nav_dugme codeBlog codeBlog
  • početna Početna stranica
  • Sačuvani članci Sačuvani članci
  • Članci
     (spisak)
  • Kontakt
Povratak na vrh stranice

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

HTML
JavaScript
dom
internet
web dizajn
frontend
fullstack
teorija

Tema: JavaScript

Operacije sa nizovima u programskom jeziku JavaScriptJavaScript ES6 sintaksaUvod u Node.jsAsinhrono programiranje u JavaScriptu

Povezani članci

Uvod u web dizajn - 1. deo - Početni koraciPromenljive u CSS-u (pretprocesori i imenovana svojstva)JSON - tekstualni format za razmenu podatakaUvod u PHP i backend programiranjeLokalno skladištenje podataka browsera (sessionStorage, localStorage, cookies)Šablonske niske u programskim jezicimaCallback funkcije i lambda izraziStruktura web adresa i pristup internet stranicamaIzbor prvog programskog jezikaASCII, UNICODE i UTF - Predstavljanje znakova na računarima
Svi članci
Programming isn't about what you know; it's about what you can figure out.
Chris Pine

Uvod u JavaScript i DOM (Document Object Model)

Facebook LinkedIn Twitter Viber WhatsApp E-mail
zoom_plus zoom_minus bookmark
početna > Članci > Teorija

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 ....

Dom Struktura
Slika 1. - Uprošćena struktura DOM stabla (za sada nema sadržaja i atributa, ali, svakako se može primetiti da struktura čvorova odgovara ugnežđenoj strukturi HTML tagova).

.... 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.

* Izvorni HTML kod se (naravno) ne uklanja, ali - nakon kreiranja DOM stabla - svakako pada u 'drugi plan', i praktično se koristi samo za situacije kada je posetiocima stranice potrebno prikazati - HTML kod. :)

(Na kraju prvog članka uvodnog serijala o web dizajnu, prikazali smo kako se preko browsera može pristupiti sadržaju izvornih HTML datoteka.)

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>
		
	
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 prikazanoj HTML strukturi.

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.

Takođe: zarad opšte računarske pismenosti (i budući smo još uvek u uvodnim poglavljima uvodnog članka o JavaScript-u), pomenućemo da JavaScript - osim imena (i ako izuzmemo C-oliku sintaksu u oba slučaja), nema previše dodirnih tačaka sa popularnim jezikom Java. :)

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).

Kada kažemo da je u pitanju skriptni jezik, mislimo na to da se programski kod ne kompajlira pre pokretanja (za razliku od programskih jezika kakvi su recimo C i C++, kod kojih se napisani programski kod, pre pokretanja, kompajlira u izvršnu binarnu datoteku).

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>
		
	
Slika 4. - Preko <script> tagova, definiše se veza između HTML dokumenta i JavaScript-a.

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

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! :)");
		
	
Slika 5. - JS komanda write - komanda za upis sadržaja u određeni čvor DOM stabla.

.... nećemo (naizgled) biti "prevelike sreće", jer - iako je poruka uredno ispisana - skripta je zapravo poništila prethodnu strukturu učitanog HTML dokumenta!

Ups. :)

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 ....

HTML dokument - pre pozivanja komande document.write
Slika 6. HTML dokument - pre pozivanja komande document.write.

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

HTML dokument - posle pozivanja komande document.write
Slika 7. HTML dokument - posle pozivanja komande document.write.

.... čime je postojeći sadržaj praktično poništen.

.... a videli smo usput i (relativno 'diskutabilnu') "priručnu HTML strukturu" koja nastaje kada browser sam kreira DOM stablo posle pozivanja komande document.write().

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.

Vrlo brzo ćemo razmotriti takav primer.

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.

* U praktičnom smislu, pripisani HTML sadržaj odmah postaje deo DOM stabla.

Funkcija alert ....

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

.... 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).

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).

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!");
		
	
Slika 9. - Komanda console.log, preko koje se u konzoli browsera ispisuje poruka korisniku.

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!");
		
	
Slika 10. - Komanda console.error - funkcionalnost je slična kao u slučaju komande console.log, ali - poruka je uokvirena crvenom bojom.

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.)

Ovoga puta, rezultat neće biti prikazan u osnovnom prozoru.

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); 
		
	
Slika 11. - Komanda prompt, preko koje se obavlja učitavanje podataka koje korisnici unose.

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.

* Sa upotrebom promenljivih detaljnije ćemo se upoznati u nastavku (posle upoznavanja sa funkcijom getElementById).

** Da pomenemo (ipak), još jednu 'očiglednu' ideju: probajte da unesete dve komande sa gornje slike - direktno u ulazno polje konzole browsera (korisna opcija koja, vrlo često - baš dobro dođe u fazi kreiranja i isprobavanja skripti).

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>
		
	
Slika 12. - Primer pripisivanje id-ova HTML elementima (što predstavlja neophodan preduslov za direktan pristup elementima preko JavaScript-a).

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

DOM Struktura
Slika 13. - Delimična DOM struktura izmenjenog dokumenta (sa id-om koji je pripisan pasusu).

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.";
		
	
Slika 14. - Pristup elementu preko id-a.

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). **

* Ovoga puta zadržaćemo se na jednostavnom načinu za kreiranje novih elemenata, a funkcije createElement i appendChild će biti prikazane u kasnijim člancima.

** Nakon primera, sa kontrolnim strukturama upoznaćemo se detaljnije.

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;
}
		
	
Slika 15. - CSS klasa na koju ćemo se pozivati u nastavku (u opštem smislu, ukoliko u CSS dokumentu postoji selektor koji se odnosi na određenu klasu, moguće je pozivati se na datu klasu 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 16. - JavaScript na delu: globalne promenljive (var), kontrolne strukture (for) i pristup elementima preko id-a (document.getElementById).

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).

* Da se podsetimo, u HTML primeru koji koristimo, već je naveden tag <link> za povezivanje sa CSS-om.

** Postoji i moderniji način za deklarisanje imenovanih podataka, preko rezervisanih reči let i const (što je pristup koji ćemo posle uvodnog članka početi da koristimo), ali, u uvodnom članku, uglavnom ćemo koristiti rezervisanu reč var (za sam početak - "školski"). :)

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";
		
	
Slika 17. - Definisanje novog sadržaja na način koji praktično podrazumeva pisanje HTML koda unutar JavaScript-a.

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).

U JavaScript-u, vrednosti promenljivih i izraza mogu se umetati u niske i 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):

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)

Čitaoci koji poznaju programski jezik C, jasno će prepoznati (praktično istovetnu) sintaksu za zapis grananja i petlji.

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.")
	}
}
		
	
Slika 18. - Primer (ugnežđenog) if grananja.

Primer takođe prikazuje da je uslove moguće i "ugnežđavati".

* Blok naredbi koji se izvršava ukoliko je uslov zadovoljen ("true grana"), predstavlja obavezan deo sintakse u if grananjima, dok drugi blok naredi ("false grana"), može biti i izostavljen.

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")
}
		
	
Slika 19. - Primer višestrukog ugnežđavanja uslova (koje naizgled deluje kao "nadovezivanje").

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"
		
	
Slika 20. - Primer switch grananja.

Međutim, iako smo koristili isti primer, treba pomenuti da switch grananje nije isto što i 'stilski uređenije višestruko if grananje', već je u pitanja poseban mehanizam za brzinsko pronalaženje poklapanja (o čemu ćemo ipak diskutovati neki drugi put).

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
}
		
	
Slika 21. - Primer while petlje.

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"!

Zarad ulaska u petlju (u gornjem primeru), potrebno je da vrednost promenljive i bude manja od n, međutim, ukoliko u telu petlje ne postoji naredba preko koje se vrednost promenljive i koriguje, uslov će biti zadovoljen svaki put kada se petlja vrati na ispitivanje uslova (i takva "beskonačna petlja" se potencijalno može izvršavati "doveka").

Preko naredbe ++i; uslov će u nekom trenutku prestati da važi (i pri tom je gornjem primeru takođe veoma bitno da se vrednost promenljive n - ne promeni).

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);
		
	
Slika 22. - Primer while petlje sa unutrašnjim uslovom za "rani prekid", preko naredbe break.

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).

Ukoliko se unese vrednost čijim bi dodavanjem granica bila prekoračena, petlja se zaustavlja.

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).

U idejnom smislu, razlika između while petlje i do-while petlje je sledeća: while petlja praktično ima uslov za ulazak u petlju, dok do-while petlja praktično ima uslov za izlazak iz petlje.

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! :)");
		
	
Slika 23. - primer do-while petlje.

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).

Trenutak je da se dodatno osvrnemo na dinamičku tipizaciju (koju smo ranije pominjali) ....

Budući da nisu korišćeni znaci navoda pri inicijalizaciji, promenljiva n se tretira kao celobrojna vrednost, međutim, podatak koji se učitava preko funkcije prompt, formatiran je kao niska - i potrebno je nisku pretvoriti u celobrojni podatak (za šta se koristi funkcija parseInt).

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: ili poznat unapred, ili može biti izračunat).

Opšta šema for petlje može se opisati na sledeći način:

		
for (inicijalizacija; uslov; korekcija) {
	naredbe ....
}
		
	
Slika 24. - Opšta šema for petlje.

Usput: prvi susret sa for petljama često izaziva čuđenje kod početnika u programiranju, međutim, nemojte se 'plašiti' for petlji i ne dajte (ni inače) da vas programske konstrukcije zbunjuju. :)

Sledi dodatno objašnjenje ...

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.

Za primer možemo uzeti pojednostavljenu verziju while petlje sa slike #21 (ispis brojeva od 1 do 10, tj. uzastopni ispis sa unapred zadatom 'gornjom granicom') ....

		
// Inicijalizacija promenljive:
let i = 1;

// Uslov za ulazak u petlju:
while (i <= 10) {
	// Naredbe opšteg tipa:
	console.log("i = " + i);
	// Korekcija:
	++i;
}
		
	
Slika 25. - Detaljnija analiza while petlje koja ispisuje brojeve od 1 do 10.

.... pri čemu možemo zapaziti da je promenljiva i inicijalizovana pre ulaska u petlju, * 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 10, možemo definisati sledeću for petlju:

		
for (let i = 1; i <= 10; ++i) {
	console.log("i = " + i);
}
		
	
Slika 26. - Primer for petlje.

Slični primeri povremeno se pojavljuju u praksi (nisu retki), ali, znatno češće sretaćete se sa primerima petlji u kojima broj ponavljanja nije poznat unapred - 'ali se može izračunati'.

Za primer možemo uzeti (veoma tipičnu) for petlju koja prolazi redom kroz (sve) elemente niza (tj. liste), i obavlja određene operacije:

		
let lista = [ 1, 2, 3, 4, 5, 6, 7 ]
let suma  = 0

for (let i = 0; i< lista.length; ++i) {
	s += lista[i];
	console.log(lista[i]);
}

console.log("suma svih elemenata: ", suma);
		
	
Slika 27. - Primer for petlje koja prolazi kroz sve elemente niza

Kao što vidimo, skripta ispisuje elemente niza redom i računa ukupan zbir svih elemenata (i pri tom broj ciklusa petlje nije zadat unapred, već zavisi od dužine niza).

Takođe (kao što smo već naveli), slične petlje koristićete i za (brojne) druge zadatke. :)

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>
		
	
Slika 28. - Povezivanje JavaScript događaja (onclick) sa HTML elementom (povezivanje podrazumeva poziv funkcije dodavanjePasusa).

"Zvaničan" način podrazumeva da se sav kod (koji se tiče povezivanja) - premešta u JS datoteku.

Moguće je kod pisati i u okviru <script> tagova (ali takav pristup tipično umanjuje preglednost projekata).

Ovoga puta, neophodno je da HTML dugmetu bude pripisan odgovarajući id:

		
<button id="dugme_1">KLIK</button>
		
	
Slika 29. - HTML kod dugmeta koje će biti povezano sa JS događajem.

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);
		
	
Slika 30. - JS kod za povezivanje dugmeta (sa prethodne slike), sa funkcijom dodavanjePasusa.

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.

* Prvi ("lakši") način smatra se prihvatljivim u slučaju manjih projekata/školskih primera i sl, dok se drugi ("zvanični") način povezivanja smatra preglednijim (i prikladnijim za (iole) veće i ozbiljnije projekte), budući da je programski kod (Javascript), razdvojen od HTML dokumenta.

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

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).

Ostalih razlika, 'nema baš previše'. :)

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
		
	
Slika 32. - Primer definisanja funkcije koja vraća vrednost.

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).

* Hoćemo reći: pri definisanju parametara, ne samo da se ne navode tipovi podataka, već se ne koriste ni rezervisane reči var ili let.

Takođe, može se primetiti da smo, u nekoliko prethodnih primera, za deklaraciju promenljivih koristili rezervisanu reč let (umesto var), da bismo se polako upoznali i sa modernijom sintaksom (praktična razlika u gornjim primerima skoro da ne postoji, a više o razlikama između deklaracije preko rezervisanih reči var i let, možete kasnije 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 (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.

U navedenom kontekstu, spoljne JS datoteke se tretiraju kao programski kod koji je direktno upisan unutar <script> tagova.

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>
		
	
Slika 33. - Tag script smešten je unutar head tagova - pre 'vidljivog' sadržaja stranice (tj. pre elementa sa id-om "prvi_pasus").

.... 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")
		
	
Slika 34. - Primer JS instrukcije preko koje se traži element, shodno navedenom id-u (ali - u konkretnom primeru, element 'neće' biti pronađen, budući da DOM struktura elementa body nije kreirana, s obzirom na to da je JS skripta praktično pozvana na početku HTML dokumenta, unutar tagova head).

.... praktično tražila element koji (još uvek) ne postoji!

U praksi, DOM stablo se kreira "veoma brzo" (tipično, cela stranica se učita za manje od 1ms), ali, svejedno, "onda kada je JS skripta tražila određeni element" - nije ga bilo. :)

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

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")
		
	
Slika 35. - Naredba querySelectorAll - univerzalan i veoma koristan način za pronalaženje elemenata.

.... mogu se pronaći svi elementi unutar DOM stabla 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 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";
}
		
	
Slika 36. - 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 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");
		
	
Slika 37. - Naredba querySelector, koja se može koristiti ukoliko smo sigurni da navedeni selektor važi za samo jedan element (koji postoji, i pri tom nema duplikate).

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 vrednost null
  • 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. :)

U idejnom smislu, može se reći da funkcija querySelector predstavlja kombinaciju funkcija getElementById i querySelectorAll.

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");
		
	
Slika 38. - Naredba getElementsByClass, koja pronalazi elemente shodno pripisanoj klasi.

.... 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).

* U praksi, većina programera radije koristi naredbu querySelectorAll, koja funkcioniše po istom principu - i pri tom nudi više mogućnosti.

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");
		
	
Slika 39. - Naredba getElementsByTagName, koja pronalazi elemente prema imenima tagova.

.... 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: ....

Autor članka Nikola Vukićević Za web portal codeblog.rs
Napomena: Tekstovi, slike, web aplikacije i svi ostali sadržaji na sajtu codeblog.rs (osim u slučajevima gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta 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-2025. Sva prava zadržana.
Facebook LinkedIn Twitter Viber WhatsApp E-mail
početna > Članci > Uvod u JavaScript i DOM (Document Object Model)
codeBlog codeBlog
Sajt posvećen popularizaciji kulture i veštine programiranja.
Napomena: Tekstovi i slike na sajtu codeblog.rs (osim u slučajevima, gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta 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-2025. Sva prava zadržana.
Facebook - logo
Instagram - logo
LinkedIn - logo
Twitter - logo
E-mail
Naslovna
   •
Uslovi korišćenja
   •
Obaveštenja
   •
FAQ
   •
Kontakt