Windows.  Virus.  Bärbara datorer.  Internet.  Kontor.  Verktyg.  Förare

När du öppnar ett HTML-dokument, analyserar webbläsaren först dess innehåll och skapar, baserat på denna analys, en HTML-dokumentobjektmodell, eller DOM för kort.

DOM består av hierarkiskt kapslade objekt som kallas noder. Varje nod i strukturen representerar en som är placerad på HTML-sida element.

Med hjälp av DOM kan du interagera ( läsa, ändra, ta bort) med innehållet i HTML-dokument från skript.

Nedan är koden för HTML-dokumentet och DOM som skulle skapas av webbläsaren baserat på denna kod:

HTML DOM HTML DOM.

Hej alla.

Alla rektanglar som visas på bilden är objekt (eller noder). Noder av olika typer är markerade i olika färger i bilden.

Dokumentnoden är markerad med rött. All åtkomst till DOM måste börja med en åtkomst till denna nod.

Elementära noder är markerade med grönt. För varje HTML-element på sidan skapar webbläsaren en motsvarande elementnod.

Innehållet i element lagras i textnoder. Textnoder är markerade med blått i vårt diagram.

För alla HTML-attribut element skapas en attributnod. Attributnoden är markerad med rosa på diagrammet.

Observera: kom ihåg att text alltid lagras i textnoder och inte är en egenskap hos elementet. Dessa. För att komma åt innehållet i ett HTML-element måste du komma åt dess textnodegenskap.

Relationer mellan noder

Noder i en objektstruktur är kopplade till varandra. Det finns flera speciella termer för att beskriva relationerna mellan noder:

Föräldernod ( föräldernod) - den överordnade noden i förhållande till objektet i fråga är den nod som objektet i fråga är kapslat i. I vårt diagram, i förhållande till noderna och

är förälder. För en nod är den överordnade noden .

Descendant noder ( barnnod) - en underordnad nod i förhållande till objektet i fråga är en nod som är kapslad i objektet i fråga. I vårt diagram, i förhållande till noden och

De är ättlingar. För en nod är barnet .

Syskonnoder ( syskonnod) - noder som är på samma kapslingsnivå i förhållande till sin överordnade nod. I vårt diagram är syskonnoderna och ,

Den översta noden i DOM kallas roten. I vårt diagram är det roten (eftersom dokumentobjektet inte är en del av DOM).


Dokumentstruktur

Du kan tänka på HTML som en serie kapslade rutor. Taggar verkar innehålla andra taggar, som i sin tur inkluderar taggar eller text. Här är ett exempeldokument från föregående kapitel:

Min startsida Min startsida

Hej, jag heter Marijn och det här är min hemsida.

Och jag skrev också en bok! Läs den här.

Den här sidan har följande struktur:

Datastrukturen som webbläsaren använder för att presentera ett dokument återspeglar dess form. För varje ruta finns ett objekt som vi kan interagera med och ta reda på olika data om det - vilken tagg den representerar, vilka rutor och text den innehåller. Denna representation kallas Document Object Model, eller förkortat DOM.

Vi kan komma åt dessa objekt genom dokumentets globala variabel. Dess documentElement-egenskap hänvisar till objektet som representerar taggen. Det ger också huvud- och kroppsegenskaper, som innehåller objekt för motsvarande element.

Träd Återkallar syntaxträd från kapitel 11. Deras struktur är anmärkningsvärt lik strukturen i ett webbläsardokument. Varje nod kan länka till andra noder, och varje gren kan ha sin egen gren. Denna struktur är ett typiskt exempel på kapslade strukturer, där element innehåller delelement som liknar dem själva.

Vi kallar en datastruktur för ett träd när den förgrenar sig, inte har några loopar (en nod kan inte innehålla sig själv) och har en enda distinkt "rot". När det gäller DOM är roten document.documentElement.

Träd finns ofta inom beräkningsvetenskap. Förutom att representera rekursiva strukturer som ett HTML-dokument eller -program, används de ofta för att arbeta med sorterade datauppsättningar eftersom element vanligtvis är lättare att hitta eller infoga i ett sorterat träd än i en sorterad endimensionell array.

Ett typiskt träd har olika noder. Äggspråkets syntaxträd hade variabler, värden och applikationer. Applikationer hade alltid underordnade grenar, och variabler och värden var "löv", det vill säga noder utan underordnade grenar.

Detsamma gäller för DOM. Noder för vanliga element som representerar HTML-taggar, bestämma strukturen för dokumentet. De kan ha barnnoder. Ett exempel på en sådan nod är document.body. Några av dessa underordnade noder kan vara löv - till exempel text eller kommentarer (i HTML-kommentarer skrivet mellan tecken).

Varje DOM-nodobjekt har en nodeType-egenskap, som innehåller en numerisk kod som identifierar nodtypen. För vanliga element är det lika med 1, vilket också definieras som ett konstant egenskapsdokument.ELEMENT_NODE. För textnoder som representerar textpassager är det lika med 3 (document.TEXT_NODE). Kommentarer har 8 (document.COMMENT_NODE).

Det vill säga, här är ett annat sätt att grafiskt representera dokumentträdet:

Bladen är textnoder och pilarna visar far-barn-relationerna mellan noderna.

Standard Att använda kryptiska siffror för att representera nodtyp är inte ett tillvägagångssätt i JavaScript-stil. Senare kommer vi att möta andra delar av DOM-gränssnittet som också verkar främmande och besvärliga. Anledningen är att DOM inte designades bara för JavaScript. Den försöker definiera ett språkoberoende gränssnitt som kan användas i andra system - inte bara HTML utan även XML, som är ett dataformat allmänt syfte med en syntax som påminner om HTML.

Det visar sig vara obekvämt. Även om standarder är en mycket användbar sak, är fördelen med språkoberoende i vårt fall inte så användbar. Det är bättre att ha ett gränssnitt som är väl anpassat till språket du använder än ett gränssnitt som är bekant på alla språk.

För att illustrera den besvärliga integrationen med språket, överväg egenskapen childNodes som DOM-noder har. Den innehåller ett arrayliknande objekt med en length-egenskap och numrerade egenskaper för åtkomst av barnnoder. Men det här är en instans av typen NodeList, inte en riktig array, så den har inte metoder som forEach.

Det finns också problem förknippade med dålig design av systemet. Du kan till exempel inte skapa ny nod och lägg omedelbart till egenskaper eller underordnade noder till den. Först måste du skapa den, sedan lägga till barn en efter en och slutligen tilldela egenskaper en efter en, med hjälp av biverkningar. Kod som samarbetar nära med DOM visar sig vara lång, ful och med många upprepningar.

Men dessa problem är inte dödliga. JavaScript låter dig skapa abstraktioner. Lätt att skriva hjälpfunktioner, vilket gör att verksamheten kan uttryckas tydligare och mer koncist. I allmänhet tillhandahåller den här typen av verktyg många bibliotek som syftar till att programmera för webbläsaren.

Tree Traversal DOM-noder innehåller många referenser till närliggande noder. Detta visas i diagrammet:

Även om endast en länk av varje typ visas här, har varje nod en parentNode-egenskap som pekar på dess överordnade nod. Varje elementnod (typ 1) har också en childNodes-egenskap som pekar på ett arrayliknande objekt som innehåller dess undernoder.

I teorin kan du gå till vilken del av trädet som helst med endast dessa länkar. Men JavaScript ger oss många ytterligare hjälplänkar. Egenskaperna firstChild och lastChild pekar på det första och sista underordnade elementet, eller är null för de noder som inte har några underordnade. previousSibling och nextSibling pekar på angränsande noder - noder som har samma förälder som den aktuella noden, men är omedelbart före eller efter den nuvarande i listan. Den första nodens previousSibling-egenskap kommer att vara null, och den sista nodens nextSibling-egenskap kommer att vara null.

Rekursiva funktioner är användbara när man arbetar med sådana kapslade strukturer. Följande söker i dokumentet efter textnoder som innehåller den givna strängen och returnerar true när den hittar den:

Funktion talksAbout(nod, sträng) ( if (node.nodeType == document.ELEMENT_NODE) ​​(för (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, "böcker")); // → sant

Text Node Properties nodeValue innehåller en textrad. Hitta element Det är ofta användbart att navigera genom dessa föräldra-, barn- och syskonlänkar och gå igenom hela dokumentet. Men om vi behöver en specifik nod i ett dokument är det väldigt obekvämt att gå igenom den, med start från document.body och dumt nog genom den väg som är hårdkodad i koden. Genom att göra detta gör vi antaganden i programmet om dokumentets exakta struktur - som vi senare kanske vill ändra. En annan komplicerande faktor är att textnoder skapas även för mellanrum mellan noder. I exempeldokumentet body tag

inte tre barn (h1 och två p), utan så många som sju: dessa tre plusmellanslag före, efter och mellan dem.

Var länk = document.body.getElementsByTagName("a"); console.log(länk.href);

Alla elementnoder har en getElementsByTagName-metod som samlar in alla element med en given tagg som är ättlingar (direkta eller indirekta ättlingar) till den noden och returnerar den som ett arrayliknande objekt.

För att hitta en specifik nod kan du ge den ett id-attribut och använda metoden document.getElementById.

Min struts Gertrud:

Den tredje metoden är getElementsByClassName, som, liksom getElementsByTagName, söker igenom innehållet i elementnoden och returnerar alla element som innehåller den angivna strängen i sin klass.

Ändra dokument Nästan allt i DOM-strukturen kan ändras. Elementnoder har en uppsättning metoder som används för att modifiera dem. Metoden removeChild tar bort den angivna underordnade noden. För att lägga till en nod kan du använda appendChild, som lägger till noden i slutet av listan, eller insertBefore, som lägger till noden som skickades som det första argumentet innan noden skickades som det andra argumentet.

var paragraphs = document.body.getElementsByTagName("p");

document.body.insertBefore(stycken, stycken);

En nod kan bara finnas på ett ställe i ett dokument. Så genom att infoga stycket "Tre" före stycket "Ett" tar vi faktiskt bort det från slutet av listan och infogar det i början, och vi får "Tre/En/Två". Alla operationer för att infoga en nod kommer att leda till att den försvinner från dess nuvarande position (om den hade en).

Metoden replaceChild används för att ersätta en underordnad nod med en annan. Den accepterar två noder: den nya och den som behöver bytas ut. Noden som ska ersättas måste vara ett underordnat element vars metod vi anropar. Både replaceChild och insertBefore förväntar sig en ny nod som deras första argument.

Skapa noder I följande exempel måste vi skapa ett skript som ersätter alla bilder (taggar) i dokumentet med texten som finns i deras "alt"-attribut, vilket anger en alternativ textrepresentation av bilden.

För att göra detta behöver du inte bara ta bort bilderna, utan också lägga till nya textnoder för att ersätta dem. För att göra detta använder vi metoden document.createTextNode. Detta .

V

Ersätta

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

Givet en sträng ger createTextNode oss en DOM-nod typ 3 (text) som vi kan infoga i dokumentet för att visa på skärmen.

Om du behöver arbeta med en fast lista med noder istället för en live, kan du konvertera den till en riktig array med segmentmetoden.

Var arrayish = (0: "en", 1: "två", längd: 2); var real = Array.prototype.slice.call(arrayish, 0); real.forEach(function(elt) ( console.log(elt); )); // → en // två

För att skapa elementnoder (typ 1) kan du använda document.createElement. Metoden tar ett taggnamn och returnerar en ny tom nod av den givna typen. Följande exempel definierar verktyget elt, som skapar en elementnod och använder de återstående argumenten som dess underordnade. Denna funktion används sedan för att lägga till ytterligare information till offerten.

Ingen bok blir någonsin färdig. Vi lär oss tillräckligt när vi arbetar med det för att finna det omoget så fort vi lämnar det.< 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"));

funktion elt(typ) ( var nod = document.createElement(typ); för (var i = 1; i

Attribut Vissa attributelement, som href för länkar, kan nås via objektegenskapen med samma namn. Detta är möjligt för ett begränsat antal vanliga standardattribut. Men HTML låter dig tilldela alla attribut till noder. Detta är användbart eftersom... låter dig lagra ytterligare information

i dokumentet. Om du kommer på dina egna attributnamn kommer de inte att vara bland egenskaperna för elementnoden. Istället måste du använda metoderna getAttribute och setAttribute för att arbeta med dem.

Startkod 00000000.

Katten har fyra ben.

var paras = document.body.getElementsByTagName("p"); Array.prototype.forEach.call(paras, function(para) ( if (para.getAttribute("data-classified") == "hemlig") para.parentNode.removeChild(para); )); Jag rekommenderar att du sätter "data-" framför namnen på uppfunna attribut för att se till att de inte kommer i konflikt med andra. Som enkelt exempel vi kommer att skriva syntaxmarkering som letar efter taggar ("preformatted" – används för kod och

Funktion highlightCode(nod, nyckelord) ( var text = node.textContent; node.textContent = ""; // Rensa noden var matchning, pos = 0; while (match = keywords.exec(text)) ( var before = text . slice(pos, match.index); keywords.lastIndex; ) var after = text.slice(pos node.appendChild(document.createTextNode(after));

HighlightCode-funktionen tar en nod OCH ett vanligt tecken (med den globala inställningen aktiverad) som matchar programmeringsspråkets nyckelord som innehåller elementet.

Egenskapen textContent används för att hämta all text i noden och sätts sedan till den tomma strängen, vilket rensar noden. Vi går igenom alla förekomster av nyckelordsuttrycket, lägger till text mellan dem i form av enkla textnoder och lägger till matchande text (sökord) genom att omsluta dem i element (fetstil).

Vi kan automatiskt markera hela sidkoden genom att gå igenom alla element som har attributet data-language, och anropa highlightCode på var och en med korrekt reguljärt uttryck.

Var languages ​​= (javascript: /\b(funktion|retur|var)\b/g /* … etc */ ); function highlightAllCode() ( var pres = document.body.getElementsByTagName("pre"); för (var i = 0; i< pres.length; i++) { var pre = pres[i]; var lang = pre.getAttribute("data-language"); if (languages.hasOwnProperty(lang)) highlightCode(pre, languages); } }

Här är ett exempel:

Och här är den, identifieringsfunktionen:

Funktion id(x) ( return x; ) highlightAllCode();

Det finns ett vanligt förekommande attribut, klass, vars namn är ett nyckelord i JavaScript. Av historiska skäl, när äldre JavaScript-implementeringar inte kunde hantera egenskapsnamn som matchade nyckelord, är detta attribut tillgängligt via en egenskap som heter className. Du kan också komma åt den med dess riktiga namn "klass" genom metoderna getAttribute och setAttribute.

Layout Du kanske har märkt det olika typer element är ordnade på olika sätt. Vissa gillar stycken

Och rubriker sträcker sig över hela dokumentets bredd och visas på separata rader. Sådana element kallas blockelement. Andra som länkar eller fet text visas på samma rad som den omgivande texten. De kallas inbyggda (inline).

För alla dokument kan webbläsare bygga ett arrangemang av element, en layout där varje kommer att ha en storlek och position baserat på dess typ och innehåll. Denna layout används sedan för att skapa dokumentets utseende.

Storleken och positionen för ett element kan hittas genom JavaScript. Egenskaperna offsetWidth och offsetHeight anger storleken i pixlar som upptas av elementet. Pixel är den grundläggande måttenheten i webbläsare, och motsvarar vanligtvis storleken på den minsta punkten på skärmen. På liknande sätt anger clientWidth och clientHeight storleken på insidan av ett element, utan att räkna gränsen (eller, som vissa säger, trottoarkanten).

Jag är i en låda

var para = document.body.getElementsByTagName("p");

console.log("clientHeight:", para.clientHeight);

console.log("offsetHeight:", para.offsetHeight);

Det mest effektiva sättet att ta reda på den exakta platsen för ett element på skärmen är metoden getBoundingClientRect. Det returnerar ett objekt med egenskaper upptill, botten, vänster och höger som innehåller elementets position i förhållande till skärmens övre vänstra hörn i pixlar. Om du behöver få dessa data i förhållande till hela dokumentet måste du lägga till den aktuella rullningspositionen, som finns i de globala variablerna pageXOffset och pageYOffset.

Att analysera ett dokument är en svår uppgift. Av hastighetsskäl bygger webbläsarmotorer inte om dokumentet varje gång det ändras, utan väntar så länge. hur är detta möjligt. När JavaScript-programmet som modifierade dokumentet slutar köras måste webbläsaren beräkna en ny sidlayout för att visa det ändrade dokumentet på skärmen. När ett program begär positionen eller storleken på något genom att läsa egenskaper som offsetHeight eller anropa getBoundingClientRect, måste layouten också beräknas för att ge korrekt information.< 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

Ett program som regelbundet läser DOM-layouten och modifierar DOM kommer att tvinga webbläsaren att räkna om layouten många gånger och kommer därför att vara långsam. I följande exempel finns det två olika program som konstruerar en rad med 2000 px breda X-tecken och mäter körtiden.

Bildens utseende i taggen eller det faktum att länken i taggen öppnar en ny sida när den klickas är relaterat till typen av element. Men de grundläggande stilarna förknippade med elementet, som textfärg eller understrykning, kan ändras av oss. Här är ett exempel på hur du använder stilegenskapen:

Grön länk

Style-attributet kan innehålla en eller flera egenskapsdeklarationer (färg), följt av ett kolon och ett värde. Vid flera deklarationer separeras de med semikolon: "color: red; gräns: ingen".

Många saker kan ändras med hjälp av stilar. Till exempel styr egenskapen display om ett element visas i blockform eller inlineform.

Texten visas inline, som ett block, och syns inte alls.

Ett blockelement visas som ett separat block, och det senare är inte synligt alls – display: ingen inaktiverar visningen av element. På så sätt kan du dölja element. Detta är vanligtvis att föredra fullständigt avlägsnande dem från dokumentet, eftersom det är lättare att visa dem igen senare om det behövs.

JavaScript-kod kan agera direkt på ett elements stil genom nodens stilegenskap. Den innehåller ett objekt som har egenskaper för alla stilegenskaper. Deras värden är strängar som vi kan skriva till för att ändra någon aspekt av elementets stil.

Skönhet

var para = document.getElementById("para");

console.log(para.stil.färg); para.style.color = "magenta"; Vissa stilegenskapsnamn innehåller bindestreck, till exempel font-family. Eftersom de skulle vara obekväma att arbeta med i JavaScript (du skulle behöva skriva stil["font-family"]), skrivs namnen på egenskaperna i stilobjektet utan bindestreck, och visas istället i dem

versaler
: style.fontFamily

Cascading Styles Stilsystemet i HTML kallas CSS (Cascading Style Sheets). En stilmall är en uppsättning stilar i ett dokument. Det kan skrivas inuti en tagg:

stark (typsnittsstil: kursiv; färg: grå; )

Nu är texten på den starka taggen snett och grå.

I CSS är det möjligt att inte bara ställa in namnet på taggarna. Regeln för .abc gäller för alla element som har klassen "abc" specificerad. #xyz-regeln gäller för ett element med ett id-attribut lika med "xyz" (id-attribut måste göras unika för dokumentet).

Subtil ( färg: grå; font-size: 80%; ) #header ( bakgrund: blå; färg: vit; ) /* Element p som har klasserna a och b och id satt till main */ p.a.b#main ( margin-bottom : 20px)

Prioriteten för de senaste reglerna fungerar när reglerna har samma granularitet. Det är ett mått på hur noggrant det beskriver de stödberättigade elementen, bestämt av antalet och typen av elementära aspekter som krävs. Till exempel är regeln för p.a mer detaljerad än reglerna för p eller just.a, och kommer att ha företräde.

Notationen p > a (...) gäller för alla taggar som finns inuti taggen och är dess direkta ättlingar.
p a (...) gäller även för alla taggar inom, oavsett om det är ett direkt underordnat eller inte.

Frågeväljare Vi kommer inte att använda stilmallar mycket i den här boken. Att förstå hur de fungerar är avgörande för webbläsarprogrammering, men en detaljerad förklaring av alla deras egenskaper skulle ta 2-3 böcker. Huvudorsaken bekanta dig med dem och med syntaxen för väljare (poster som avgör vilka element reglerna gäller) - vi kan använda samma effektiva minispråk för att söka efter DOM-element.

Metoden querySelectorAll, som finns på både dokumentobjektet och nodelementen, tar en väljarsträng och returnerar ett arrayliknande objekt som innehåller alla element som matchar det.

Jag älskar åskväder i början av maj

När vårens första åska

Som om man leker och leker

Mullrar på den blå himlen.

funktion count(selector) ( return document.querySelectorAll(selector).length; ) console.log(count("p")); // Alla element

// → 4 console.log(count(".djur")); // Djurklass // → 2 console.log(count("p .djur")); // Djurklass inne

// → 2 console.log(count("p > .djur")); // Direkt barn

// → 1

Till skillnad från metoder som getElementsByTagName är objektet som returneras av querySelectorAll inte interaktivt. Det ändras inte om du ändrar dokumentet.

Metoden querySelector (utan Alla) fungerar på liknande sätt. Du behöver det om du behöver ett specifikt element. Den returnerar endast den första matchningen, eller null om det inte finns några matchningar.

Position och animering Placeringsegenskapen för stilar påverkar i hög grad placeringen av element. Som standard är det statiskt, vilket betyder att elementet är i sin normala position i dokumentet. När det är relativt tar elementet fortfarande plats, men nu kan de övre och vänstra egenskaperna användas för att flytta det i förhållande till dess normala position. När det är absolut tas elementet bort från det normala "flödet" av dokumentet - det vill säga det tar inte upp plats och kan överlappa med andra. Dessutom kan dess vänstra och övre egenskaper användas för att placera den absolut i förhållande till det övre vänstra hörnet av det närmaste omslutande elementet vars position inte är statisk. Och om det inte finns något sådant element, är det placerat i förhållande till dokumentet.

Vi kan använda detta för att skapa animationer. Följande dokument visar en bild av en katt som rör sig i en ellips.

var cat = document.querySelector("img");

var angle = 0, lastTime = null;

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

Bilden är centrerad på sidan och given position: relativ. Vi uppdaterar ständigt bildens övre och vänstra egenskaper för att få den att röra sig. Skriptet använder requestAnimationFrame för att anropa animeringsfunktionen varje gång webbläsaren är redo att rita om skärmen. Själva animeringsfunktionen anropar requestAnimationFrame igen för att schemalägga nästa uppdatering. När webbläsarfönstret (eller bokmärket) är aktivt kommer detta att resultera i uppdateringar med en hastighet av cirka 60 gånger per sekund, vilket möjliggör snygga animationer. Om vi ​​helt enkelt uppdaterade DOM i en loop, skulle sidan frysa och ingenting skulle vara synligt. Webbläsare uppdaterar inte sidan under

JavaScript fungerar , och får inte arbeta med sidan för närvarande. Det är därför vi behöver en requestAnimationFrame - den talar om för webbläsaren att vi är klara för nu och den kan göra sina webbläsargrejer som att uppdatera skärmen och svara på användarförfrågningar. Vår animationsfunktion är godkänd

Cirkulär rörelse utförs med hjälp av de trigonometriska funktionerna Math.cos och Math.sin. Jag kommer kortfattat att beskriva dem för dem som inte känner till dem, eftersom vi kommer att behöva dem senare.

Math.cos och Math.sin är användbara när du behöver hitta punkter på en cirkel med mittpunkten (0, 0) och radien ett. Båda funktionerna tolkar deras argument som en position på cirkeln, där 0 är punkten på cirkelns högra kant, sedan moturs tills en bana på 2π (cirka 6,28) tar oss runt cirkeln. Math.cos beräknar x-koordinaten för den punkt som är vår nuvarande position på cirkeln, och Math.sin ger y-koordinaten. Positioner (eller vinklar) större än 2π eller mindre än 0 är också tillåtna - rotationer upprepas så att a+2π betyder samma vinkel som a.

Använda sinus och cosinus för att beräkna koordinater Cat-animationen lagrar en vinkelräknare för animationens aktuella rotationsvinkel och ökar den proportionellt mot den förflutna tiden varje gång animeringsfunktionen anropas. Denna vinkel används för att beräkna den aktuella positionen för bildelementet. Toppstilen beräknas genom Math.sin och multipliceras med 20 - detta är den vertikala radien på vår ellips. Den vänstra stilen beräknas genom Math.cos och multipliceras med 200, så bredden på ellipsen är mycket större än höjden.

Stilar kräver vanligtvis måttenheter. I vårt fall måste vi lägga till px till numret för att förklara för webbläsaren att vi räknar i pixlar (och inte i centimeter, ems eller andra enheter). Det är lätt att glömma. Att använda siffror utan enheter kommer att göra att stilen ignoreras - om inte talet är 0, vilket är oberoende av enheterna.

Sammanfattning JavaScript-program kan undersöka och ändra det aktuella dokumentet som visas i webbläsaren genom en struktur som kallas DOM. Denna datastruktur representerar webbläsarens dokumentmodell, och ett JavaScript-program kan modifiera den för att ändra det synliga dokumentet. DOM är organiserat som ett träd, där element är ordnade hierarkiskt enligt dokumentets struktur. Elementobjekt har egenskaper av typen parentNode och childNodes, som används för orientering i trädet.

Utseendet på ett dokument kan ändras genom stilar, antingen genom att lägga till stilar till noder direkt, eller genom att definiera regler för vissa noder. Stilar har många egenskaper, som färg eller display. JavaScript kan påverka ett elements stil direkt genom dess stilegenskap.

Övningar Bygga en tabell Vi byggde tabeller från vanlig text i kapitel 6. HTML gör det enkelt att bygga tabeller. En tabell i HTML skapas med följande taggar:

namnhöjd land
Kilimanjaro 5895 Tanzania

Varje rad innehåller en tagg. Inuti den kan vi placera celler: antingen rubrikceller eller vanliga celler.

Samma data som vi använde i kapitel 6 är återigen tillgänglig i MOUNTAINS-variabeln.

Skriv en funktion buildTable som, med en array av objekt med samma egenskaper, bygger en DOM-struktur som representerar tabellen. Tabellen bör ha en rubrikrad där egenskapsnamnen är lindade i element, och det bör finnas en rad per arrayobjekt där dess egenskaper lindas i element. Det är här funktionen Object.keys kommer till nytta och returnerar en array som innehåller namnen på objektets egenskaper.

När du har grunderna nere, justera nummercellerna till höger genom att ändra deras style.textAlign-egenskap till "right".

/* Definierar stilar för vackra tabeller */ table ( border-collapse: collapse; ) td, th ( border: 1px solid black; padding: 3px 8px; ) th ( text-align: left; ) function buildTable(data) ( / / Din kod ) document.body.appendChild(buildTable(MONTAINS));

Element efter taggnamn Metoden getElementsByTagName returnerar alla underordnade element med det angivna taggnamnet. Gör din egen version av denna metod som en vanlig funktion som tar en nod och en sträng (taggnamn) och returnerar en array som innehåller alla fallande noder med det givna taggnamnet.

För att ta reda på namnet på ett elements tagg, använd tagName-egenskapen. Observera att detta kommer att returnera taggnamnet med versaler. Använd strängmetoderna toLowerCase eller toUpperCase.

En titel med ett spännelement inuti.

Ett stycke med ett eller två spännelement.

function byTagName(nod, tagName) ( // Din kod ) 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);

var cat = document.querySelector("#cat");

var hat = document.querySelector("#hat");
// Din kod här.
innerHTML
var text = element.innerHTML;

element.innerHTML = "";
Genom att tilldela en ny innerHTML skrivs koden över, även om det nya värdet läggs till det nuvarande (+=). Skript som läggs till på detta sätt körs inte.

yttreHTML
Innehåller hela elementet och kan inte ändras. Tekniskt sett skapar skrivning till den här egenskapen ett nytt element som ersätter det gamla. Referenser till det gamla elementet i variabler ändras inte.

data
textNode.data - innehållet i textnoder och kommentarer
textInnehåll

element.textContent - text inuti elementet utan taggar.

Det finns också en icke-standardegenskap som heter innerText, som har mycket gemensamt med textContent.
Element synlighet
dold

element.hidden = sant

Det dolda attributet stöds inte i IE11.
Attribut
De flesta standardattribut i DOM blir objektegenskaper:

element.id = "id"
För icke-standardattribut skapas inte egenskapen (odefinierad)
Du kan skapa dina egna DOM-egenskaper:
element.myData = (namn:"John", efternamn:"Smith");
och metoder:

element.myFunc = function())(alert this.nodeName);
Detta fungerar eftersom DOM-noder är vanliga JavaScript-objekt. Sådana icke-standardiserade egenskaper och metoder påverkar inte visningen av taggen och är endast synliga i JavaScript.
Åtkomst till taggattribut:
element.hasAttribute(namn)
element.getAttribute(namn)
element.setAttribute(namn, värde)

element.removeAttribute(name)
element.attributes är en pseudo-array av attribut.

Attribut är skiftlägesokänsliga (html), medan egenskaper är skiftlägeskänsliga (javaScript).
Attributvärdet är alltid en sträng.
Attribute: a.getAttribute("href") - visar exakt vad som finns i HTML

Egenskap: a.href - kan skilja sig från attributvärdet

Oftast beror en egenskap på ett attribut, men inte vice versa. Att ändra egenskapen påverkar inte attributet.
Arbeta med klasser
Klassattributet motsvarar två egenskaper:

className - sträng
classList — objekt
classList-objektmetoder:
element.classList.contains("klass") - kontrollerar om ett objekt innehåller en given klass
element.classList.add("klass")

element.classList.remove("klass") element.classList.toggle("klass").

classList är en pseudo-array, den kan itereras igenom

för slinga dataattribut Beställnings
dataattribut
tillgängliga inte bara som attribut, utan också via datauppsättningsegenskapen

data-about = "något värde"

element.dataset.om
Nodordning

nodeA.compareDocumentPosition(nodeB) - Ger information om innehållet och den relativa ordningen av element. Returvärdet är en bitmask:

Lägga till och ta bort noder

var div = document.createElement("div")
document.createTextNode("text")

parent.appendChild(element) - elementet läggs till i slutet av det överordnade
parent.insertBefore(element, nextSibling) - elementet läggs till före nextSibling
parent.insertBefore(element, parent.firstChild) - läggs till i början
parent.insertBefore(element, null) - kommer att fungera som appendChild
Alla insättningsmetoder returnerar den infogade noden.
När du flyttar ett element behöver du inte först ta bort det från dess gamla plats. Insättningsmetoden gör detta automatiskt.

element.insertAdjacentHTML(where, html) - infogar godtycklig HTML-kod var som helst i dokumentet. Where anger var html ska infogas i förhållande till elementet - beforeBegin, afterBegin, beforeEnd, afterEnd.
element.insertAdjacentElement(where, newElement)
element.insertAdjacentText(where, text)
De två sista metoderna stöds inte i Firefox

node.append(...noder) – infogar noder i slutet av nod ,
node.prepend(...nodes) – infogar noder i början av nod ,
node.after(...nodes) – infogar noder efter nodnod,
node.before(...noder) – infogar noder före nodnoden,
node.replaceWith(...nodes) – infogar noder istället för node .
här är noder noder eller strängar, i valfri kvantitet och kombination, listade avgränsade med kommatecken.

var fragment = document.createDocumentFragment() - simulerar en DOM-nod som, när den infogas i ett dokument, försvinner och bara lämnar dess avkomlingar. I moderna webbläsare rekommenderas inte.

element.cloneNode(true) - djup kopia av elementet
element.cloneNode(false) - kopia utan underordnade element

parent.removeChild(element)
parent.replaceChild(newElement, element)
element.remove() - tar bort ett element direkt, utan referens till dess överordnade.
Metoder returnerar fjärrnoden

Huvudverktyget för att arbeta och dynamiska ändringar på sidan är DOM (Document Object Model) - en objektmodell som används för XML/HTML-dokument.

Enligt DOM-modellen är ett dokument en hierarki.
Varje HTML-tagg bildar ett separat nodelement, varje textstycke bildar ett textelement, etc.

Enkelt uttryckt är DOM en representation av ett dokument som ett träd av taggar. Detta träd bildas av en kapslad struktur av taggar plus textfragment av sidan, som var och en bildar en separat nod.

Den enklaste DOM

Låt oss först bygga DOM-trädet för nästa dokument.

Titel: Utmärkt dokument

Den yttersta taggen är , så trädet börjar växa därifrån.

Det finns två noder inuti: och - de blir undernoder av .

Taggar form elementnoder(elementnod). Text presenterad textnoder(textnod). Båda är lika noder i DOM-trädet.

Mer komplicerat exempel

Låt oss nu titta på en viktigare sida:

Om älg Sanningen om älg.

  • Älg är ett listigt djur
  • .. Och lömsk
  • Rotelementet i hierarkin är html. Han har två ättlingar. Den första är huvud, den andra är kropp. Och så vidare, varje kapslad tagg är underordnad taggen ovan:

    I den här figuren indikerar blått nodelement, svart indikerar textelement.

    Trädet bildas av blå nodelement - HTML-taggar.

    Och så här ser ett träd ut om du ritar det direkt på en HTML-sida:

    Förresten, trädet i denna figur tar inte hänsyn till text som bara består av blanksteg. Till exempel bör en sådan textnod komma direkt efter . En DOM som inte innehåller sådana "tomma" noder anropas "normaliserad".

    Låt oss titta på ett lite mer komplext dokument.

    Dokumentdata

    • Försiktigt
    • Information
    Tillverkad i Ryssland

    Den översta taggen är html, den har barns huvud och kropp, och så vidare. Detta resulterar i ett taggträd:

    Attribut

    I det här exemplet har noderna följande attribut: style , class , id . Generellt sett anses attribut också vara noder i DOM vars förälder är DOM-element, där de anges.

    Men i webbprogrammering går de vanligtvis inte ner i den här djungeln och anser att attribut helt enkelt är egenskaperna hos en DOM-nod, som, som vi kommer att se senare, kan ställas in och ändras på begäran av programmeraren.

    Egentligen är detta en hemlighet, men DOCTYPE är också en DOM-nod och ligger i DOM-trädet till vänster om HTML-koden (detta är dolt i bilden).

    P.S. Det är naturligtvis ett skämt om hemligheten, men alla vet inte riktigt om det. Det är svårt att tänka på var sådan kunskap kan vara användbar...

    Normalisering i olika webbläsare

    När du analyserar HTML Internet Explorer skapar omedelbart normaliserats DOM där noder inte skapas från tom text.

    Firefox har en annan åsikt, den skapar ett DOM-element från varje textfragment.
    Därför ser trädet för detta dokument i Firefox ut så här:

    I figuren, för korthetens skull, indikeras textnoder helt enkelt med en hash. kroppen har 7 barn istället för 3.

    Opera har också något att skryta med. Hon kan lägga till ett extra tomt element "bara från sig själv".

    Öppna dokumentet för att se detta. Den returnerar antalet underordnade noder för document.body , inklusive textnoder.

    Jag får 3 för IE, 7 för Firefox och 8 (!?) för Opera.

    I praktiken skapar denna inkompatibilitet inte stora problem, men du måste komma ihåg det. Skillnaden kan till exempel visa sig i fallet med uppräkning av trädnoder.

    Möjligheterna som DOM ger

    Varför, förutom vackra teckningar, behöver vi en hierarkisk DOM?

    Mycket enkelt:

    Varje DOM-element är ett objekt och tillhandahåller egenskaper för att manipulera dess innehåll, för åtkomst till föräldrar och barn.

    Dokumentobjektet används för DOM-manipulation.
    Med hjälp av dokument kan du få önskat trädelement och ändra dess innehåll.

    Till exempel får den här koden det första elementet med ol-taggen, tar bort två listelement i följd och lägger sedan till dem i omvänd ordning:

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

    För ett exempel på hur ett sådant manus fungerar, klicka på texten på älgsidan

    I gamla handledningar och skript kan du se hur du ändrar HTML-koden för en sida direkt genom att anropa document.write .

    I moderna skript används denna metod nästan aldrig korrekt tillämpning kan räknas på en hand.

    Undvik document.write.. Förutom när du verkligen vet vad du gör (varför läser du en handledning då - du är redan en guru)

    Låt oss ta en närmare titt på åtkomstmetoder och egenskaper för DOM-element.

    Tillgång till element

    Alla DOM-åtkomster och ändringar kommer från dokumentobjektet.

    Låt oss börja på toppen av trädet.

    document.documentElement

    Den översta taggen. I fallet med en korrekt HTML-sida kommer detta att vara .

    document.body

    Tagg, om den finns i dokumentet (måste finnas).

    Följande exempel, när en knapp klickas, producerar en textrepresentation av document.documentElement- och document.body-objekten. Strängen i sig beror på webbläsaren, även om objekten är desamma överallt.

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

    Typer av DOM-element

    Varje element i DOM har en typ. Dess nummer lagras i attributet elem.nodeType

    Totalt finns det 12 typer av element i DOM.

    Vanligtvis används bara en: Node.ELEMENT_NODE, vars nummer är 1. Element av denna typ motsvarar HTML-taggar.

    Ibland är typen Node.TEXT_NODE också användbar, vilket är lika med 3. Dessa är textelement.

    Andra typer i javascript programmering används inte.

    Följande exempel, när du klickar på en knapp, kommer att skriva ut typerna av document.documentElement och sedan typen av det sista underordnade av noden document.body. Detta är en textnod.

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

    Exempel

    Så här skulle till exempel dokumentet från exemplet ovan se ut i en webbläsare om varje synligt element var omgivet av en ram med ett nodeType-nummer i det övre högra hörnet.

    ...Data

    • Försiktigt
    • Information
    Tillverkad i Ryssland

    Endast elementen inuti kroppen visas här, eftersom de är de enda som visas på sidan. För element av typ 1 (taggar) anges motsvarande tagg inom parentes för textelement (typ 3), det finns helt enkelt ett nummer.

    Barnelement
  • Alla underordnade element, inklusive textelement, finns i childNodes-matrisen.

    Följande exempel går igenom alla underordnade av document.body.

    For(var i=0; i BODY

    stil

    Den här egenskapen styr stilen. Detta liknar att ställa in en stil i CSS.

    Du kan till exempel ställa in element.style.width:

    Källkod för denna knapp:

    Äta allmän regel ersättningar - om CSS-attributet har bindestreck, för att ställa in stilen måste du ersätta dem med versal bokstäver

    Till exempel, för att ställa in z-index-egenskapen till 1000, måste du ställa in:

    Element.style.zIndex = 1000

    innerHTML

    Vid ett tillfälle stöddes den här egenskapen endast i IE. Nu stöder alla moderna webbläsare det.

    Den innehåller all HTML-kod inuti noden och kan ändras.

    InnerHTML-egenskapen används huvudsakligen för att dynamiskt ändra innehållet på en sida, till exempel:

    Document.getElementById("footer").innerHTML = "Hejdå!"

    InnerHTML är kanske en av de mest använda DOM-elementegenskaperna.

    klassnamn

    Den här egenskapen anger klassen för elementet. Det är helt likt "class" html-attributet.

    Elem.className = "nyklass"

    onclick, onkeypress, onfocus...

    Och andra egenskaper som börjar med "på..." butikshanterarfunktioner för motsvarande händelser. Du kan till exempel tilldela en hanterare onclick-händelser.

    För mer information om dessa egenskaper och händelsehanterare, se

    Denna publikation föregår ett antal artiklar om alternativa sätt arbetar med XML. "Alternativ", eftersom arbetet med XML i 1C som regel är begränsat xml-tolkning med sekventiell läsning - rad-för-rad-tolkning av textinnehåll. Men det finns andra sätt.

    Till exempel genom att använda XML-frågespråket xPath eller XSL-transformationsmallar. Dessa alternativ kommer att diskuteras i framtida artiklar. Men de förlitar sig alla på en grundläggande DOM-representation av XML-dokument. Vad är DOM (dokumentobjektmodell) och vi pratar i publikationen.

    DOM bygger på representationen av ett dokument av vilken struktur som helst i form av ett träd av noder, vars varje nod (nod) representerar ett element, ett attribut för ett element, ett elements textvärde etc. Sambandet mellan noder bygger på principen om "förälder - underordnade". Dokumentroten (DOM-trädet) har ingen förälder. Ett återvändsgränd element har inget barn (sådana element kallas abstrakt trädets löv). Således kan DOM skapas inte bara för XML, utan för praktiskt taget alla strukturerade dokument (HTML, XHTML). Så, till exempel, användarens webbläsare, som tar emot HTML-koden för en webbsida från Internet, bygger DOM-trädet för denna sida i RAM-minnet på användarens dator.

    DOM öppnar stora möjligheter för att manipulera dokumentdata. Du kan skapa nya noder, infoga dem på olika trädnivåer, kopiera noder, ta bort noder, söka efter noder med olika parametrar och mycket mer.

    DOM-modellen för ett XML-dokument visualiseras i figuren nedan.

    Alla moderna programmeringsspråk inkluderar verktyg (parsers) för att arbeta med ett sådant träd. XML-parsern tar emot stränginnehåll som indata och bygger ett träd av noder i RAM och utför manipulationer med träddata. Fördelen med detta tillvägagångssätt jämfört med rad-för-rad-analys är uppenbar: med en fråga till trädet kan du välja nödvändiga data utan att gå igenom hela dokumentet rad för rad, eftersom RAM-minnet innehåller en fullständig representation av elementen med alla relationer.

    I 1C-plattformen representeras DOM-modellen av ett specialobjekt DocumentDOM, som i sin tur är byggt med hjälp av BuilderDOM-objektet och dess Read-metod. Indata till denna metod är vanligtvis antingen en XML Reader eller ett HTML Reader-objekt, som direkt läser XML- eller HTML-textinnehåll från filer eller laddar det från en sträng. Jo, då finns det ett antal konstruktioner som låter dig extrahera data från objektmodellen för det lästa dokumentet.

    Av alla alternativ är det mest intressanta ur min synvinkel alternativ nr 1 med metoden CalculateXPathExpression. Nästa artikel kommer att ägnas åt honom.

    Fördelar med rad-för-rad-analys: behovet av resurser är mindre. Nackdelar: det tar lång tid att få data, du måste läsa hela filen rad för rad, programkodens komplexitet när du analyserar XML-dokument med en komplex struktur.

    Fördelen med sampling genom DOM: datasamplingshastighet, enkelhet i programkoden. Nackdelar: krävande resurser, spenderat på konstruktion och förfrågningar till DOM RAM och processorkraft.



    Om du upptäcker ett fel markerar du ett textstycke och trycker på Ctrl+Enter
  • DELA: