Logotyp för Björns studiewebb

Document Object Model (JavaScript)

Innehåll

På den webbsidan introduceras Document Object Model (DOM) Level 1 (DOM1). Bl.a. behandlas bakgrunden till DOM1 samt vad DOM faktiskt är. Här behandlas även begreppet diskret JavaScript (eng. unobtrusive JavaScript) och hur man "aktiverar" den (kopplar kod till webbsida).

Bakgrund

Netscape skapade JavaScript för att bl.a. kunna göra webbsidor mer interaktiva, vilket Microsoft (MS) hakade på (men kallade JScript). Så här långt var allt OK... tills MS bestämde sig för att gå sin egen väg, d.v.s. utveckla sin egen dokumentmodell (se nedan). Därmed hade vi två dokumentmodeller och webbutvecklare var tvungna att antingen göra två uppsättningar av webbsidor eller skriva två versioner av kod där modeller skiljde sig. Detta är vad som brukar kallas DOM Level 0 (DOM0).

Dokumentmodeller

En dokumentmodell är hur ett dokument är strukturerat, d.v.s. hur element (rubriker, stycken, länkar, m.m.) i ett dokument bl.a. kan refererars till i ett programspråk (så som JavaScript - se även sidan Objekt). Element i dokument brukar representeras av objekt, bl.a. då de kan innehålla text men även andra element. Objekten i DOM brukar kallas noder och placeras i ett träd - ett s.k. nodträd.

Specifikationerna DOM Core och DOM HTML

DOM används, som sagt, för att skapa en enhetlig dokumentmodell, d.v.s. underlätta utveckling av interaktiva webbsidor. Modellen, kan sägas, bestå av två delar:

Vad detta betyder är att vissa saker finns definierade i DOM Core-specifikationen medans andra i DOM HTML-specifikationen. Så om ni letar efter en komplett referens så måste ni eventuellt leta i två referenser... I denna underwebb försöker jag skapa en gemensam referens för dessa två specifikationer, men samtidigt visa på vilken specifikation som objekt (samt dess egenskaper och metoder) tillhör, skulle ni vilja "forska" vidare.

DOM och noder

När en webbklient läser in ett dokument, må det vara (X)HTML- eller XML-dokument, så skapar den ett nodträd med alla element i dokumentet. D.v.s. för varje rubrik (Hx), stycke (P), länkar (A) m.m. så skapas en motsvarande nod i nodträdet. Om element även innehåller text, som är synlig för besökare, och attribut (vilka inte är synliga) så skapas även noder för dessa. Observera att även mellanslag, tabbar och radbrytningar (s.k. white spaces) kan genererar textnoder!

Ett första exempel

Nedan visas ett enkelt HTML-dokument.

<!DOCTYPE html>
<html>
  <head>
    <title>Titel</title>
  </head>
  <body>
    <h1>Rubrik 1</h1>
    <p>Stycke 1</p>
    <p>Stycke 2 med <a href=...>länk</a></p>
  </body>
</html>

Exempel 1.1 - Enkelt XHTML-dokument

Ovanstående HTML-dokument resulterar i följande nodträd (enligt DOM Inspector i Firefox). Efter respektive nod visas nodtyp samt eventuellt innehåll inom "hakparenteser" ([ och ], samt något nedtonat - där är inte fel på dina ögon :-).

Den första noden, #document, motsvarar själva dokumentet och den första HTML-noden innehåller dokumenttyp för dokumentet (om t.ex. HTML, XHTML eller XML). Den andra HTML-noden är själva innehållet i dokumentet, d.v.s. HTML-taggen i dokumentet, som innehåller de två obligatoriska delarna: sidhuvud (HEAD) och sidkropp (BODY - den synliga delen av dokumentet).

Sidhuvudet innehåller endast (obligatoriska) titel medan sidkroppen innehåller den del av dokumentet som är synlig för besökare, d.v.s. stycken (P), rubriker (Hx), listor (OL/UL), m.m.. Observera ett antal #text som motsvarar radbrytning, m.m.!

En detalj att observera är att länkar (A) måste innehålla ett attribut HREF som är adressen som länk "pekar på". Men, som diskuteras nedan, så ska det ju finnas en motsvarande attributnod, vilket inte syns ovan. Jag har alltså inte glömt dem i trädet ovan utan de brukar faktiskt behandlas annorlunda från övriga typer av noder (vilket är förrvirrande!).

Till början på sida

Typer av noder

I DOM finns ett antal nodtyper, där vi främst är intresserade av de tre första i lista nedan. (Jag återkommer till varför de/lista är numrerad senare.)

  1. element (objekt)
  2. attribut (objekt, men kan även betraktas som sträng - se nedan)
  3. text (sträng)
  4. CDATA
  5. entitetsreferens
  6. entitetsnod
  7. processinstruktion
  8. kommentar
  9. dokument (objekt)
  10. dokumenttyp
  11. dokumentfragment (objekt)
  12. notation

Elementnoder

En elementnod (typ 1) motsvarar alltså ett element i ett (X)HTML-dokument, t.ex. stycken (P), rubriker (Hx), länkar (A) och betoningar (EM). Denna typ av nod kan innehålla andra noder och typiska exempel är de för taggarna HTML, HEAD och BODY, men även t.ex. stycken (P) och listor (OL/UL) som kan innehålla andra noder (element). Eftersom element kan ha attribut och innehålla text (data) så är det mycket vanligt, om inte regel, att elementnoder innehåller attribut- och/eller textnoder, utöver eventuella elementnoder.

Attributnoder

Attributnoder (typ 2) motsvarar attribut i (X)HTML-taggar, t.ex. HREF i länk (A) samt de mer övergripande attributen ID och CLASS som alla taggar har. Som nämnts ovan så behandlas attributnoder annorlunda från övriga typer av noder (i.a.f. element- och textnoder, som behandlas här). Det är bl.a. fullt möjligt att betrakta dem som värden i elementnoder och inte barnnoder (se Elementnoder nedan). Denna typ av noder kan inte innehålla andra noder och i s.k. DOM-granskare (DOM inspectors) så visas denna typ av noder inte som del av nodträd.

Textnoder

Eftersom element som rubriker (Hx) och stycken (P) kan innehålla text så motsvarar texten av textnoder (typ 3). I DOM-granskare så visas denna typ av noder som "#text" och denna typ av noder kan inte innehålla andra noder.

Observera att om t.ex. stycken (P) innehåller andra element, så som länkar (A), så är dess text oftast uppdelad i flera textnoder! I exempel i förra avsnittet så innehåller det andra stycket texten "Stycke 2 med länk", men eftersom ordet "länk" är en del av länkelementet (A) så tillhör detta ord motsvarande elementnod för länk. D.v.s. texten i andra stycket är två textnoder tillhörande två olika elementnoder: "Stycke 2 med " i P-noden och "länk" i A-noden. Skulle vi t.ex. vilja översätta stycket till ett annat språk så måste vi alltså ändra innehållet i två textnoder.

Övriga nodtyper

Övriga nodtyper, inte beskrivna ovan, fyller sin funktion de också, men de manipuleras inte så ofta (och definitivt inte i denna underwebb). De finns med i lista ovan för att göra referens komplett. (Se Referenser för mer information.)

Nodtypsnummer

Respektive nodtyp (element, attribut eller text) motsvaras alltså av ett nummer (vilket förklarar numreringen i listan ovan). Detta är användbart tillsammans med operatorn typeof, vilket visas i exempel nedan.

if((typeof minNod) == 1)
  //Gör något med elementnod
else if((typeof minNod) == 2)
  //Gör något med attributnod
else if((typeof minNod) == 3)
  //Gör något med textnod

Till början på sida

Diskret JavaScript

Förtroendet för JavaScript, och viljan att aktivera den i sin webbläsare, är ganska lågt hos många besökare på Internet. Men om webbutvecklare är villiga att ta till sig syftet med konceptet diskret JavaScript (eng. unobtrusive JavaScript) så kanske besökare kommer bli mer villiga att aktivera JavaScript.

Konceptet bygger på att webbplatser ska fungera oavsett om JavaScript (och även stilmallar, CSS) är aktiverat (eller fungerar) i besökares klient. Funktioner som erhålls med JavaScript ska även vara en utökning som ger besökare ett mervärde av att ha det aktiverat, d.v.s. JavaScript-funktion ska inte vara påträngande eller påtvingat.

För att diskret JavaScript ska fungera så lägger vi alltså till eventuell funktion med JavaScript när webbsida laddas, vilket vi bl.a. kan använda funktionen addLoadEvent() nedan till. Funktionen läggs till genom en (eller flera) "initieringsfunktioner" som bl.a. testar hur mycket klienten klarar av innan den går vidare.

Till början på sida

Funktionen addLoadEvent

Någon, som är intelligentare än mig, har tagit fram en funktion som lägger till funktioner som ska exekveras när en webbsida laddas, d.v.s. när händelsen "load" sker. Vi kopplar alltså dessa funktioner till fönstrets händelseattribut onload. Funktionen tillåter bl.a. att lägger till flera funktioner som ska exekveras när webbsida laddas (vilket är skälet till att jag tar upp den istället för att bara tilldela till window.onload :-).

Skriv av (eller kopiera) kod nedan och spara i en fil med namnet addloadevent.js (eller namn av eget tycke :-).

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func; //OBS: inga parenteser!
  }
  else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

Lägg sen till följande rad i (X)HTML-dokumentets HEAD-tagg för att länka in det externa dokumentet ovan (ändra namn på fil om du sparade med annat namn än addloadevent.js).

<script type="text/javascript" src="addloadevent.js"></script>

I en tredje fil (HTML-dokument är det första :-), t.ex. min_javascript.js, så placerar vi sen nedanstående kod plus alla funktioner som vi vill använda oss av. Observera att i anropet av funktionen addLoadEvent() så skriver vi inga parenteser efter vårt funktionsnamn, bara namnet!

addLoadEvent(minFunktion); //Koppla funktion till sidladdning
function minFunktion() {
  alert('Sida laddas');  //Ta bort när koppling fungerar...
  //Placera kod här som ska exekveras när sida laddas
}
//Övriga av dina funktioner här...

Kod som ska skrivas i funktionen minFunktion() ovan behandlas i kommande sidor. (Ta bort raden med alert() när du vet att koppling fungerar, d.v.s. att meddelanderuta visas. :-)

Lägg sen till även följande rad i (X)HTML-dokumentets HEAD-tagg för att länka in det externa dokumentet ovan (ändra namn på fil om du sparade med annat namn än min_javascript.js).

<script type="text/javascript" src="min_javascript.js"></script>

Ladda ner kod för exempel ovan.

Om funktionen/About the function

Denna funktion hittade jag i följande suveräna bok:/I found this function in the following excellent book:

Till början på sida

Referenser

Nedan finns några webbsidor/-platser med mer information om ämnet på denna webbsida.