nav_dugme codeBlog codeBlog
  • početna Početna stranica
  • Sačuvani članci Sačuvani članci
  • Učionica
  • Saveti
  • Zanimljivosti
  • Kontakt

Uvod u Javascript i DOM (Document Object Model)

Viber
zoom_plus zoom_minus bookmark

Uvod

Pomenuli smo u prvom članku uvodnog serijala o web dizajnu da jezici HTML, CSS i Javascript čine svojevrsno "sveto trojstvo" internet jezika, odmah se upustili u proučavanje prva dva jezika i čitaocima preporučili da se izučavanju Javascript-a 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 i da je došao trenutak da počnete da proučavate Javascript, pa ćemo u nastavku napraviti presek osnovnih mogućnosti ovog 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žemo reći da je 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 naravno 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 način za daljinski prenos informacije o strukturi sajta, browseri ne skladište podatke neophodne za prikaz stranice u izvornom obliku.

Umesto toga, HTML kod se koristi za izgradnju strukture stabla koje predstavlja strukturu stranice:

Dom Struktura
Slika 1. - Uprošćena DOM struktura (bez sadržaja i atributa). Struktura čvorova odgovara ugnežđenoj strukturi HTML tagova.

U korenu navedenog stabla nalazi se sam dokument (figurativno - browser), odmah ispod je čvor koji predstavlja <html> tagove, direktno ispod su čvorovi koji predstavljaju tagove <head> i <body> i tako redom, do nižih nivoa hijerarhije, to jest, do čvorova koji nemaju potomke.

Svakom čvoru pripisan je i odgovarajući sadržaj.

Da bismo sve to 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>
		
	
Slika 2. - HTML struktura koju ćemo koristiti u članku.

.... i DOM stablo koje nastaje iz prikazane HTML strukture:

Dom Struktura
Slika 3. - DOM stablo koje odgovara prethodno navedenoj HTML strukturi.

Stablo sadrži celokupnu strukturu dokumenta (tekstualni sadržaj svih tagova i vrednosti svih atributa) i što je najvažnije - ovakva struktura omogućava znatno brži i efikasniji pristup elementima.

Programski jezik preko koga se pristupa elementima unutar DOM stabla i preko koga se obavljaju različite operacije nad elementima je (kao što već znate) - Javascript.

Zarad opšte računarske pismenosti (i budući da ovo pišemo u okviru uvodnog članka o Javascript-u), pomenućemo da - osim imena - Javascript nema dodirnih tačaka sa popularnim jezikom Java.

Osnove jezika Javascript

Javascript je skriptni programski jezik visokog nivoa koji (preko DOM modela), omogućava pristup elementima stranice, obradu (odnosno izmenu) elemenata, asinhronu komunikaciju sa serverom preko specijalizovanih XmlHttpRequest objekata (time ćemo se ipak baviti u nekom od budućih članaka), kao i obavljanje brojnih drugih zadataka.

Ovaj jezik pojavio se sredinom devedesetih godina dvadesetog veka i u početku je nudio znatno manje mogućnosti nego danas, ali su tokom vremena mogućnosti jezika proširivane i Javascript je stekao veliku popularnost.

Na popularnost Javascript-a posebno je uticala pojava radnog okruženja Node JS (cca. 2009), koje je omogućilo pokretanje desktop aplikacija napisanih u Javascript-u (što prethodno nije bio slučaj; Javascript je bio isključivo web jezik).

Kada kažemo da je u pitanju skriptni jezik, mislimo na njegovu osobinu da se izvršava "instrukciju-po-instrukciju" (onda kada zatreba), za razliku od programskih jezika kakvi su recimo C i C++, kod kojih se napisani programski kod prvo kompajlira, posle čega se kreira izvršna datoteka.

Javascript sadrži kontrolne strukture kakve srećemo u C-u i srodnim programskim jezicima (matematičke operatore, operatore poređenja, uslovne naredbe, petlje, funkcije, objekte), ali - kada se pokreće u browseru - JS ne omogućava pristup sistemskim resursima računara klijenta.

Javascript se sa HTML datotekama povezuje preko <script> tagova (datoteke u kojima čuvamo skripte koje pišemo preko jezika Javascript, imaju ekstenziju .js):

		
<body>
	<!--
		Sadržaj stranice
		....
	-->

	<script src='skripta.js'></script>
</body>
		
	
Slika 4. - Preko "script" tagova definišemo vezu između HTML dokumenta i jezika Javascript.

Javascript kod možemo pisati i unutar <script> tagova, ali, koristićemo (kao i za CSS) elegantniji pristup, koji podrazumeva da se JS kod zapisuje u zasebnoj datoteci (jednoj ili više).

Tagove <script> ćemo za potrebe primera u ovom članku smestiti unutar <body> tagova, na samom kraju (posle svih ostalih sadržaja, onako kako smo već videli).

Inače se <script> tagovi mogu smestiti i unutar <head> tagova (što je zapravo pristup koji se tipično koristi, ali, objasnićemo u nastavku u čemu je razlika i zašto smo za ovaj članak napravili drugačiji izbor).

Za početak (kako i dolikuje), "hello world" program. Ukoliko unutar JS dokumenta koji smo povezali sa HTML datotekom unesemo sledeći kod:

		
document.write("Dobar dan!");
		
	
Slika 5. - JS komanda write - komanda za upis sadržaja u određeni čvor DOM stabla. Moramo (u opštem smislu) biti pažljivi, budući da poziv document.write() praktično podrazumeva pristup korenom čvoru, pa će ceo dokument biti izbrisan!

.... nećemo se previše "usrećiti", jer će skripta poništiti strukturu već učitanog HTML dokumenta (ali će bar uredno ispisati pozdravnu poruku). :)

Javascript (kao što smo nagovestili) ima pristup DOM strukturi, a preko skripte koju smo napisali, direktno smo pristupili korenom elementu DOM strukture i zadali sadržaj (čime je poništen postojeći sadržaj), ali to što se desilo je samo pouka i sada znamo da je potrebno da budemo precizniji (to jest, da moramo izabrati konkretan HTML element na stranici, kome potom možemo pripisati određeni sadržaj).

Međutim, ako samo želimo da ispisujemo poruke, postoje i drugi načini.

Ispis poruka (alert i console.log)

Umesto "poništavanja" sadržaja DOM strukture (kao u prethodnom odeljku) i pre nego što razmotrimo kako se poruke mogu prosleđivati postojećim HTML elementima (zapravo - kako se postojećim elementima može pripisati određeni HTML sadržaj), razmotrićemo još i načine slanja poruka korisniku preko funkcija alert i console.log.

Funkcija alert ....

		
alert("Dobar dan!");
		
	
Slika 6. - Komanda alert, preko koje se prikazuje prozor sa porukom.

.... poziva 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 ga ne zatvorimo).

Za probu, kliknite na donje dugme:

Funkcija alert tipično se koristi za ispis "kritičnih" poruka (poruke o sadržajima koji su nedostupni i sl), ali se u pojedinim situacijama koristi i za poruke opšteg tipa (na primer, ako Javascript koristite za kreiranje igara za browser, možete korisnicima slati poruke o pređenom nivou/igri i sl).

Bitno je samo zadržati se u granicama dobrog ukusa i ne "izbacivati" poruke korisnicima "za svaku sitnicu" (nikako ne treba zaboraviti da korisnici u većini situacija imaju izbor da ne posećuju sajtove koji im dosađuju).

Za ispis poruka mogu se koristiti i postojeći HTML elementi na stranici (kao što ćemo videti u sledećem odeljku), po mogućnosti oni koje smo unapred odredili za ipis poruka, ali se poruke mogu slati i u konzolu browsera, preko funkcije log:

		
console.log("Dobar dan!");
		
	
Slika 7. - Komanda console.log, preko koje se u konzoli browsera ispisuje poruka korisniku.

Greške se mogu (ukoliko smatramo da o njima ne treba direktno obavestiti korisnika preko funkcije alert - ali da je potrebno da postoji informacija o tome da je do greške došlo), proslediti i preko konzole:

		
console.error("Opcija je dostupna samo na mobilnim uređajima!");
		
	
Slika 8. - Komanda console.error - funkcionalnost je slična kao u slučaju komande console.log, s tom razlikom što je poruka uokvirena crvenom bojom.

Razlika u odnosu na funkciju console.log je u tome što je poruka ispisana preko funkcije console.error formatirana 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, da biste mogli da vidite rezultat.)

Pristup DOM elementima preko id-a (getElementById)

Verovatno najkorišćeniji način pristupa elementima podrazumeva pristup preko pripisanih id-ova (a budući da elementi koje smo prethodno definisali nemaju pripisan id, 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>
		
	
Slika 9. - Pripisivanje id-ova HTML elementima (neophodan preduslov za pristupanje elementima preko Javascript-a).

.... pri čemu će se i DOM struktura takođe promeniti (prikazujemo samo jedan pasus):

DOM Struktura
Slika 10. - Delimična DOM struktura izmenjenog dokumenta (sa id-om pripisanim p elementu).

Sada možemo pristupiti (na primer) prvom pasusu:

		
document.getElementById("prvi_pasus").innerHTML = "Dobar dan! :) Ovo je prvi pasus.";
		
	
Slika 11. - Pristup elementu preko id-a.

Koristili smo u svemu svojstvo innerHTML i zaista, ono što unosimo je HTML (možemo direktno unositi HTML tagove i time redefinisati strukturu elemenata kojima pristupamo)

Da bismo to što bolje razumeli, razmotrićemo još jedan jednostavan primer, preko koga ćemo se upoznati i sa kontrolnim strukturama jezika i upotrebom promenljivih.

Kontrolne strukture Javascript jezika i promenljive (var)

Pre nego što se upoznamo sa navedenim elementima jezika, dodaćemo sadržaj u datoteku "stil.css" (da se podsetimo, u HTML primeru koji koristimo već je naveden tag <link>, za povezivanje sa CSS-om):

		
.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;
}
		
	
Slika 12. - CSS klasa na koju ćemo se pozivati u nastavku (u opštem smislu, ukoliko je klasa definisana u CSS dokumentu, možemo se na nju pozvati preko Javascript-a).

.... 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;
		
	
Slika 13. - Javascript na delu: globalne promenljive (var), kontrolne strukture (for) i pristup elementima (document.getElementById).

Promenljive se definišu preko rezervisane reči var, a Javascript je, kao što možemo videti, jezik sa dinamičkom tipizacijom (pri deklaraciji promenljivih se ne zadaje tip promenljive, već se tip određuje automatski pri prvoj naredbi dodele).

Postoji i moderniji način, preko rezervisanih reči let i const (koje ćemo posle uvodnog članka početi da koristimo), ali ćemo u uvodnom članku koristiti rezervisanu reč var.

Sledeće što možemo zapaziti je vrlo "liberalno" povezivanje string konstanti (običnog teksta koji smo mi sami ispisali) i vrednosti promenljivih brojevnog tipa, koje se u toku izvršavanja skripte automatski pretvaraju u tekst (mislimo pri tom na sledeći odeljak):

		
sadrzajPasusa += "<div class='plavi_pasus'>" + i + "</div>\n";
		
	
Slika 14. - Definisanje novog sadržaja na način koji praktično podrazumeva pisanje HTML koda unutar Javascript-a.

.... što nije slučaj sa većinom drugih jezika, gde se komanda za pretvaranje broja u nisku mora eksplicitno navesti.

U Javascript-u, vrednosti promenljivih i izraza se mogu umetati u niske i na elegantniji način, preko tzv. šablonskih niski, ali, to će takođe biti tema za neki od članaka u (bliskoj) budućnosti.

Pre nego što nastavimo, pogledaćemo kako primer koji smo prethodno definisali funkcioniše u praksi (kliknite na dugme):

JS kod koji je zapisan izvan funkcija poziva se (svaki put) pri pokretanju skripte, što može biti upravo ono što želimo da izvedemo, a može biti i nešto što želimo da izbegnemo.

Kod zapisan unutar funkcija izvršava se samo kada funkcije pozovemo, a naravno možemo udesiti i da se pozivi funkcija poklope sa određenim događajima na stranici.

Događaji (events) i funkcije

Za primer ćemo uzeti tipičnu situaciju u kojoj je određeni blok programskog koda potrebno pokrenuti kada korisnik klikne na dugme (što će biti registrovano preko događaja onclick):

		
<body>
	<p>
		Prvi pasus
	</p>
	
	<p>
		Drugi pasus
	</p>
	<button onclick='dodavanjePasusa()'>KLIK</button>
</body>
		
	
Slika 15. - Povezivanje Javascript događaja (onclick) sa HTML elementom, koje podrazumeva poziv funkcije (dodavanjePasusa).

U konkretnom primeru, svaki put kad korisnik klikne na dugme biće pozvana funkcija dodavanjePasusa.

Da bi klik imao pravog efekta, u skripti ćemo definisati funkciju dodavanjePasusa i u telo funkcije premestiti celokupan kod koji smo prethodno definisali:

		
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;
}
		
	
Slika 16. - Definicija funkcija dodavanjePasusa na koju smo se prethodno pozivali.

Sada je kod spreman i neće se pokretati sam od sebe (već samo onda kada kliknemo na dugme).

Ovoga puta, koristili smo za deklaraciju promenljivih rezervisanu reč let (umesto var). Praktična razlika u ovom slučaju skoro da ne postoji, a više o razlikama između var i let deklaracije možete pročitati u članku koji smo posvetili novinama koje su uvedene sa revizijom Javascript-a ECMAScript 2015 (koja je popularnija pod skraćenicom ES6).

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 važi i za kod učitan preko <script> tagova koji se izvršava odmah po učitavanju (spoljne JS datoteke se u tom smislu tretiraju kao kod koji je direktno upisan unutar <script> tagova).

Da smo u gornjim primerima, koji koriste funkciju getElementById, tagove <script> smeštali unutar tagova <head>, Javascript kod bi bio učitan i pokrenut odmah (budući da je zapisan izvan funkcija), pa bi sledeća naredba ....

		
document.getElementById("prvi_pasus")
		
	
Slika 17. - Odeljak JS koda koji traži element shodno navedenom id-u (ali ga ne nalazi, budući da DOM struktura elementa body nije kreirana, s obzirom na to da smo JS pozvali na početku HTML dokumenta, unutar head tagova).

.... praktično pozivala element koji ne postoji!

U praksi, element se u DOM stablu (tipično) pojavi za manje od 1ms, ali svejedno ("onda kad smo ga tražili" - nije ga bilo). :)

Međutim, ako skripta ne sadrži kod koji se pokreće automatski (već samo funkcije vezane za događaje i sl), deluje preglednije da se script tagovi smeste unutar head tagova.

Dakle: ako pozivamo funkciju getElementById unutar koda koji se automatski pokreće pri učitavanju stranice, takav kod mora se pojaviti posle HTML koda kojim se definiše objekat (u većini situacije je najpraktičnije da to bude - onako kako smo videli - na samom kraju unutar <body> tagova).

Pogledaćemo i ostale načine pristupa elementima DOM stabla.

Pristup DOM elementima preko CSS selektora (querySelector i querySelectorAll)

Preko funkcije querySelectorAll ....

		
document.querySelectorAll("div > img.slika_sa_okvirom")
		
	
Slika 18. - Naredba querySelectorAll - univerzalan i veoma koristan način za pronalaženje elemenata.

.... možemo unutar DOM stabla pronaći sve elemente na koje se odnosi selektor koji je u obliku niske predat kao argument (u gornjem primeru, selektor se odnosi na sve img tagove sa klasom slika_sa_okvirom koji se nalaze direktno unutar div tagova). Međutim, budući da takvih elemenata može biti više, pristup elementima nije jednostavan kao u slučaju kada smo (jedan) element tražili preko id-a.

Funkcija getElementById vraća jedan objekat (sada znamo zašto je jako bitno da id bude jedinstven!), dok naredba querySelectorAll vraća listu elemenata koji odgovaraju kriterijumu pretrage, pa se mora koristiti i malo drugačiji mehanizam pristupa:

		
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";
}
		
	
Slika 19. - Način pristupa pojedinačnim elementima i lista koja nastaje posle pozivanja funkcije querySelectorAll.

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 će biti prazna
  • kada postoji samo jedan element za koji selektor važi, lista će imati jedan element (neće biti vraćen običan objekat)
  • kada postoji više elemenata za koje selektor važi, biće vraćena lista sa više elemenata

Ukoliko smo skroz sigurni da postoji samo jedan element koji može biti pronađen, možemo mu pristupiti na jednostavniji način:

		
var slika = document.querySelector("div > img.slika_sa_okvirom");
		
	
Slika 20. - Naredba querySelector, koju možemo koristiti ukoliko smo sigurni da navedeni selektor važi za samo jedan element (koji postoji i pri tom nema duplikate).

Funkcija querySelector vraća objekat (nije u pitanju lista), a čak i ako se "pređemo" sa ovakvim pristupom, neće biti strašno:

  • ukoliko ne postoji ni jedan element koji odgovara navedenom selektoru, objekat slika imaće vrednost null
  • ukoliko postoji više elemenata koji odgovaraju selektoru, biće izabran prvi

.... ali, na nama je da pazimo da ne dođemo u situaciju #2 ako nam trebaju svi elementi, a ne samo jedan/prvi (to jest, da budemo sigurni da pozivamo selektor koji se odnosi na jedinstveni objekat).

Pristup DOM elementima preko pripisane klase (getElementsByClass)

Za pristup elementima preko pripisane klase možemo koristiti funkciju getElementsByClass (s tim da u praksi, većina programera radije koristi naredbu querySelectorAll, koja funkcioniše po istom principu, ali, nudi više mogućnosti).

Sledeći kod:

		
var nav_linkovi = document.getElementsByClass("nav_linkovi");
		
	
Slika 21. - Naredba getElementsByClass, koja pronalazi elemente shodno pripisanoj klasi.

.... pronaći će sve elemente kojima je pripisana klasa nav_linkovi i kreirati listu (koju takođe možemo obraditi onako kako smo videli u prethodnom odeljku).

Pristup DOM elementima preko opštih tagova (getElementsByTagName)

Na kraju, elementima možemo pristupati i preko opštih odrednica za tagove preko naredbe getElementsByTagName (ali opet - i u ovom slučaju se isti efekat može postići korišćenjem naredbe querySelectorAll).

Sledeći kod:

		
var naslovi_h2 = document.getElementsByTagName("h2");
		
	
Slika 22. - Naredba getElementsByTagName, koja pronalazi elemente prema imenima tagova.

.... pronaći će sve h2 naslove unutar dokumenta i (ponovo) kreirati listu (kojoj možemo pristupati na način koji smo već prikazali).

Sledeći koraci ....

Opcije koje smo prikazali u članku predstavljaju (kao što možete pretpostaviti) samo mali deo onog što Javascript nudi.

U člancima koje pripremamo za blisku budućnost, govorićemo o Node JS okruženju, ES6 sintaksi, kao i mnogim drugim temama vezanim za Javascript.

Do tada: ....

Autor članka Nikola Vukićević Za web portal www.codeblog.rs
Napomena: Tekstovi, slike, web aplikacije i svi ostali sadržaji na sajtu www.codeblog.rs (osim u slučajevima gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta www.codeblog.rs i zabranjeno je njihovo korišćenje na drugim sajtovima i štampanim medijima, kao i bilo kakvo drugo korišćenje u komercijalne svrhe, bez eksplicitnog pismenog odobrenja autora.
© 2020-2023. Sva prava zadržana.
Viber
početna Početna > Članci > Uvod u Javascript i DOM

Info & povezani članci Info o članku - dugme

Info

trejler_sat Datum objave: 29.10.2020.

trejler_olovka Poslednja izmena: 06.01.2023.

trejler_dokument Jezici: Javascript

trejler_teg_narandzasti Težina: 6/10

Povezani članci

Ostali članci
If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.
Robert X. Cringely
codeBlog codeBlog
Sajt posvećen popularizaciji kulture i veštine programiranja.
Napomena: Tekstovi i slike na sajtu www.codeblog.rs (osim u slučajevima, gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta www.codeblog.rs i zabranjeno je njihovo korišćenje na drugim sajtovima i štampanim medijima, kao i bilo kakvo drugo korišćenje u komercijalne svrhe, bez eksplicitnog odobrenja autora.
© 2020-2023. Sva prava zadržana.
Facebook - logo
Instagram - logo
LinkedIn - logo
Twitter - logo
E-mail
Naslovna
   •
Uslovi korišćenja
   •
Obaveštenja
   •
FAQ
   •
Kontakt