Uvod u JavaScript i DOM (Document Object Model)
Uvod
U prvom članku uvodnog serijala o web dizajnu naveli smo da jezici HTML, CSS i JavaScript predstavljaju tri najosnovnija i najvažnija jezika koji se koriste u izradi web stranica, nakon čega smo se odmah upustili u proučavanje prva dva jezika, i preporučili smo čitaocima da se izučavanju jezika JavaScript posvete tek pošto dobro savladaju osnove HTML-a i CSS-a.
Ukoliko čitate ove redove, pretpostavićemo da ste savladali osnove HTML-a i CSS-a, to jest, pretpostavićemo da ste procenili da je došao trenutak da počnete da proučavate JavaScript, i stoga u nastavku sledi presek osnovnih mogućnosti ovog popularnog jezika.
Neko manje upućen, rekao bi možda da je JavaScript jezik koji se povezuje sa HTML-om, i (figurativno/u prenesenom smislu), može se reći da je 'donekle tako', ali, u pravom smislu reči, JavaScript se zapravo povezuje sa strukturom podataka koja nastaje iz HTML koda pri učitavanju dokumenta u browser, s tim da takva struktura (za razliku od HTML-a), nije obična niska znakova, već, posebno dizajnirano stablo.
Pomenuta struktura nosi naziv Document Object Model, ili skraćeno - DOM.
Document Object Model (DOM)
Sadržaj web stranica prenosi se od servera do klijenta u obliku HTML koda, međutim, koliko god tekst bio prikladan format za daljinski prenos informacija o strukturi sajta, podaci koji su neophodni za prikaz stranice, ne skladište se u browserima u izvornom (tekstualnom) obliku. *
Struktura primljenog HTML dokumenta koristi se za izgradnju strukture stabla ....

.... koje nadalje, u komunikaciji između web programera i browsera, predstavlja strukturu stranice.
U korenu DOM stabla nalazi se "dokument" (figurativno - browser), odmah ispod je čvor koji predstavlja <html>
tagove, na sledećem hijerarhijskom nivou su čvorovi koji predstavljaju tagove <head>
i <body>
, a na ostalim hijerarhijskim nivoima nalaze se ostali tagovi, poređani u raspored koji odgovara rasporedu tagova u izvornoj HTML datoteci.
Svakom čvoru pripisan je i odgovarajući sadržaj.
Da bismo iznete principe razumeli što bolje, razmotrićemo sledeći jednostavan HTML kod ....
<!DOCTYPE html>
<html>
<head>
<title>DOM Struktura</title>
<meta charset='UTF-8'>
<link rel='stylesheet' href='stil.css'/>
</head>
<body>
<h1>DOM Struktura</h1>
<p>
Prvi pasus
</p>
<p>
Drugi pasus
</p>
</body>
</html>
.... i DOM stablo koje nastaje iz prikazane HTML strukture:

Stablo sadrži sve bitne informacije iz ulaznog HTML dokumenta (tekstualni sadržaj svih tagova i vrednosti svih atributa), i - što je najvažnije - u pitanju je struktura koja omogućava znatno brži i znatno efikasniji pristup elementima.
Za pristup elementima DOM stabla (i obavljanje različitih operacija nad elementima), koristi se jezik JavaScript.
Osnove jezika JavaScript
JavaScript je skriptni programski jezik visokog nivoa koji omogućava: pristup elementima stranice (preko DOM modela), obradu (odnosno izmenu) elemenata, asinhronu komunikaciju sa serverom preko specijalizovanih XmlHttpRequest
objekata (čime ćemo se baviti u jednom od budućih članaka), kao i obavljanje brojnih drugih zadataka.
Sam jezik pojavio se sredinom devedesetih godina dvadesetog veka i u početku je nudio znatno manje mogućnosti nego danas, ali, tokom vremena mogućnosti jezika su proširivane, i JavaScript je postepeno stekao veliku popularnost (i status jedne od najvažnijih mrežnih tehnologija).
Na popularnost JavaScript-a posebno je uticala pojava radnog okruženja Node JS (cca. 2009), koje je omogućilo pokretanje desktop programa napisanih u JavaScript-u, kao i korišćenje JavaScript-a u vidu back-end tehnologije, što prethodno nije bio slučaj (JavaScript je bio jezik koji se koristi samo u browserima).
JavaScript sadrži programske strukture kakve se sreću u C-u i srodnim programskim jezicima (matematički operatori, operatori poređenja, uslovne naredbe, petlje, funkcije, objekti i sl), ali - kada se pokreće u browseru - JS ne omogućava pristup sistemskim resursima računara klijenta.
Redosled koji ćemo pratiti pri upoznavanju sa osnovama JavaScript-a je sledeći:
- povezaćemo HTML datoteku sa JS skriptom
- upoznaćemo se sa osnovnim komandama za ispis poruka i učitavanje korisničkog unosa
- razmotrićemo kako se preko pripisanog id-a pristupa elementima DOM strukture (odnosno 'HTML tagovima'), nakon čega ćemo - preko primera - sagledati kako sve funkcioniše u praksi
- upoznaćemo se ukratko sa osnovnim kontrolnim strukturama (grananja i petlje), a potom i sa funkcijama i događajima
Ostatak članka iskoristićemo za upoznavanje sa drugim metodama za pristup DOM elementima (tj. praktično, HTML tagovima), kao i drugim sitnijim 'tehnikalijama'.
Povezivanje sa HTML datotekama
Povezivanje JavaScript kodova sa HTML datotekama, tipično se obavlja preko <script>
tagova, najčešće uz navođenje naziva datoteka u kojima je zapisan Javascript programski kod (pri čemu datoteke imaju ekstenziju .js
).
<body>
<!--
Sadržaj stranice
....
-->
<script src='skripta.js'></script>
</body>
Za potrebe primera u ovom članku, tagove <script>
ćemo smestiti unutar <body>
tagova - na samom kraju (posle svih ostalih sadržaja, onako kako smo već videli).
Inače (tj. u drugim skriptama), <script>
tagovi se mogu smestiti i unutar <head>
tagova, što je zapravo pristup koji se tipično koristi (objasnićemo nešto kasnije u čemu je razlika i zašto smo za ovaj članak napravili drugačiji izbor).
Za početak (kako i dolikuje), napisaćemo "hello world" program (koji je svakako vrlo jednostavan), međutim, kada je preko JavaScript-a potrebno ispisati poruku korisniku, postavlja se pitanje - "gde će tekst biti ispisan".
Javascript nudi nekoliko opcija za ispis tekstualnih poruka, a za početak ćemo se upoznati sa "najdrastičnijom" opcijom (čim pokrenemo skriptu - razumećete na šta mislimo). :)
Ukoliko unesemo sledeći kod u JS dokument koji je povezan sa HTML datotekom (i potom pokrenemo skriptu) ....
document.write("Dobar dan! :)");
.... nećemo (naizgled) biti "prevelike sreće", jer - iako je poruka uredno ispisana - skripta je zapravo poništila prethodnu strukturu učitanog HTML dokumenta!
U praktičnom smislu (budući da je dokument ionako bio 'prazan' (skoro)), moglo bi se reći da nismo napravili grešku 'koja skupo košta', međutim, najvažnije je da iz prvog "eksperimenta" - izvučemo pouku.
Kao što smo naveli: JavaScript ima direktan pristup DOM strukturi; preko skripte koju smo napisali, direktno smo pristupili korenom elementu DOM strukture ....

.... i zadali smo (novi) sadržaj ....

.... čime je postojeći sadržaj praktično poništen.
Dakle: potrebno je da budemo pažljivi i precizni!
Ukoliko želimo da ispisujemo poruke na stranici - a pri tom ne želimo da postojeći sadržaj stranice bude "poništen" - potrebno je pristupiti određenom (konkretnom) HTML elementu na stranici - kome se potom može pripisati HTML sadržaj.
Međutim, ako je samo potrebno ispisivati "servisne poruke", postoje i drugi načini (u pitanju su opcije koje ćete koristiti prilično često).
Ispis poruka (alert i console.log)
Umesto "poništavanja" sadržaja DOM strukture (kao u prethodnom odeljku), i pre nego što razmotrimo kako se postojećim elementima može pripisivati HTML sadržaj, * razmotrićemo još i načine za slanje poruka korisniku preko funkcija alert
i console.log
.
Funkcija alert
....
alert("Dobar dan!");
.... pokreće otvaranje prozora sa porukom koja je predata kao argument, pri čemu je bitno uočiti da prozor (koji se otvara), blokira pristup elementima stranice (naravno, dok se prozor ne zatvori).
Za probu, kliknite na donje dugme:
Funkcija alert
se tipično koristi za ispis "kritičnih" poruka (poruke o sadržajima koji su nedostupni i sl), ali, u pojedinim situacijama, koristi se i za poruke opšteg tipa (na primer, ako JavaScript koristite za kreiranje igara za browser, možete korisnicima prikazivati poruke o pređenom nivou/završenoj igri i sl).
Kao što smo ranije naveli, za ispis poruka mogu se koristiti i postojeći HTML elementi na stranici; po mogućnosti, elementi koje smo unapred odredili za ispis poruka (kao što ćemo videti uskoro), ali, poruke se mogu ispisivati i u konzoli browsera, preko funkcije log
:
console.log("Dobar dan!");
Takođe, ukoliko smatramo da ne treba o greškama direktno obavestiti korisnika preko funkcije alert
- ali smatramo da je potrebno na drugi način prikazati informaciju o tome da je do greške došlo - poruke o greškama se mogu proslediti i preko konzole:
console.error("Opcija je dostupna samo na mobilnim uređajima!");
Razlika u odnosu na funkciju console.log
je u tome što se poruka koja je ispisana preko funkcije console.error
formatira crvenom bojom (tamno crvena slova i crveni okvir).
Za isprobavanje funkcija console.log
i console.error
, možete iskoristiti donje dugme:
(Nemojte zaboraviti da otvorite konzolu (preko prečice F12
), da biste mogli da vidite rezultat.)
Učitavanje korisničkog unosa (prompt)
Ukoliko je potrebno da korisnik unese podatke u skriptu, učitavanje se tipično obavlja preko funkcije prompt
, koja iscrtava prozor sa poljem za korisnički unos (a korisnički unos se potom može učitavati u promenljive).
Pogledajmo primer:
var ime = prompt("Unesite korisničko ime:");
alert("Korisnik je uneo sledeće ime: " + ime);
Za isprobavanje primera, kliknite na donje dugme:
Kao što vidimo, povratna vrednost funkcije prompt
je niska - koja se predaje promenljivoj koju smo sami deklarisali. *
Postoje (naravno) i drugi načini za unos podataka, ** ali, to ćemo ostaviti za neku drugu priliku.
Nakon isprobavanja, vreme je da počnemo da povezujemo JS skripte sa elementima stranice (preko DOM stabla). :)
Pristup DOM elementima preko id-a (getElementById)
Najuobičajeniji način pristupa elementima, podrazumeva upotrebu pripisanih id-ova, ali, budući da elementi koje smo prethodno definisali nemaju pripisane id-ove, to je prvo što ćemo prepraviti ....
<body>
<h1>DOM Struktura</h1>
<p id='prvi_pasus'>
Prvi pasus
</p>
<p id='drugi_paus'>
Drugi pasus
</p>
</body>
.... pri čemu će se i DOM struktura takođe promeniti (prikazujemo samo jedan pasus):

Sada se elementima može direktno pristupati preko JavaScript-a, što možemo prikazati na primeru naredbe preko koje se pristupa prvom pasusu:
document.getElementById("prvi_pasus").innerHTML = "Dobar dan! :) Ovo je prvi pasus.";
Koristili smo u svemu svojstvo innerHTML
i može se reći * da uneti tekst praktično predstavlja HTML kod (mogu se direktno pisati HTML tagovi, čime se definiše struktura elemenata kojima se pristupa), međutim, u ozbiljnijim i 'zvaničnijim' skriptama, preporučljivo je koristiti funkcije createElement
i appendChild
pri dodavanju novih elemenata u DOM stablo. *
Da bismo što bolje razumeli kako pristup elementima stranice funkcioniše u praksi, razmotrićemo jedan jednostavan primer, preko koga ćemo se upoznati i sa promenljivama u JS-u (a upoznaćemo se okvirno i sa kontrolnim strukturama jezika). **
Promenljive (var) i primer pristupa elementima stranice
Primer koji ćemo prikazati, podrazumeva dodavanje <div>
elemenata u DOM stablo, ali, budući da već znamo da prazni <div>
elementi nemaju "pojavni oblik" (sami po sebi), dodaćemo prvo prigodan selektor u datoteku stil.css
: *
.plavi_pasus {
width: 120px;
height: 120px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: #7788ee;
color: #fff;
font-family; Arial, sans-serif;
font-size: 18pt;
margin: 0 12px 0 0;
}
.... posle čega se možemo vratiti na JavaScript i uneti sledeće izmene:
var i;
var brojPasusa = 4;
var sadrzajPasusa = "";
for (i = 1; i <= brojPasusa; i++) {
sadrzajPasusa += "
<div class='plavi_pasus'>" + i + "</div>
\n";
}
document.getElementById("prvi_pasus").innerHTML = sadrzajPasusa;
Promenljive se definišu preko rezervisane reči var
, ** a iz priloženog se može naslutiti i to da JavaScript spada u kategoriju jezika sa dinamičkom tipizacijom (pri deklaraciji promenljivih, ne navodi se tip promenljive, već se tip određuje automatski pri prvoj naredbi dodele).
Možemo takođe zapaziti i vrlo "liberalno" povezivanje: string konstanti (običnog teksta koji je 'ručno' ispisan u programskom kodu), i vrednosti promenljivih brojčanog tipa (mislimo pri tom na sledeći odeljak iz gornjeg primera):
sadrzajPasusa += "<div class='plavi_pasus'>" + i + "</div>\n";
U toku izvršavanja skripte (to jest, u situacijama kada se ukaže potreba), vrednosti brojčanih promenljivih se automatski pretvaraju u tekst - što nije slučaj sa većinom drugih jezika (koji zahtevaju da se komanda za pretvaranje broja u nisku navede eksplicitno).
Pre nego što nastavimo, pogledaćemo kako primer koji smo prethodno definisali funkcioniše u praksi (kliknite na dugme):
Preko primera koji smo prethodno razmotrili, videli smo na delu izvestan broj naredbi i for
petlju, a u nastavku ćemo se detaljnije upoznati i sa ostalim najčešće korišćenim kontrolnim strukturama.
Kontrolne strukture jezika (grananja i petlje)
Kao i u drugim programskim jezicima, grananja i petlje omogućavaju:
- preusmeravanje toka programskih instrukcija shodno zadatim uslovima (grananja)
- ciklično ponavljanje određenih naredbi (petlje)
Grananje - if
Grananja u JavaScript-u (kao i u većini drugih programskih jezika), podrazumevaju prelazak na jedan od dva moguća * bloka naredbi - shodno postavljenom uslovu.
Prikazaćemo primer preko koga se proverava da li je uneti broj veći od nule (sa posebnim ispisima za situacije kada korisnik unese: pozitivan broj, nulu ili negativnu vrednost).
if (a > 0) {
console.log("Broj je veći od 0.")
}
else {
if (a == 0) {
console.log("Uneli ste nulu.")
}
else {
console.log("Broj je manji od 0.")
}
}
Primer takođe prikazuje da je uslove moguće i "ugnežđavati".
Za razliku od jednostavnog ugnežđavanja (sa kakvim smo se sreli u prethodnom primeru), višestruko ugnežđavanje, koje bi bilo zapisano po istom principu - ni iz daleka ne predstavlja pregledan programski kod.
Za situacije kada je potrebno "ugnežđavati" više uslova, JavaScript nudi mogućnost korišćenja konstrukcije else if
, preko koje se ugneždavanje svodi (u sintaksičkom smislu), na nadovezivanje.
Uzmimo za primer skriptu koja treba da ispiše ocenu (od 1 do 5), shodno unetom broju bodova (u rasponu od 0 do 100):
let bodovi = 92;
if (bodovi < 50) {
console.log("Ocena: 1")
}
else if (bodovi < 65) {
console.log("Ocena: 2")
}
else if (bodovi < 75) {
console.log("Ocena: 3")
}
else if (bodovi < 85) {
console.log("Ocena: 4")
}
else {
console.log("Ocena: 5")
}
Međutim, u situacijama kada se ispituje striktno poklapanje sa jednom vrednošću, tipično se koristi konstrukcija switch
.
Grananje - switch
Shodno svom "C-ovskom sintaksičkom poreklu", JavaScript nudi mogućnost korišćenja konstrukcije switch
, koja se tipično koristi za uparivanje pojedinačnih uslova - i instrukcija koje je potrebno izvršiti (naravno, ako je neki od uslova zadovoljen).
Kao primer, razmotrićemo switch
grananje koje, za uneti broj, ispisuje dan u nedelji koji odgovara unetom broju (ili poruku o grešci, ukoliko se unese broj koji je manji od 1 ili veći od 7):
let a = 3;
switch (a) {
case 1: console.log("Ponedeljak"); break;
case 2: console.log("Utorak"); break;
case 3: console.log("Sreda"); break;
case 4: console.log("Četvrtak"); break;
case 5: console.log("Petak"); break;
case 6: console.log("Subota"); break;
case 7: console.log("Nedelja"); break;
default:
console.error("Broj ne predstavlja dan u nedelji");
break;
}
// Ispis je: "Sreda"
Petlja - while
Petlja while
pokreće blok sa programskim instrukcijama - sve dok je zadati uslov zadovoljen:
- ukoliko je uslov zadovoljen, ulazi se u ciklus petlje
- izvršava se blok naredbi
- po završetku bloka naredbi - skripta se vraća na proveru uslova
Za primer ćemo uzeti petlju koja ispisuje brojeve u rasponu od 1 do n.
let i = 1;
let n = 10;
while (i <= n) {
console.log("i = " + i);
++i; // korekcija
}
U praktičnom smislu, veoma je bitno da se unutar petlje pojavi naredba preko koje se koriguje vrednost promenljive koja je deo uslova (tako da u prigodnom trenutku uslov prestane da važi), jer - u suprotnom - nastaje "beskonačna petlja"!
Ukoliko je potrebno prekinuti izvršavanje ciklusa - pre nego što osnovni uslov poprimi vrednost false
- koristi se naredba break
(pogledajmo primer):
let i = 1; // brojač
let n = 10; // maksimalni broj učitavanja
let s = 0; // suma
let x; // pojedinačna vrednost
// koja se učitava
let g = 10000; // granica (koja se ne sme prekoračiti)
while (i <= n) {
let ulaz = prompt ("Unesite vrednost:");
x = parseInt(ulaz);
let p = g - s; // kontrolna vrednost
if (x > p) break; // rana terminacija -
// shodno uslovu
s += x; // ukoliko nije ispunjen uslov
// za "prerani prekid", suma se
// uvećava za x
++i; // korekcija
}
console.log(s);
Primer koji smo prikazali predstavlja petlju koja se izvršava n
puta, pri čemu se u svakom ciklusu učitava vrednost (x
) i dodaje na sumu (s
), ali - samo pod uslovom da dodavanjem vrednosti neće biti prekoračena unapred zadata kontrolna vrednost, tj. 'granica' (promenljiva g
).
Petlja - do-while
Petlja do-while
, naizgled je slična "običnoj" while
petlji (sa kojom smo se upoznali u prethodnom odeljku), a razlika je u tome što se ovoga puta bezuslovno ulazi u prvi ciklus petlje.
Naravno, po izvršavanju ciklusa, ispituje se uslov, i - ukoliko je uslov zadovoljen - ponovo se ulazi u ciklus petlje (i postupak se ponavlja).
Za primer možemo uzeti do-while
petlju u okviru koje korisnik unosi brojčanu vrednost, sve dok ne pogodi zamišljeni broj (u rasponu od 1 do 1024):
let g = 1024;
let n = parseInt(Math.random() * g) + 1
let broj = -1;
let unos;
do {
unos = prompt("Unesite broj:");
broj = parseInt(unos)
if (broj < n) {
console.log("Uneti broj je manji od zamišljenog broja.");
}
if (broj > n) {
console.log("Unesti broj je veći od zamišljenog broja.")
}
}
while (broj != n);
alert("Čestitamo! Pogodili ste zamišljeni broj! :)");
Za isprobavanje primera, kliknite na donje dugme:
Primer koji smo videli ne spada (naravno) u kategoriju programa koji pomažu u rešavanju svakodnevnih zadataka, ali, sasvim uspešno prikazuje zašto je uputno da programski jezici raspolažu strukturom petlje koja omogućava da se blok naredbi izvrši "bar jednom" (uz ispitivanje uslova na kraju svakog ciklusa).
Takođe, dodatno smo isprobali naredbu prompt
i upoznali se sa naredbom parseInt
preko koje se niska pretvara u celobrojnu vrednost (naravno, pod uslovom da je format niske odgovarajući).
Petlja - for
Petlja for
predstavlja (kao i u drugim jezicima), praktičan način za organizaciju ciklusa koji se temelje na određenom broju ponavljanja (pri čemu je broj ponavljanja vrlo često poznat unapred).
Opšta šema for
petlje može se opisati na sledeći način:
for (inicijalizacija; uslov; korekcija) {
naredbe ....
}
U praktičnom smislu - for
petlja je isto što i while
petlja - "zapisana na malo drugačiji način".
Pri upotrebi bilo koje pravilno definisane while
petlje, podrazumeva se da je promenljiva od čije vrednosti zavisi izvršavanje petlje inicijalizovana pre ulaska u petlju, a posebno se podrazumeva da unutar tela petlje mora postojati naredba preko koje se vrednost navedene promenljive koriguje.
Na primeru while
petlje sa slike #19 (ispis brojeva od 1 do n) ....
// Inicijalizacija promenljivih:
let i = 1;
let n = 10;
// Uslov za ulazak u petlju:
while (i <= n) {
// Naredbe opšteg tipa:
console.log("i = " + i);
// Korekcija:
++i;
}
.... možemo zapaziti da je promenljiva i
inicijalizovana pre ulaska u petlju (isto važi i za promenljivu n
), * i možemo zapaziti da u telu petlje postoji naredba preko koje se vrednost promenljive i
menja (u pitanju je naredba na kraju tela petlje: ++i
).
Preko for
petlje, sve što smo naveli - zapisuje se "u jednom redu".
Ako ponovo za primer uzmemo program koji ispisuje vrednosti od 1 do n, možemo definisati sledeću for
petlju:
const n = 10;
for (let i = 1; i <= n; ++i) {
console.log("i = " + i);
}
Na ovom mestu, vraćamo se na specifičnosti JavaScript-a (to jest, na primer sa generisanjem HTML koda, koji smo prethodno razmatrali).
Pažljivijim sagledavanjem primera, mogli bismo zaključiti da se JS kod koji je zapisan izvan funkcija poziva pri pokretanju skripte (svaki put), što može biti upravo ono što želimo da izvedemo, ali - može biti i nešto što je potrebno izbeći.
Kod koji je zapisan unutar funkcije, izvršava se samo kada se funkcija pozove, a možemo (naravno) udesiti i to da se pozivi funkcija poklope sa određenim 'događajima' na stranici.
Događaji (events) i funkcije
Događaji (u programiranju) se najpraktičnije mogu shvatiti kao pojave koja imaju uticaj na dalji tok izvršavanja programa (npr. "korisnik je pritisnuo levi taster miša", "korisnik je pritisnuo taster na tastaturi", "tajmer je istekao", "prozor je otvoren/zatvoren" i sl), pri čemu programski jezici omogućavaju da se na takve pojave reaguje pokretanjem odgovarajućeg programskog koda.
U JavaScript-u, određeni HTML element se povezuje sa "osluškivačem događaja" (eventListener
), nakon čega se pokreće akcija vezana za dati događaj (eventHandler
).
Postoji nekoliko načina za povezivanje HTML elemenata sa događajima u JavaScript-u, ali, za početak ćemo se zadržati na dva osnovna načina (prvi način se može smatrati "lakšim", na početku, dok se drugi način može smatrati "zvaničnim").
Za primer ćemo uzeti tipičnu situaciju u kojoj je potrebno pokrenuti određene naredbe kada korisnik klikne na dugme ....
"Lakši način" (tzv. inline event handler), podrazumeva da se registracija događaja obavlja preko HTML atributa na samom HTML elementu:
<body>
<p>
Prvi pasus
</p>
<p>
Drugi pasus
</p>
<button onclick='dodavanjePasusa()'>KLIK</button>
</body>
"Zvaničan" način podrazumeva da se sav kod (koji se tiče povezivanja) - premešta u JS datoteku.
Ovoga puta, neophodno je da HTML dugmetu bude pripisan odgovarajući id:
<button id="dugme_1">KLIK</button>
Kao što smo naveli, JavaScript kod se tipično navodi u spoljnoj datoteci:
let dugme_1 = document.getElementById("dugme_1");
// konkretan primer:
dugme_1.addEventListener("click", dodavanjePasusa);
// Opšti princip:
// element.addEventListener(događaj, funkcija_za_obradu);
U konkretnom primeru (bez obzira da li se primenjuje prvi ili drugi metod povezivanja): * svaki put kad korisnik klikne na dugme, biće pozvana funkcija dodavanjePasusa
.
U svakom slučaju, da bi "klik" imao (pravog) efekta, unutar skripte je potrebno definisati funkciju dodavanjePasusa
(pri čemu ćemo premestiti celokupan kod koji smo ranije definisali - u telo nove funkcije):
function dodavanjePasusa() {
let i;
let brojPasusa = 4;
let sadrzajPasusa = "";
for (i = 1; i <= brojPasusa; i++) {
sadrzajPasusa += "
<div class='plavi_pasus'>" + i + "</div>
\n";
}
document.getElementById("prvi_pasus").innerHTML = sadrzajPasusa;
}
Kada je u pitanju opšti princip definisanja funkcija, primećujemo (očekivano), očiglednu sličnost sa programskim jezikom C, s tim da kod nije istovetan (na mestu gde se u C-u ili C++-u pojavljuje tip podatka koji funkcija vraća, u JavaScript-u se pojavljuje rezervisana reči function
).
Funkcije koje vraćaju vrednosti i/ili primaju argumente, takođe se definišu i pozivaju slično kao u C-u, ali, sa tom razlikom što se parametri navode samo imenom, bez navođenja tipa podatka. *
function maks(a, b) {
return (a > b)? a : b,
}
let a = 15;
let b = 10;
let m = maks(a, b);
console.log(m); // Ispis je: 15
U svakom slučaju, skripta koju smo prethodno napisali, sada je spremna, i neće se pokretati "sama od sebe" (već samo onda kada kliknemo na dugme).
Pozicija script tagova unutar HTML dokumenta
Pozicija <script>
tagova unutar HTML dokumenta - i te kako ima uticaja na korektnost izvršavanja JS koda, budući da se HTML tagovi učitavaju redom, što (razume se) važi i za <script>
tagove, odnosno, za JS kod koji se učitava preko <script>
tagova - i izvršava se odmah po učitavanju.
Ako bismo u gornjim primerima (u kojima se koristi funkcija getElementById
), tagove <script>
smestili unutar tagova <head>
....
<head>
<!-- mesto na koje dolaze meta tagovi i sl -->
<script src='skripta.js'></script>
</head>
<body>
<!--
Pasus sa id-om "prvi pasus" pojavljuje se
'posle' script taga (zajedno sa ostalim
tagovima koji čine sadržaj tela stranice).
-->
</body>
.... JavaScript kod bi bio učitan i pokrenut odmah (budući da je zapisan izvan funkcija), i stoga bi sledeća naredba (sa kojom smo se sretali u ranijim primerima) ....
document.getElementById("prvi_pasus")
.... praktično tražila element koji (još uvek) ne postoji!
Dakle: ako se funkcija getElementById
poziva unutar programskog koda koji se automatski pokreće pri učitavanju stranice, takav kod mora se pojaviti posle HTML koda kojim se definiše traženi element (u većini situacija je najpraktičnije da to bude - onako kako smo videli - na samom kraju unutar <body>
tagova).
Pred kraj uvodnog članka, prikazaćemo i ostale načine za pronalaženje elemenata DOM stabla.
Pristup DOM elementima preko CSS selektora (querySelector i querySelectorAll)
Preko funkcije querySelectorAll
....
document.querySelectorAll("div > img.slika_sa_okvirom")
.... mogu se pronaći svi elementi unutar DOM stabla na koje se odnosi selektor koji je (u obliku niske) predat kao argument.
Međutim, budući da može postojati više elemenata na koje se zadati selektor odnosi, pristup elementima nije jednostavan kao u slučaju kada se (samo jedan) element traži preko id-a.
Funkcija getElementById
vraća jedan objekat (sada znamo zašto je veoma bitno da id bude jedinstven (!)), dok naredba querySelectorAll
vraća listu elemenata koji odgovaraju kriterijumu pretrage, i stoga se mora koristiti i drugačiji mehanizam za pristup pojedinačnim elementima:
var slike = document.querySelectorAll("div > img.slika_sa_okvirom");
var i;
for (i = 0; i < slike.length; i++) {
slike[i].style.border = "solid 2px #77ee88";
}
Objekat slike
je referenca na listu pronađenih elemenata (koji odgovaraju prethodno navedenom CSS selektoru), pri čemu se lista kreira bez obzira na to da li elementi na koje se selektor odnosi, postoje, ili ne postoje:
- kada nema elemenata za koje selektor važi, lista je prazna
- kada postoji samo jedan element za koji selektor važi, lista sadrži jedan element (neće biti vraćen 'običan' pojedinačni objekat)
- kada postoji više elemenata za koje selektor važi, lista sadrži više elemenata
Ukoliko smo sigurni da postoji samo jedan element koji može biti pronađen, elementu se može pristupiti na jednostavniji način:
var slika = document.querySelector("div > img.slika_sa_okvirom");
Funkcija querySelector
vraća pojedinačni objekat (ovoga puta nije u pitanju lista), a čak i ako se pređemo sa ovakvim pristupom, neće biti "strašno":
- ukoliko ne postoji nijedan element koji odgovara navedenom selektoru, objekat
slika
imaće vrednostnull
- ukoliko postoji više elemenata koji odgovaraju selektoru, biće izabran prvi
Naravno, na nama je da pazimo da ne dođemo u situaciju #2 ako nam trebaju svi elementi (a ne samo jedan tj. prvi element), ili, drugim rečima: moramo biti sigurni da pozivamo selektor koji se odnosi na jedinstveni objekat. :)
Pristup DOM elementima preko pripisane klase (getElementsByClass)
Za pristup elementima preko pripisane klase, može se koristiti funkcija getElementsByClass
. *
Sledeći kod:
var nav_linkovi = document.getElementsByClass("nav_linkovi");
.... pronalazi sve elemente kojima je pripisana klasa nav_linkovi
i potom kreira listu (koja se takođe može obraditi onako kako smo videli u prethodnom odeljku).
Pristup DOM elementima preko opštih tagova (getElementsByTagName)
Pored metoda koje smo do sada prikazali, elementima se može pristupati i preko opštih odrednica za tagove, preko naredbe getElementsByTagName
.
Sledeći kod:
var naslovi_h2 = document.getElementsByTagName("h2");
.... pronalazi sve h2
naslove unutar dokumenta, i potom kreira listu kojoj se može pristupati na način koji je ranije opisan (takođe: i ovoga puta se isti efekat može postići korišćenjem naredbe querySelectorAll
).
Sledeći koraci ....
Opcije koje smo prikazali u članku, predstavljaju (kao što možete pretpostaviti), samo mali deo onog što JavaScript nudi, pogotovo posle nekoliko najnovijih revizija jezika.
U člancima koje pripremamo za blisku budućnost, pisaćemo o okruženju Node JS, o ES6 sintaksi, kao i o mnogim drugim temama koje su vezane za JavaScript.
Do tada: ....