Dom je objektový model dokumentu. Expressive JavaScript: Document Object Model


Štruktúra dokumentu

HTML si môžete predstaviť ako sériu vnorených políčok. Zdá sa, že značky obsahujú ďalšie značky, ktoré zase obsahujú značky alebo text. Tu je príklad dokumentu z predchádzajúcej kapitoly:

Moja domovská stránka Moja domovská stránka

Ahoj, som Marijn a toto je moja domovská stránka.

A napísal som aj knihu! Prečítajte si to tu.

Táto stránka má nasledujúcu štruktúru:

Štruktúra údajov, ktorú prehliadač používa na prezentáciu dokumentu, odráža jeho formu. Pre každý box je objekt, s ktorým môžeme interagovať a zisťovať o ňom rôzne údaje – akú značku predstavuje, aké políčka a text obsahuje. Táto reprezentácia sa nazýva Document Object Model ( objektový model dokument) alebo skrátene DOM.

K týmto objektom môžeme pristupovať prostredníctvom globálnej premennej dokumentu. Jeho vlastnosť documentElement odkazuje na objekt reprezentujúci značku. Poskytuje tiež vlastnosti hlavy a tela, ktoré obsahujú objekty pre zodpovedajúce prvky.

Stromy Pripomeňme si syntaktické stromy z kapitoly 11. Ich štruktúra je nápadne podobná štruktúre dokumentu prehliadača. Každý uzol sa môže spájať s inými uzlami a každá vetva môže mať svoju vlastnú vetvu. Táto štruktúra je typickým príkladom vnorených štruktúr, kde prvky obsahujú subelementy podobné im samým.

Dátovú štruktúru nazývame strom, keď sa vetví, nemá slučky (uzol nemôže obsahovať sám seba) a má jeden odlišný „koreň“. V prípade DOM je koreň document.documentElement.

Stromy sa často nachádzajú vo výpočtovej vede. Okrem reprezentácie rekurzívnych štruktúr, ako sú dokumenty alebo programy HTML, sa často používajú na prácu s triedenými súbormi údajov, pretože prvky sa zvyčajne ľahšie hľadajú alebo vkladajú do triedeného stromu ako do triedeného jednorozmerného poľa.

Typický strom má rôzne uzly. Strom syntaxe jazyka Egg mal premenné, hodnoty a aplikácie. Aplikácie mali vždy dcérske vetvy a premenné a hodnoty boli „listy“, teda uzly bez dcérskych vetiev.

To isté platí pre DOM. Uzly pre bežné prvky, predstavujúce HTML tagy, definujú štruktúru dokumentu. Môžu mať detské uzly. Príkladom takéhoto uzla je document.body. Niektoré z týchto podriadených uzlov môžu byť listy, napríklad text alebo komentáre (v HTML sa komentáre píšu medzi znaky).

Každý objekt uzla DOM má vlastnosť nodeType, ktorá obsahuje číselný kód, ktorý identifikuje typ uzla. Pre regulárne prvky sa rovná 1, čo je tiež definované ako konštantná vlastnosť dokumentu.ELEMENT_NODE. Textové uzly predstavujúce textové pasáže majú hodnotu 3 (document.TEXT_NODE). Komentáre majú 8 (document.COMMENT_NODE).

To znamená, že tu je ďalší spôsob, ako graficky znázorniť strom dokumentu:

Listy sú textové uzly a šípky znázorňujú vzťahy otca a dieťaťa medzi uzlami.

Štandard Použitie tajomných čísel na vyjadrenie typu uzla nie je prístup v štýle JavaScriptu. Neskôr sa stretneme s ďalšími časťami rozhrania DOM, ktoré sa tiež zdajú cudzie a nemotorné. Dôvodom je, že DOM nebol navrhnutý len pre JavaScript. Pokúša sa definovať jazykovo nezávislé rozhranie, ktoré možno použiť v iných systémoch – nielen HTML, ale aj XML, čo je univerzálny dátový formát so syntaxou podobnou HTML.

Ukazuje sa, že je to nepohodlné. Hoci normy sú celkom užitočná vec, v našom prípade nie je výhoda jazykovej nezávislosti až taká užitočná. Je lepšie mať rozhranie, ktoré je dobre prispôsobené jazyku, ktorý používate, ako rozhranie, ktoré je známe vo všetkých jazykoch.

Na ilustráciu nepríjemnej integrácie s jazykom zvážte vlastnosť childNodes, ktorú majú uzly DOM. Obsahuje objekt podobný poľu s vlastnosťou length a očíslovanými vlastnosťami pre prístup k podradeným uzlom. Ale toto je inštancia typu NodeList, nie skutočné pole, takže nemá metódy ako forEach.

Problémy sú spojené aj so zlým návrhom systému. Nemôžete napríklad vytvoriť nový uzol a okamžite k nemu pridať vlastnosti alebo dcérske uzly. Najprv ho musíte vytvoriť, potom pridávať deti po jednom a nakoniec priraďovať vlastnosti po jednom pomocou vedľajších efektov. Kód, ktorý úzko spolupracuje s DOM, sa ukazuje ako dlhý, škaredý a s množstvom opakovaní.

Ale tieto problémy nie sú fatálne. JavaScript vám umožňuje vytvárať abstrakcie. Jednoduché písanie sekundárne funkcie, čo umožňuje jasnejšie a stručnejšie vyjadrenie operácií. Vo všeobecnosti tieto druhy nástrojov poskytujú veľa knižníc zameraných na programovanie pre prehliadač.

Tree Traversal DOM uzly obsahujú veľa odkazov na susedné uzly. Toto je znázornené na diagrame:

Hoci je tu zobrazený iba jeden odkaz každého typu, každý uzol má vlastnosť parentNode, ktorá ukazuje na jeho nadradený uzol. Každý uzol prvku (typ 1) má tiež vlastnosť childNodes, ktorá ukazuje na objekt podobný poľu, ktorý obsahuje jeho dcérske uzly.

Teoreticky môžete prejsť na ktorúkoľvek časť stromu iba pomocou týchto odkazov. JavaScript nám však poskytuje množstvo ďalších pomocných odkazov. Vlastnosti firstChild a lastChild poukazujú na prvý a posledný podriadený prvok alebo sú nulové pre tie uzly, ktoré nemajú potomkov. previousSibling a nextSibling smerujú na susedné uzly – uzly, ktoré majú rovnakého rodiča ako aktuálny uzol, ale sú bezprostredne pred alebo za aktuálnym uzlom v zozname. Vlastnosť previousSibling prvého uzla bude mať hodnotu null a vlastnosť nextSibling posledného uzla bude mať hodnotu null.

Pri práci s takto vnorenými štruktúrami prídu vhod rekurzívne funkcie. Nasledujúce vyhľadá v dokumente textové uzly obsahujúce daný reťazec a vráti hodnotu true, keď ho nájde:

Funkcia talksAbout(node, string) ( if (node.nodeType == document.ELEMENT_NODE) ​​​​( for (var i = 0; i< node.childNodes.length; i++) { if (talksAbout(node.childNodes[i], string)) return true; } return false; } else if (node.nodeType == document.TEXT_NODE) { return node.nodeValue.indexOf(string) >-1;

) ) console.log(talksAbout(document.body, "books")); // → pravda

Vlastnosti textového uzla nodeValue obsahuje riadok textu.

Hľadanie prvkov Často je užitočné prechádzať týmito nadradenými, podradenými a súrodeneckými prepojeniami a pohybovať sa v celom dokumente. Ak však potrebujeme konkrétny uzol v dokumente, je veľmi nepohodlné ho prechádzať, začať od document.body a hlúpo prejsť cestou napevno zakódovanou v kóde. Týmto vytvárame do programu predpoklady o presnej štruktúre dokumentu – ktoré možno neskôr budeme chcieť zmeniť. Ďalším komplikujúcim faktorom je, že textové uzly sa vytvárajú aj pre medzery medzi uzlami. V dokumente z príkladu nemá značka telo tri deti (h1 a dve p), ale sedem: tieto tri plus medzery pred, za a medzi nimi.

Var link = document.body.getElementsByTagName("a"); console.log(link.href);

Všetky uzly prvkov majú metódu getElementsByTagName, ktorá zhromažďuje všetky prvky s danou značkou, ktoré sú potomkami (priamymi alebo nepriamymi potomkami) tohto uzla, a vracia ich ako objekt podobný poľu.

Ak chcete nájsť konkrétny uzol, môžete mu dať atribút id a použiť metódu document.getElementById.

var pštros = document.getElementById("gertrúda"); console.log(ostrich.src);

Treťou metódou je getElementsByClassName, ktorá podobne ako getElementsByTagName prehľadáva obsah uzla prvku a vracia všetky prvky, ktoré obsahujú zadaný reťazec vo svojej triede.

Zmena dokumentu Takmer všetko v štruktúre DOM sa dá zmeniť. Uzly prvkov majú množinu metód, ktoré sa používajú na ich úpravu. Metóda removeChild odstráni zadaný podriadený uzol. Na pridanie uzla môžete použiť appendChild, ktorý pridá uzol na koniec zoznamu, alebo insertBefore, ktorý pridá odovzdaný uzol ako prvý argument pred odovzdaný uzol ako druhý argument.

var odseky = document.body.getElementsByTagName("p"); document.body.insertBefore(odseky, odseky);

Uzol môže existovať iba na jednom mieste v dokumente. Takže vložením odseku „Tri“ pred odsek „Jedna“ ho vlastne odstránime z konca zoznamu a vložíme na začiatok a dostaneme „Tri/Jeden/Dva“. Všetky operácie na vloženie uzla povedú k jeho zmiznutiu z jeho aktuálnej pozície (ak nejakú mal).

Metóda replaceChild sa používa na nahradenie jedného dcérskeho uzla iným. Prijíma dva uzly: nový a ten, ktorý je potrebné vymeniť. Uzol, ktorý sa má nahradiť, musí byť potomkom prvku, ktorého metódu voláme. Ako nahradiťChild, tak aj vložiťBefore očakávajú ako prvý argument nový uzol.

Vytváranie uzlov V nasledujúcom príklade musíme vytvoriť skript, ktorý nahradí všetky obrázky (tag) v dokumente textom obsiahnutým v ich atribúte „alt“, ktorý špecifikuje alternatívnu textovú reprezentáciu obrázka.

Ak to chcete urobiť, musíte nielen odstrániť obrázky, ale tiež pridať nové textové uzly, ktoré ich nahradia. Na tento účel používame metódu document.createTextNode.

Toto V .

Nahradiť

function replaceImages() ( var images = document.body.getElementsByTagName("img"); for (var i = images.length - 1; i >= 0; i--) ( var image = images[i]; if ( image.alt) ( var text = document.createTextNode(image.alt); image.parentNode.replaceChild(text, image); ) ) )

Zadaný reťazec nám createTextNode poskytne uzol DOM typu 3 (text), ktorý môžeme vložiť do dokumentu a zobraziť ho na obrazovke.

Cyklus obrázkov začína na konci zoznamu uzlov. Deje sa tak preto, lebo zoznam uzlov vrátených metódou getElementsByTagName (alebo vlastnosťou childNodes) sa neustále aktualizuje, keď sa dokument mení. Ak by sme začali od začiatku, odstránenie prvého obrázka by spôsobilo, že zoznam by stratil svoj prvý prvok a počas druhého prechodu cyklu, keď je i 1, by sa zastavil, pretože dĺžka zoznamu by sa tiež zmenila na 1.

Ak potrebujete pracovať s pevným zoznamom uzlov namiesto živého, môžete ho previesť na skutočné pole pomocou metódy slice.

Var arrayish = (0: "jeden", 1: "dva", dĺžka: 2); var real = Array.prototype.slice.call(arrayish, 0); real.forEach(function(elt) ( console.log(elt); )); // → jeden // dva

Na vytvorenie uzlov prvkov (typ 1) môžete použiť document.createElement. Metóda prevezme názov značky a vráti nový prázdny uzol daný typ. Nasledujúci príklad definuje nástroj elt, ktorý vytvorí uzol prvku a použije zostávajúce argumenty ako jeho potomkov. Táto funkcia sa potom používa na pridanie ďalších informácií do cenovej ponuky.

Žiadna kniha nie je nikdy dokončená. Pri práci na nej sa naučíme dosť na to, aby sme ju považovali za nezrelú, len čo ju opustíme. funkcia elt(typ) ( var node = document.createElement(type); for (var i = 1; i< arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; } document.getElementById("quote").appendChild(elt("footer", "-", elt("strong", "Карл Поппер"), ", предисловие ко второму изданию ", elt("em", "Открытое общество и его враги "), ", 1950"));

Atribúty K niektorým prvkom atribútov, ako napríklad href pre odkazy, je možné pristupovať prostredníctvom vlastnosti objektu s rovnakým názvom. To je možné pre obmedzený počet bežne používaných štandardných atribútov.

HTML však umožňuje priradiť uzlom ľubovoľné atribúty. Je to užitočné, pretože... umožňuje uložiť dodatočné informácie v dokumente. Ak si vymyslíte vlastné názvy atribútov, nebudú medzi vlastnosťami uzla prvku. Namiesto toho budete musieť na prácu s nimi použiť metódy getAttribute a setAttribute.

Štartovací kód 00000000.

Mačka má štyri nohy.

var paras = document.body.getElementsByTagName("p"); Array.prototype.forEach.call(paras, function(para) ( if (para.getAttribute("data-classified") == "secret") para.parentNode.removeChild(para; ));

Odporúčam dať pred názvy vymyslených atribútov „data-“, aby neboli v rozpore s inými. Ako jednoduchý príklad Napíšeme zvýrazňovač syntaxe, ktorý hľadá značky („vopred naformátované“ – používa sa pre kód a obyčajný text) s atribútom data-language a pomerne hrubo sa pokúša zvýrazniť kľúčové slová v jazyku.

Funkcia highlightCode(node, keywords) ( var text = node.textContent; node.textContent = ""; // Vymazanie zhody var uzla, pos = 0; while (match = keywords.exec(text)) ( var before = text . keywords.lastIndex ) var after = text.slice(pos);

Funkcia highlightCode preberá uzol A bežný znak (s povoleným globálnym nastavením), ktorý sa zhoduje s kľúčovým slovom programovacieho jazyka, ktoré obsahuje prvok.

Vlastnosť textContent sa používa na získanie celého textu uzla a potom sa nastaví na prázdny reťazec, čím sa uzol vymaže. Prechádzame všetky výskyty výrazu kľúčového slova, pridávame medzi ne text vo forme jednoduchých textových uzlov a pridávame zodpovedajúci text (kľúčové slová) tak, že ich uzatvoríme do prvkov (tučné).

Môžeme automaticky zvýrazniť celý kód stránky prejdením všetkých prvkov, ktoré majú atribút data-language, a zavolaním highlightCode na každý so správnym regulárnym výrazom.

Jazyky var ​​= ( javascript: /\b(funkcia|návrat|var)\b/g /* … atď */ ); function highlightAllCode() ( var pres = document.body.getElementsByTagName("pre"); for (var i = 0; i< pres.length; i++) { var pre = pres[i]; var lang = pre.getAttribute("data-language"); if (languages.hasOwnProperty(lang)) highlightCode(pre, languages); } }

Tu je príklad:

A tu je identifikačná funkcia:

Funkcia id(x) ( return x; ) highlightAllCode();

Existuje jeden bežne používaný atribút, class, ktorého názov je kľúčové slovo v JavaScripte. Z historických dôvodov, keď staršie implementácie JavaScriptu nedokázali spracovať názvy vlastností, ktoré sa zhodovali Kľúčové slová, je tento atribút prístupný prostredníctvom vlastnosti s názvom className. Môžete k nemu pristupovať aj pod jeho skutočným názvom „class“ prostredníctvom metód getAttribute a setAttribute.

Rozloženie Možno ste si všimli, že rôzne typy prvkov sú rozmiestnené inak. Niektoré, ako paragrafy

Nadpisy sa rozprestierajú po celej šírke dokumentu a zobrazujú sa na samostatných riadkoch. Takéto prvky sa nazývajú blokové prvky. Ostatné ako odkazy alebo sa tučný text zobrazí na rovnakom riadku ako okolitý text. Nazývajú sa vstavané (inline).

Pre každý dokument môžu prehliadače vytvoriť usporiadanie prvkov, rozloženie, v ktorom každý bude mať veľkosť a polohu na základe jeho typu a obsahu. Toto rozloženie sa potom použije na vytvorenie vzhľadu dokumentu.

Veľkosť a polohu prvku možno zistiť pomocou JavaScriptu. Vlastnosti offsetWidth a offsetHeight udávajú veľkosť v pixeloch, ktoré prvok zaberá. Pixel je základná jednotka merania v prehliadačoch a zvyčajne zodpovedá veľkosti najmenšieho bodu na obrazovke. Podobne clientWidth a clientHeight udávajú veľkosť vnútornej časti prvku, nepočítajúc hranicu (alebo, ako niektorí hovoria, obrubník).

Som v krabici

var para = document.body.getElementsByTagName("p"); console.log("clientHeight:", para.clientHeight); console.log("offsetHeight:", para.offsetHeight);

Najúčinnejším spôsobom, ako zistiť presné umiestnenie prvku na obrazovke, je metóda getBoundingClientRect. Vráti objekt s vlastnosťami top, bottom, left a right, ktoré obsahujú polohu prvku vzhľadom na ľavý horný roh obrazovky v pixeloch. Ak potrebujete získať tieto údaje relatívne k celému dokumentu, musíte pridať aktuálnu pozíciu posúvania, ktorá je obsiahnutá v globálnych premenných pageXOffset a pageYOffset.

Analýza dokumentu je náročná úloha. Z dôvodu rýchlosti motory prehliadača neprestavujú dokument pri každej zmene, ale počkajú tak dlho. ako je to možné. Keď program JavaScript, ktorý upravil dokument, skončí, prehliadač bude musieť vypočítať nové rozloženie stránky, aby sa upravený dokument zobrazil na obrazovke. Keď program požaduje polohu alebo veľkosť niečoho čítaním vlastností ako offsetHeight alebo volaním getBoundingClientRect, rozloženie musí byť tiež vypočítané, aby poskytovalo správne informácie.

Program, ktorý pravidelne číta rozloženie DOM a upravuje DOM, prinúti prehliadač mnohokrát prepočítať rozloženie, a preto bude pomalý. V nasledujúcom príklade sú dva rôzne programy, ktoré vytvoria riadok so šírkou X znakov 2000 px a merajú čas chodu.

function time(name, action) ( var start = Date.now(); // Aktuálny čas v milisekundách action(); console.log(name, "takeen", Date.now() - start, "ms"); ) time("dumb", function() ( var target = document.getElementById("one"); while (target.offsetWidth< 2000) target.appendChild(document.createTextNode("X")); }); // → тупо заняло 32 ms time("умно", function() { var target = document.getElementById("two"); target.appendChild(document.createTextNode("XXXXX")); var total = Math.ceil(2000 / (target.offsetWidth / 5)); for (var i = 5; i < total; i++) target.appendChild(document.createTextNode("X")); }); // → умно заняло 1 ms

Štýly Videli sme, že rôzne prvky HTML sa správajú odlišne. Niektoré sú zobrazené ako bloky, iné sú vložené. Niektoré pridávajú vizuálny štýl, napríklad text tučným písmom a podčiarknutým a modrým.

Vzhľad obrázka v značke alebo skutočnosť, že odkaz v značke po kliknutí otvorí novú stránku, súvisí s typom prvku. Ale základné štýly spojené s prvkom, ako je farba textu alebo podčiarknutie, môžeme zmeniť. Tu je príklad použitia vlastnosti style:

Zelený odkaz

Atribút štýlu môže obsahovať jednu alebo viac deklarácií vlastnosti (farba), za ktorými nasleduje dvojbodka a hodnota. V prípade viacerých vyhlásení sú oddelené bodkočiarkou: „farba: červená; hranica: žiadna“.

Pomocou štýlov sa dá zmeniť veľa vecí. Vlastnosť zobrazenia napríklad riadi, či sa prvok zobrazí v blokovej alebo riadkovej forme.

Text sa zobrazuje ako blok a nie je vôbec viditeľný.

Prvok bloku je zobrazený ako samostatný blok a ten nie je vôbec viditeľný – display: none zakáže zobrazenie prvkov. Týmto spôsobom môžete skryť prvky. To sa zvyčajne uprednostňuje úplné odstránenie z dokumentu, pretože je jednoduchšie ich neskôr v prípade potreby znova zobraziť.

Kód JavaScript môže priamo pôsobiť na štýl prvku prostredníctvom vlastnosti štýlu uzla. Obsahuje objekt, ktorý má vlastnosti pre všetky vlastnosti štýlu. Ich hodnoty sú reťazce, do ktorých môžeme zapisovať, aby sme zmenili nejaký aspekt štýlu prvku.

Krása

var para = document.getElementById("para"); console.log(para.style.color); para.style.color = "purpurová";

Niektoré názvy vlastností štýlu obsahujú spojovníky, napríklad font-family. Keďže by sa s nimi nepohodlne pracovalo v JavaScripte (museli by ste napísať štýl["font-family")], názvy vlastností v objekte štýlu sú napísané bez spojovníka, ale namiesto toho sa v nich objavia veľké písmená: štýl.fontFamily

Kaskádové štýly Systém štýlov v HTML sa nazýva CSS (Cascading Style Sheets). Šablóna štýlov je množina štýlov v dokumente. Môže byť napísaný vo vnútri značky:
silné (štýl písma: kurzíva; farba: šedá; )

Teraz je text silnej značky naklonený a sivý.

„Kaskádové“ znamená, že sa kombinujú viaceré pravidlá, aby sa vytvoril konečný štýl dokumentu. V príklade je predvolený štýl pre, ktorý robí text tučným, prekrytý pravidlom zo značky, ktoré pridáva štýl a farbu písma.

Ak je hodnota vlastnosti určená viacerými pravidlami, prednosť majú tie neskoršie. Ak by štýl textu obsahoval pravidlo font-weight: normal, ktoré je v rozpore s predvoleným štýlom, text by bol normálny, nie tučný. Štýly, ktoré sa aplikujú na uzol prostredníctvom atribútu štýlu, majú najvyššiu prioritu.

V CSS je možné nastaviť nielen názov tagov. Pravidlo pre .abc sa vzťahuje na všetky prvky, ktoré majú špecifikovanú triedu „abc“. Pravidlo #xyz sa vzťahuje na prvok s atribútom id rovným „xyz“ (atribúty id musia byť jedinečné pre dokument).

Jemné ( farba: šedá; veľkosť písma: 80 %; ) #header ( pozadie: modrá; farba: biela; ) /* Prvky p, ktoré majú triedy aab a id nastavené na hlavné */ p.a.b#main ( okraj-dole : 20px)

Priorita najnovších pravidiel funguje, keď majú pravidlá rovnakú úroveň podrobnosti. Je to miera toho, ako presne opisuje oprávnené prvky, určená počtom a typom požadovaných prvkov. Napríklad pravidlo pre p.a je podrobnejšie ako pravidlá pre p alebo just.a a bude mať prednosť.

Zápis p > a (...) sa vzťahuje na všetky značky, ktoré sú vo vnútri značky a sú jej priamymi potomkami.
p a (...) platí aj pre všetky značky v rámci, či už ide o priame dieťa alebo nie.

Selektory dopytov V tejto knihe príliš nepoužívame šablóny so štýlmi. Pochopenie toho, ako fungujú, je dôležité pre programovanie prehliadača, ale podrobné vysvetlenie všetkých ich vlastností by zabralo 2-3 knihy. hlavný dôvod oboznámenie sa s nimi a so syntaxou selektorov (záznamov, ktoré určujú, na ktoré prvky sa pravidlá vzťahujú) – rovnako efektívny minijazyk môžeme použiť na vyhľadávanie prvkov DOM.

Metóda querySelectorAll, ktorá existuje na objekte dokumentu aj na prvkoch uzla, vezme reťazec selektora a vráti objekt podobný poľu, ktorý obsahuje všetky prvky, ktoré sa mu zhodujú.

Milujem búrku na začiatku mája

Keď prvý jarný hrom

Akoby frflali a hrali sa

Hukot na modrej oblohe.

funkcia pocet(selektor) ( return document.querySelectorAll(selector).length; ) console.log(count("p")); // Všetky prvky

// → 4 console.log(count(".animal")); // Trieda zvierat // → 2 console.log(count("p .animal")); // Trieda zvierat vnútri

// → 2 console.log(count("p > .zviera")); // Priame dieťa

// → 1

Na rozdiel od metód ako getElementsByTagName nie je objekt vrátený querySelectorAll interaktívny. Nezmení sa, ak zmeníte dokument.

Metóda querySelector (bez All) funguje podobným spôsobom. Potrebujete to, ak potrebujete jeden konkrétny prvok. Vráti iba prvú zhodu alebo nulu, ak neexistujú žiadne zhody.

Poloha a animácia Vlastnosť position štýlov výrazne ovplyvňuje umiestnenie prvkov. V predvolenom nastavení je statický, čo znamená, že prvok je v dokumente vo svojej normálnej polohe. Keď je relatívny, prvok stále zaberá miesto, ale teraz je možné použiť vlastnosti hore a vľavo na jeho posunutie vzhľadom na jeho normálnu polohu. Keď je absolútna, prvok je odstránený z bežného „toku“ dokumentu – to znamená, že nezaberá miesto a môže sa prekrývať s ostatnými. Navyše, jeho ľavé a horné vlastnosti môžu byť použité na umiestnenie absolútne relatívne k ľavému hornému rohu najbližšieho uzatváracieho prvku, ktorého poloha nie je statická. A ak takýto prvok neexistuje, umiestni sa vzhľadom na dokument.

Môžeme to použiť na vytvorenie animácie. Nasledujúci dokument zobrazuje obrázok mačky pohybujúcej sa po elipse.

var cat = document.querySelector("img"); var uhol = 0, lastTime = null; function animate(time) ( if (lastTime != null) angle += (time - lastTime) * 0,001; lastTime = time; cat.style.top = (Math.sin(uhol) * 20) + "px"; cat .style.left = (Math.cos(uhol) * 200) + "px"; requestAnimationFrame(animate);

Obrázok je vycentrovaný na stránke a má daná pozícia: relatívna. Neustále aktualizujeme horné a ľavé vlastnosti obrázka, aby sa hýbal.

Skript používa requestAnimationFrame na volanie funkcie animovať zakaždým, keď je prehliadač pripravený prekresliť obrazovku. Samotná funkcia animácie znova zavolá requestAnimationFrame, aby naplánovala ďalšiu aktualizáciu. Keď je okno prehliadača (alebo záložka) aktívne, výsledkom budú aktualizácie rýchlosťou približne 60-krát za sekundu, čo umožní pekne vyzerajúce animácie.

Ak by sme jednoducho aktualizovali DOM v slučke, stránka by zamrzla a nič by nebolo vidieť. Prehliadače neobnovujú stránku, keď je spustený JavaScript, a neumožňujú interakciu so stránkou, keď je spustená. To je dôvod, prečo potrebujeme requestAnimationFrame – hovorí prehliadaču, že sme nateraz hotoví, a môže robiť veci v prehliadači, ako je obnovenie obrazovky a odpovede na požiadavky používateľov.

Naša animačná funkcia prechádza aktuálny čas cez argumenty, ktoré porovnáva s predchádzajúcim (premenná lastTime), aby bol pohyb mačky rovnomerný a animácia prebiehala plynulo. Ak by sme ním pri každom kroku jednoducho posunuli o nastavenú hodnotu, pohyb by sa spomalil, ak by napríklad počítač zaťažila iná úloha.

Kruhový pohyb sa vykonáva pomocou goniometrických funkcií Math.cos a Math.sin. Pre tých, ktorí ich nepoznajú, ich stručne popíšem, keďže ich budeme potrebovať neskôr.

Math.cos a Math.sin sú užitočné, keď potrebujete nájsť body na kružnici so stredom (0, 0) a polomerom jedna. Obe funkcie interpretujú svoj argument ako polohu na kruhu, kde 0 je bod na pravom okraji kruhu, potom proti smeru hodinových ručičiek, kým nás cesta 2π (asi 6,28) neprevedie okolo kruhu. Math.cos vypočíta súradnicu x bodu, ktorý je našou aktuálnou pozíciou na kružnici, a Math.sin udáva súradnicu y. Povolené sú aj polohy (alebo uhly) väčšie ako 2π alebo menšie ako 0 - rotácie sa opakujú tak, že a+2π znamená rovnaký uhol ako a.

Použitie sínusu a kosínusu na výpočet súradníc Animácia mačky ukladá počítadlo uhla pre aktuálny uhol natočenia animácie a zvyšuje ho proporcionálne k uplynutému času pri každom vyvolaní funkcie animácie. Tento uhol sa používa na výpočet aktuálnej polohy prvku obrázka. Vrchný štýl sa vypočíta cez Math.sin a vynásobí sa 20 - to je vertikálny polomer našej elipsy. Ľavý štýl je vypočítaný cez Math.cos a vynásobený 200, takže šírka elipsy je oveľa väčšia ako výška.

Štýly zvyčajne vyžadujú jednotky merania. V našom prípade musíme k číslu pridať px, aby sme prehliadaču vysvetlili, že počítame v pixeloch (a nie v centimetroch, ems alebo iných jednotkách). Je ľahké zabudnúť. Použitie čísel bez jednotiek spôsobí, že štýl bude ignorovaný – pokiaľ číslo nie je 0, čo je nezávislé od jednotiek.

Zhrnutie Programy JavaScript môžu skúmať a upravovať aktuálne zobrazený dokument v prehliadači prostredníctvom štruktúry nazývanej DOM. Táto dátová štruktúra predstavuje model dokumentu prehliadača a program JavaScript ju môže upraviť tak, aby zmenil viditeľný dokument. DOM je usporiadaný ako strom, v ktorom sú prvky usporiadané hierarchicky podľa štruktúry dokumentu. Objekty prvkov majú vlastnosti typu parentNode a childNodes, ktoré slúžia na orientáciu v strome.

Vzhľad dokumentu je možné zmeniť pomocou štýlov, buď priamym pridávaním štýlov do uzlov, alebo definovaním pravidiel pre niektoré uzly. Štýly majú veľa vlastností, napríklad farbu alebo zobrazenie. JavaScript môže ovplyvniť štýl prvku priamo prostredníctvom jeho vlastnosti štýlu.

Cvičenia Zostavenie tabuľky Tabuľky sme vytvorili z obyčajného textu v kapitole 6. HTML uľahčuje vytváranie tabuliek. Tabuľka v HTML je vytvorená pomocou nasledujúcich značiek:

názov výška krajina
Kilimandžáro 5895 Tanzánia

Každý riadok obsahuje značku. Do nej môžeme umiestniť bunky: buď bunky hlavičky alebo bežné bunky.

Rovnaké údaje, ktoré sme použili v kapitole 6, sú opäť dostupné v premennej MOUNTAINS.

Napíšte funkciu buildTable, ktorá pomocou poľa objektov s rovnakými vlastnosťami vytvorí štruktúru DOM reprezentujúcu tabuľku. Tabuľka by mala mať riadok hlavičky, v ktorom sú názvy vlastností zabalené do prvkov, a na každý objekt poľa by mal byť jeden riadok, v ktorom sú jeho vlastnosti zabalené do prvkov. Tu príde vhod funkcia Object.keys, ktorá vráti pole obsahujúce názvy vlastností objektu.

Keď máte základy, zarovnajte bunky s číslami doprava zmenou ich vlastnosti style.textAlign na "right".

/* Definuje štýly pre krásne tabuľky */ tabuľka ( border-collapse: Collapse; ) td, th ( border: 1px plná čierna; padding: 3px 8px; ) th ( text-align: left; ) function buildTable(data) ( / / Váš kód ) document.body.appendChild(buildTable(MOUNTAINS));

Prvky podľa názvu značky Metóda getElementsByTagName vráti všetky podradené prvky s daným názvom značky. Vytvorte si vlastnú verziu tejto metódy ako bežnú funkciu, ktorá vezme uzol a reťazec (názov značky) a vráti pole obsahujúce všetky zostupné uzly s daným názvom značky.

Ak chcete zistiť názov značky prvku, použite vlastnosť tagName. Upozorňujeme, že toto vráti názov značky veľkými písmenami. Použite metódy reťazca toLowerCase alebo toUpperCase.

Názov s prvkom span vo vnútri.

Odsek s jedným alebo dvoma rozpätiami.

function byTagName(node, tagName) ( // Váš kód ) console.log(byTagName(document.body, "h1").length); // → 1 console.log(byTagName(document.body, "span").length); // → 3 var para = document.querySelector("p"); console.log(byTagName(para, "span").length); // → 2

Cat's Hat Rozviňte animáciu mačky tak, aby kocúr aj jeho klobúk lietali na opačných stranách elipsy.

Alebo nechajte klobúk lietať okolo mačky. Alebo vymyslite niečo iné zaujímavé.

Pre zjednodušenie usporiadania mnohých predmetov je dobré prejsť na absolútne umiestnenie. Potom sa horná a ľavá časť budú považovať za relatívne k ľavému hornému rohu dokumentu. Aby ste sa vyhli používaniu záporných súradníc, môžete k hodnotám polohy pridať daný počet pixelov.

var cat = document.querySelector("#cat"); var klobúk = document.querySelector("#klobúk"); // Tu je váš kód.

Vývojári zvyčajne používajú jQuery, keď potrebujú niečo urobiť s DOM. Takmer akúkoľvek manipuláciu s DOM je však možné vykonať v čistom JavaScripte pomocou jeho DOM API.

Pozrime sa na toto API podrobnejšie:

Nakoniec si napíšete vlastnú jednoduchú knižnicu DOM, ktorú môžete použiť v akomkoľvek projekte.

Dotazy DOM

Dotazy DOM sa vykonávajú pomocou metódy .querySelector(), ktorá berie ako argument ľubovoľný selektor CSS.

Const myElement = document.querySelector("#foo > div.bar")

Vráti prvý zodpovedajúci prvok. Môžete to urobiť opačne - skontrolujte, či sa prvok zhoduje so selektorom:

MyElement.matches("div.bar") === true

Ak chcete získať všetky prvky, ktoré zodpovedajú selektoru, použite nasledujúcu konštrukciu:

Const myElements = document.querySelectorAll(.bar")

Ak viete, na ktorý nadradený prvok chcete odkazovať, môžete namiesto prehľadávania celého kódu jednoducho prehľadávať jeho potomkov:

Const myChildElemet = myElement.querySelector("input") // Namiesto: // document.querySelector("#foo > div.bar input")

Vynára sa otázka: prečo potom používať iné, menej pohodlné metódy ako .getElementsByTagName() ? Je tu malý problém - výstupný výsledok .querySelector() nie je aktualizovaný a keď pridáme nový prvok(pozri), nezmení sa.

Const elements1 = document.querySelectorAll("div") const elements2 = document.getElementsByTagName("div") const newElement = document.createElement("div") document.body.appendChild(newElement) elements1.length === elements2.length // nepravda

Tiež querySelectorAll() zhromažďuje všetko do jedného zoznamu, čo ho robí málo efektívnym.

Ako pracovať so zoznamami?

Okrem toho má .querySelectorAll() dve malé upozornenia. Nemôžete len volať metódy na výsledky a očakávať, že sa použijú na každý z nich (ako ste možno zvyknutí robiť s jQuery). V každom prípade budete musieť iterovať všetky prvky v slučke. Po druhé, vrátený objekt je zoznam prvkov, nie pole. Preto metódy poľa nebudú fungovať. Samozrejme, existujú metódy pre zoznamy, niečo ako .forEach() , ale, bohužiaľ, nie sú vhodné pre všetky prípady. Preto je lepšie previesť zoznam na pole:

// Použitie Array.from() Array.from(myElements).forEach(doSomethingWithEachElement) // Alebo prototyp poľa (pred ES6) Array.prototype.forEach.call(myElements, doSomethingWithEachElement) // Jednoduchšie: .forEach.call( myElements , doSomethingWithEachElement)

Každý prvok má nejaké vlastnosti, ktoré odkazujú na „rodinu“.

MyElement.children myElement.firstElementChild myElement.lastElementChild myElement.previousElementSibling myElement.nextElementSibling

Keďže rozhranie prvku je zdedené z rozhrania uzla, sú prítomné aj nasledujúce vlastnosti:

MyElement.childNodes myElement.firstChild myElement.lastChild myElement.previousSibling myElement.nextSibling myElement.parentNode myElement.parentElement

Prvé vlastnosti sa vzťahujú na prvok a posledné (s výnimkou .parentElement) môžu byť zoznamy prvkov ľubovoľného typu. Podľa toho môžete skontrolovať typ prvku:

MyElement.firstChild.nodeType === 3 // tento prvok bude textový uzol

Pridávanie tried a atribútov

Pridať nová trieda veľmi jednoduché:

MyElement.classList.add("foo") myElement.classList.remove("bar") myElement.classList.toggle("baz")

Pridanie vlastnosti k prvku je rovnaké ako pri akomkoľvek objekte:

// Získanie hodnoty atribútu const value = myElement.value // Nastavenie atribútu ako vlastnosti prvku myElement.value = "foo" // Для установки нескольких свойств используйте.Object.assign() Object.assign(myElement, { value: "foo", id: "bar" }) // Удаление атрибута myElement.value = null !}

Môžete použiť metódy .getAttibute() , .setAttribute() a .removeAttribute(). Okamžite zmenia atribúty HTML prvku (na rozdiel od vlastností DOM), čo spôsobí opätovné vykreslenie prehliadača (všetky zmeny môžete vidieť preskúmaním prvku pomocou vývojárskych nástrojov prehliadača). Takéto prekreslenia si vyžadujú nielen viac zdrojov ako nastavenie vlastností DOM, ale môžu viesť aj k neočakávaným chybám.

Zvyčajne sa používajú pre prvky, ktoré nemajú zodpovedajúce vlastnosti DOM, ako napríklad colspan . Alebo ak je ich použitie naozaj nevyhnutné, napríklad pre HTML vlastnosti pri dedení (pozri).

Pridanie štýlov CSS

Pridávajú sa rovnakým spôsobom ako ostatné vlastnosti:

MyElement.style.marginLeft = "2em"

Niektoré špecifické vlastnosti je možné nastaviť pomocou .style , ale ak chcete získať hodnoty po niektorých výpočtoch, potom je lepšie použiť window.getComputedStyle() . Táto metóda prijme prvok a vráti CSSStyleDeclaration, ktorá obsahuje štýly samotného prvku aj jeho rodiča:

Window.getComputedStyle(myElement).getPropertyValue("margin-left")

Zmena DOM

Prvky môžete presúvať:

// Pripojiť element1 ako posledného potomka elementu2 element1.appendChild(element2) // Vložiť element2 ako potomka elementu1 pred element3 element1.insertBefore(element2, element3)

Ak ho nechcete presunúť, ale potrebujete vložiť kópiu, použite:

// Vytvorenie klonu const myElementClone = myElement.cloneNode() myParentElement.appendChild(myElementClone)

Metóda .cloneNode() berie ako argument boolovskú hodnotu a ak je true, klonujú sa aj podradené prvky.

Samozrejme môžete vytvárať nové prvky:

Const myNewElement = document.createElement("div") const myNewTextNode = document.createTextNode("nejaký text")

A potom ich vložte podľa obrázka vyššie. Prvok nemôžete odstrániť priamo, ale môžete to urobiť prostredníctvom nadradeného prvku:

MyParentElement.removeChild(myElement)

Môžete tiež nepriamo kontaktovať:

MyElement.parentNode.removeChild(myElement)

Metódy pre prvky

Každý prvok má vlastnosti ako .innerHTML a .textContent , obsahuje HTML kód a teda aj samotný text. Nasledujúci príklad zmení obsah prvku:

// Zmena HTML myElement.innerHTML = ` Nový obsah ( el.addEventListener("zmena", funkcia (udalosť) ( console.log(event.target.value) )) ))

Zabránenie predvoleným akciám

Na tento účel použite metódu .preventDefault(), ktorá blokuje štandardné akcie. Napríklad zablokuje odoslanie formulára, ak autorizácia na strane klienta nebola úspešná:

MyForm.addEventListener("submit", funkcia (udalosť) ( const name = this.querySelector("#name") if (name.value === "Káčer Donald") { alert("You gotta be kidding!") event.preventDefault() } }) !}

Metóda .stopPropagation() vám pomôže, ak máte špecifickú obsluhu udalosti priradenú podriadenému prvku a druhú obsluhu udalosti priradenú rodičovi pre rovnakú udalosť.

Ako už bolo uvedené, metóda .addEventListener() má voliteľný tretí argument vo forme konfiguračného objektu. Tento objekt musí obsahovať ktorúkoľvek z nasledujúcich boolovských vlastností (všetky sú predvolene nastavené na hodnotu false):

  • zachytiť: udalosť bude pripojená k tomuto prvku pred akýmkoľvek iným prvkom nižšie v DOM;
  • raz: udalosť možno priradiť iba raz;
  • pasívne: event.preventDefault() sa bude ignorovať (výnimka pri chybe).

Najbežnejšou vlastnosťou je .capture a je taká bežná, že pre ňu existuje skratka: namiesto jej odovzdania v konfiguračnom objekte jednoducho odovzdajte jej hodnotu sem:

MyElement.addEventListener(typ, poslucháč, pravda)

Obslužné rutiny sa odstraňujú pomocou metódy .removeEventListener(), ktorá má dva argumenty: typ udalosti a odkaz na obslužný program, ktorý sa má odstrániť. Napríklad vlastnosť Once možno implementovať takto:

MyElement.addEventListener("zmena", poslucháč funkcie (udalosť) ( console.log(udalosť.type + " sa spustilo " + toto) this.removeEventListener("zmena", poslucháč) ))

Dedičnosť

Povedzme, že máte prvok a chcete pridať obsluhu udalosti pre všetky jeho deti. Potom by ste ich museli prechádzať pomocou metódy myForm.querySelectorAll("input"), ako je uvedené vyššie. Môžete však jednoducho pridať prvky do formulára a skontrolovať ich obsah pomocou event.target .

MyForm.addEventListener("zmena", funkcia (udalosť) ( const target = event.target if (target.matches("input")) ( console.log(target.value) ) ))

A ešte jedno plus túto metódu je, že handler bude automaticky viazaný na nové podradené prvky.

Animácia

Najjednoduchší spôsob, ako pridať animáciu, je použiť CSS s vlastnosťou prechodu. Ale pre väčšiu flexibilitu (napríklad pre hry) je vhodnejší JavaScript.

Volanie metódy window.setTimeout() až do konca animácie nie je najlepší nápad, pretože vaša aplikácia môže zamrznúť, najmä na mobilné zariadenia. Na uloženie všetkých zmien do ďalšieho prekreslenia je lepšie použiť window.requestAnimationFrame(). Berie funkciu ako argument, ktorý zase dostáva časovú pečiatku:

Const start = window.performance.now() const Duration = 2000 window.requestAnimationFrame(funkcia fadeIn (teraz)) ( const progress = now - start myElement.style.opacity = progress/trvanie if (pokrok< duration) { window.requestAnimationFrame(fadeIn) } }

Týmto spôsobom sa dosiahne veľmi hladká animácia. Mark Brown vo svojom článku rozoberá túto tému.

Písanie vlastnej knižnice

Skutočnosť, že v DOM musíte neustále opakovať prvky, aby ste mohli vykonávať akékoľvek operácie s prvkami, sa môže zdať dosť únavná v porovnaní so syntaxou $(".foo").css((color: "red") jQuery. Prečo však nenapísať niekoľko vlastných metód, ktoré vám túto úlohu uľahčia?

Const $ = funkcia $ (selektor, kontext = dokument) ( prvky const = Array.from(context.querySelectorAll(selektor)) return ( prvky, html (newHtml) ( this.elements.forEach(element => ( element.innerHTML = newHtml )) return this ), css (newCss) ( this.elements.forEach(element => ( Object.assign(element.style, newCss) )) return this ), on (event, handler, options) ( this.elements .forEach(element => ( element.addEventListener(event, handler, options) )) return this ) ) )

Keď otvoríte akýkoľvek dokument HTML, prehliadač najprv analyzuje jeho obsah a na základe tejto analýzy vytvorí objektový model dokumentu HTML alebo skrátene DOM.

DOM pozostáva z hierarchicky vnorených objektov nazývaných uzly. Každý uzol v štruktúre predstavuje umiestnenie na HTML stránku element.

Pomocou DOM môžete interagovať ( čítať, meniť, mazať) s obsahom HTML dokumentov zo skriptov.

Nižšie je uvedený kód pre HTML dokument a DOM, ktoré by prehliadač vytvoril na základe tohto kódu:

HTML DOM HTML DOM.

Ahojte všetci.

Všetky obdĺžniky zobrazené na obrázku sú objekty (alebo uzly). Uzly rôznych typov sú na obrázku označené rôznymi farbami.

Uzol Dokument je označený červenou farbou. Akýkoľvek prístup k DOM musí začínať prístupom k tomuto uzlu.

Elementárne uzly sú označené zelenou farbou. Pre každý prvok HTML na stránke prehliadač vytvorí zodpovedajúci uzol prvku.

Obsah prvkov je uložený v textových uzloch. Textové uzly sú v našom diagrame označené modrou farbou.

Pre každý HTML atribút vytvorí sa atribútový uzol. Uzol atribútu je na diagrame označený ružovou farbou.

Poznámka: Pamätajte, že text je vždy uložený v textových uzloch a nie je vlastnosťou prvku. Tie. Ak chcete získať prístup k obsahu prvku HTML, musíte získať prístup k vlastnosti jeho textového uzla.

Vzťahy medzi uzlami

Uzly v štruktúre objektu sú navzájom prepojené. Existuje niekoľko špeciálnych výrazov na opis vzťahov medzi uzlami:

Nadradený uzol ( rodičovský uzol) - nadradeným uzlom vo vzťahu k predmetnému objektu je uzol, do ktorého je predmetný objekt vnorený. V našom diagrame vo vzťahu k uzlom a

je rodič. Pre uzol je nadradený uzol .

Zostupné uzly ( detský uzol) - podradený uzol vo vzťahu k predmetnému objektu je uzol, ktorý je vnorený do predmetného objektu. V našom diagrame vo vzťahu k uzlu a

Sú to potomkovia. Pre uzol je dieťa .

Súrodenecké uzly ( súrodenecký uzol) - uzly, ktoré sú na rovnakej úrovni vnorenia vo vzťahu k ich rodičovskému uzlu. V našom diagrame sú súrodenecké uzly a ,

Najvyšší uzol v DOM sa nazýva koreň. V našom diagrame je to koreň (keďže objekt dokumentu nie je súčasťou DOM).

V tejto lekcii sa pozrieme na to, čo je DOM, prečo je potrebný a ako sa vytvára.

čo je DOM?

Keď prehliadač požiada o stránku a dostane svoj zdrojový kód HTML ako odpoveď zo servera, musí ho najprv analyzovať. V procese analýzy a analýzy kódu HTML prehliadač na základe neho vytvorí strom DOM.

Po dokončení tejto akcie a niekoľkých ďalších začne prehliadač vykresľovať stránku. V tomto procese už samozrejme používa strom DOM, ktorý vytvoril, a nie pôvodný HTML kód.

DOM je objektový model dokumentu, ktorý prehliadač vytvára v pamäti počítača na základe HTML kódu, ktorý dostane zo servera.

Zjednodušene povedané, HTML kód je text stránky a DOM je množina súvisiacich objektov vytvorených prehliadačom pri analýze jej textu.

V prehliadači Chrome je možné zdrojový kód stránky, ktorú prehliadač dostane, zobraziť na karte Zdroj na paneli Nástroje pre vývojárov webu.


Chrome nemá nástroj, pomocou ktorého môžete zobraziť strom DOM, ktorý vytvára. Existuje však znázornenie tohto stromu DOM vo forme kódu HTML, ktorý je k dispozícii na karte „Prvky“. Táto reprezentácia DOM je, samozrejme, pre webového vývojára oveľa pohodlnejšia na prácu. Preto neexistuje nástroj, ktorý by reprezentoval DOM ako stromovú štruktúru.


Objekty v tomto modeli sú tvorené takmer zo všetkého, čo je v HTML (značky, textový obsah, komentáre atď.), vrátane samotného dokumentu. Vzťahy medzi týmito objektmi v modeli sa vytvárajú na základe toho, ako sú prvky HTML v kóde navzájom umiestnené.

V tomto prípade je možné zmeniť DOM dokumentu po jeho vytvorení. Keď sa zmení DOM, prehliadač takmer okamžite prekreslí obrázok stránky. Výsledkom je, že vykresľovanie našej stránky vždy zodpovedá modelu DOM.

Na čítanie a zmenu DOM programovo nám prehliadač poskytuje DOM API alebo inými slovami programovacie rozhranie. Jednoducho povedané, DOM API je kolekcia obrovského množstva rôznych objektov, ich vlastností a metód, ktoré môžeme použiť na čítanie a zmenu DOM.

Na prácu s DOM sa vo väčšine prípadov používa JavaScript, pretože... Dnes je to jediný programovací jazyk, v ktorom je možné spúšťať skripty v prehliadači.

Prečo potrebujeme DOM API? Potrebujeme to, aby sme mohli pomocou JavaScriptu meniť stránku za chodu, t.j. aby to bolo dynamické a interaktívne.

DOM API nám (vývojárom) poskytuje obrovské množstvo metód, pomocou ktorých môžeme na stránke všetko meniť, ako aj interagovať s používateľom. Tie. toto softvérové ​​rozhranie nám umožňuje vytvárať zložité rozhrania, formuláre, spracovávať akcie používateľov, pridávať a odstraňovať rôzne prvky na stránke, meniť ich obsah, vlastnosti (atribúty) a mnoho iného.

V súčasnosti na webe prakticky neexistujú stránky, ktorých scenáre by s DOM nefungovali.

Z čoho pozostáva HTML kód stránky?

Predtým, ako prejdete k štúdiu objektového modelu dokumentu, musíte si najprv zapamätať, aký je zdrojový kód webovej stránky (dokument HTML).

Zdrojový kód webovej stránky pozostáva zo značiek, atribútov, komentárov a textu. Značky sú základným syntaktickým konštruktom HTML. Väčšina z nich je spárovaná. V tomto prípade sa jeden z nich otvára a druhý zatvára. Jeden takýto pár tagov tvorí HTML element. HTML prvky môžu mať Extra možnosti– atribúty.

Na vytvorenie určitého označenia v dokumente sú niektoré prvky umiestnené v iných. Výsledkom je, že dokument HTML môže byť reprezentovaný ako množina prvkov HTML vnorených do seba.

Ako príklad si predstavte nasledujúci kód HTML:

Názov stránky Názov článku Sekcia článku

Obsah článku

V tomto kóde je koreňovým prvkom html. Obsahuje prvky hlavy a tela. Prvok head obsahuje nadpis a telo obsahuje h1 a div. Prvok div zase obsahuje h2 a p .

Teraz sa pozrime na to, ako prehliadač vytvára strom DOM založený na kóde HTML.

Ako sa vytvára strom DOM dokumentu?

Ako už bolo popísané vyššie, prehliadač vytvára strom založený na prvkoch HTML a iných entitách zdrojový kód stránky. Pri vykonávaní tohto procesu berie do úvahy vnorenie prvkov do seba.

Výsledkom je, že prehliadač používa výsledný strom DOM nielen pri svojej práci, ale poskytuje nám aj API pre pohodlná práca s ním cez JavaScript.

Pri konštrukcii DOM prehliadač vytvára objekty (uzly stromu DOM) z HTML prvkov, textu, komentárov a iných entít tohto jazyka.

Vo väčšine prípadov sa weboví vývojári zaujímajú iba o objekty (uzly) vytvorené z prvkov HTML.

Prehliadač zároveň nielen vytvára objekty z HTML prvkov, ale ich aj navzájom spája určitými väzbami, podľa toho, ako každý z nich súvisí s tým druhým v kóde.

Prvky, ktoré sú priamo v nejakom prvku, sú vo vzťahu k nemu deti. A pre každého z nich je rodičom. Navyše, všetky tieto prvky sú vo vzájomnom vzťahu súrodenci (bratia).

Navyše v HTML má každý prvok vždy jedného rodiča (prvok HTML, v ktorom sa priamo nachádza). V HTML nemôže mať prvok viacero rodičov. Jedinou výnimkou je prvok html. Nemá rodiča.

Ak chcete získať strom DOM tak, ako ho prehliadač vytvára, stačí „usporiadať“ všetky prvky v závislosti od ich vzájomného vzťahu.

Vytváranie stromu DOM sa vykonáva zhora nadol.

V tomto prípade je koreňom stromu DOM vždy samotný dokument (uzol dokumentu). Ďalej je strom zostavený v závislosti od štruktúry HTML kódu.

Napríklad kód HTML, na ktorý sme sa pozreli vyššie, by mal nasledujúci strom DOM:


Na samom vrchole tohto stromu je uzol dokumentu. Tento uzol spojené s html, je to jeho dieťa. Vytvorí sa html uzol html prvok(...). Uzly head(...) a body(...) majú nadradený vzťah s html. Vo vzťahu k sebe sú súrodenci, pretože mať jedného rodiča. Hlavný uzol je spojený s názvom (lt;title>...), je jeho potomkom. Uzly h1 a div sú spojené s telom , ktoré je ich rodičom. Uzol div je spojený s h2(...) a p(), sú jeho potomkami.

Strom začína, ako je uvedené vyššie, objektom dokumentu (uzlom). Na druhej strane má jeden dcérsky uzol tvorený prvkom html (...). Prvky hlava(...) a telo(...) sú v html a sú teda jeho potomkami. Ďalej, hlavný uzol je rodič názvu (lt;title>...). Prvky h1 a div sú vnorené do tela, čo znamená, že sú jeho potomkami. Div priamo obsahuje prvky h2 (...) a p (). To znamená, že uzol div pre každý z nich je rodič.

Takto jednoducho sa dá vytvoriť strom DOM v prehliadači na základe kódu HTML.

Prečo potrebujete vedieť, ako sa vytvára strom DOM? Po prvé, je to pochopenie prostredia, v ktorom chcete niečo zmeniť. Po druhé, väčšina akcií pri práci s DOM spočíva v hľadaní (výbere) potrebných prvkov. Bez znalosti štruktúry DOM stromu a väzieb medzi uzlami bude dosť ťažké v ňom nájsť konkrétny prvok.

Cvičenie

Na základe stromu DOM zobrazeného na obrázku vytvorte HTML kód.


Hlavným nástrojom pre prácu a dynamické zmeny na stránke je DOM (Document Object Model) - objektový model používaný pre XML/HTML dokumenty.

Podľa modelu DOM je dokument hierarchiou.
Každá značka HTML tvorí samostatný prvok uzla, každý text tvorí prvok textu atď.

Jednoducho povedané, DOM je reprezentácia dokumentu ako stromu značiek. Tento strom je tvorený vnorenou štruktúrou značiek a textových fragmentov stránky, z ktorých každý tvorí samostatný uzol.

Najjednoduchší DOM

Najprv zostavme strom DOM pre ďalší dokument.

Názov: Vynikajúci dokument

Vonkajší štítok je , takže strom začína rásť odtiaľ.

Vnútri sú dva uzly: a - stanú sa podriadenými uzlami .

Formulár značiek uzly prvkov(prvkový uzol). Prezentovaný text textové uzly(textový uzol). Oba sú rovnaké uzly v strome DOM.

Zložitejší príklad

Pozrime sa teraz na dôležitejšiu stránku:

O losoch Pravda o losoch.

  • Los je prefíkané zviera
  • .. A zákerné
  • Koreňovým prvkom hierarchie je html. Má dvoch potomkov. Prvým je hlava, druhým telo. A tak ďalej, každá vnorená značka je potomkom vyššie uvedenej značky:

    Na tomto obrázku modrá označuje prvky uzla, čierna označuje textové prvky.

    Strom tvoria modré uzlové prvky – HTML tagy.

    A takto vyzerá strom, ak ho nakreslíte priamo na stránku HTML:

    Mimochodom, strom na tomto obrázku neberie do úvahy text pozostávajúci iba z bielych znakov. Napríklad, takýto textový uzol by mal prísť hneď za . Zavolá sa DOM, ktorý takéto „prázdne“ uzly neobsahuje "normalizovaný".

    Pozrime sa na trochu zložitejší dokument.

    Údaje o dokumente

    • Opatrne
    • Informácie
    Vyrobené v Rusku

    Horná značka je html, má detskú hlavu a telo atď. Výsledkom je strom značiek:

    Atribúty

    V tomto príklade majú uzly nasledujúce atribúty: style , class , id . Všeobecne povedané, atribúty sa tiež považujú za uzly v DOM, ktorých rodičom je prvok DOM, na ktorom sú špecifikované.

    Vo webovom programovaní sa však do tejto džungle väčšinou neponárajú a atribúty považujú za jednoducho vlastnosti uzla DOM, ktoré, ako uvidíme neskôr, možno nastaviť a zmeniť na žiadosť programátora.

    Toto je v skutočnosti tajomstvo, ale DOCTYPE je tiež uzol DOM a nachádza sa v strome DOM naľavo od HTML (tento fakt je skrytý na obrázku).

    P.S. Je to žart o tajomstve, samozrejme, ale nie každý o tom vie. Ťažko si predstaviť, kde by takéto znalosti mohli byť užitočné...

    Normalizácia v rôznych prehliadačoch

    Pri analýze HTML internet Explorer okamžite vytvorí normalizované DOM, v ktorom sa uzly nevytvárajú z prázdneho textu.

    Firefox má iný názor, z každého textového fragmentu vytvára prvok DOM.
    Preto vo Firefoxe strom tohto dokumentu vyzerá takto:

    Na obrázku sú pre stručnosť textové uzly jednoducho označené krížikom. telo má 7 detí namiesto 3.

    Opera sa má tiež čím chváliť. Môže pridať ďalší prázdny prvok „len zo seba“.

    Ak to chcete vidieť, otvorte dokument. Vráti počet podriadených uzlov súboru document.body vrátane textových uzlov.

    Dostanem 3 pre IE, 7 pre Firefox a 8 (!?) pre Operu.

    V praxi táto nekompatibilita nevzniká veľké problémy, ale musíte si to pamätať. Rozdiel sa môže prejaviť napríklad v prípade vymenovania uzlov stromu.

    Možnosti, ktoré DOM dáva

    Prečo okrem krásnych kresieb potrebujeme aj hierarchický DOM?

    Veľmi jednoduché:

    Každý prvok DOM je objekt a poskytuje vlastnosti na manipuláciu s jeho obsahom, na prístup k rodičom a deťom.

    Objekt dokumentu sa používa na manipuláciu s DOM.
    Pomocou document môžete získať požadovaný prvok stromu a zmeniť jeho obsah.

    Napríklad tento kód vezme prvý prvok so značkou ol, postupne odstráni dva prvky zoznamu a potom ich pridá v opačnom poradí:

    Var ol = document.getElementsByTagName("ol") var hiter = ol.removeChild(ol.firstChild) var kovaren = ol.removeChild(ol.firstChild) ol.appendChild(kovaren) ol.appendChild(hiter)

    Príklad, ako takýto skript funguje, nájdete po kliknutí na text na stránke losov

    V starých tutoriáloch a skriptoch môžete vidieť úpravu HTML kódu stránky priamo volaním document.write .

    V moderných skriptoch sa táto metóda takmer nepoužíva, prípady jej správneho použitia sa dajú spočítať na jednej ruke.

    Vyhnite sa document.write... Okrem prípadov, keď naozaj viete, čo robíte (prečo potom čítate návod - už ste guru)

    Pozrime sa bližšie na prístupové metódy a vlastnosti prvkov DOM.

    Prístupové prvky

    Všetky prístupy a úpravy DOM pochádzajú z objektu dokumentu.

    Začnime na vrchole stromu.

    document.documentElement

    Vrchný štítok. V prípade správnej HTML stránky to bude .

    dokument.telo

    Značka, ak sa v dokumente nachádza (musí byť).

    V nasledujúcom príklade sa po kliknutí na tlačidlo vytvorí textová reprezentácia objektov document.documentElement a document.body. Samotný reťazec závisí od prehliadača, hoci objekty sú všade rovnaké.

    function go() ( alert(document.documentElement) alert(document.body) )

    Typy prvkov DOM

    Každý prvok v DOM má svoj typ. Jeho číslo je uložené v atribúte elem.nodeType

    Celkovo je v DOM 12 typov prvkov.

    Zvyčajne sa používa iba jeden: Node.ELEMENT_NODE, ktorého číslo je 1. Prvky tohto typu zodpovedajú značkám HTML.

    Niekedy je užitočný aj typ Node.TEXT_NODE, ktorý sa rovná 3. Ide o textové prvky.

    Iné typy sa pri programovaní javascriptu nepoužívajú.

    Nasledujúci príklad po kliknutí na tlačidlo vytlačí typy document.documentElement a potom typ posledného potomka uzla document.body. Toto je textový uzol.

    function go() ( alert(document.documentElement.nodeType) alert(document.body.lastChild.nodeType) ) Text

    Príklad

    Takto by napríklad vyzeral dokument z vyššie uvedeného príkladu v prehliadači, ak by bol každý viditeľný prvok obklopený rámom s číslom nodeType v pravom hornom rohu.

    ...Údaje

    • Opatrne
    • Informácie
    Vyrobené v Rusku

    Zobrazujú sa tu iba prvky vo vnútri tela, pretože sú jediné, ktoré sa zobrazujú na stránke. Pre prvky typu 1 (tagy) je príslušný tag uvedený v zátvorkách pre textové prvky (typ 3), je tam len číslo.

    Detské prvky
  • Všetky podradené prvky vrátane textových sú v poli childNodes.

    Nasledujúci príklad prejde všetkými potomkami document.body .

    For(var i=0; i TELO

    štýl

    Táto vlastnosť riadi štýl. Je to podobné ako pri nastavovaní štýlu v CSS.

    Môžete napríklad nastaviť element.style.width:

    Zdrojový kód pre toto tlačidlo:

    Jedzte všeobecné pravidlo náhrady - ak má atribút CSS spojovníky, potom na nastavenie štýlu ich musíte nahradiť veľké písmená písmená

    Napríklad, ak chcete nastaviť vlastnosť z-index na 1000, musíte nastaviť:

    Element.style.zIndex = 1000

    innerHTML

    Kedysi bola táto vlastnosť podporovaná iba v IE. Teraz to podporujú všetky moderné prehliadače.

    Obsahuje všetok HTML kód vo vnútri uzla a je možné ho zmeniť.

    Vlastnosť innerHTML sa používa hlavne na dynamickú zmenu obsahu stránky, napríklad:

    Document.getElementById("footer").innerHTML = "Dovidenia!"

    Možno je innerHTML jednou z najbežnejšie používaných vlastností prvku DOM.

    className

    Táto vlastnosť určuje triedu prvku. Je úplne podobný atribútu html „class“.

    Elem.className = "nová trieda"

    onclick, onkeypress, onfocus...

    A ďalšie vlastnosti začínajúce na „on...“ ukladajú funkcie obsluhy pre príslušné udalosti. Môžete napríklad priradiť obsluhu udalosti onclick.

    Ďalšie informácie o týchto vlastnostiach a obslužných programoch udalostí nájdete v časti