JavaScript

Einstieg ins DOM (JavaScript Tutorial)

Tutorial erstellt von Ingo, letzte Änderung am 22.08.2008

Die Lage

Es ist soweit: Wir, die hoffnungsvolle Zukunft des WWW, kennen uns einigermaßen in (X)HTML aus, haben uns
durch CSS gewühlt und auch die ersten JavaScript-Erfahrungen liegen bereits hinter uns -  und nun wollen
wir so richtig loslegen:
  • Wir wollen dem Besucher unserer Seite eine besonders neue Neuigkeit als kleine Haftnotiz "oben auf"
    der eigentlichen Homepage zeigen, zusammen mit einem Schließen-Button: sobald man darauf klickt,
    verschwindet die Notiz - wie geht so was?

  • Wir wollen den Nutzer beim Ausfüllen eines Formulars unterstützen, indem wir -je nach Eingabe-
    bestimmte Felder ausgrauen, andere aktivieren

  • Eine kleine Diashow auf unserer Homepage wäre nett, vielleicht mit einem <img ...>, dessen src
    (per Knopfdruck oder Timer) geändert wird - geht das überhaupt, nur mit JavaScript?



Das alles ist kein großes Problem, wenn wir erst einmal wissen, wie wir mit JavaScript an die Elemente
eines HTML-Dokuments herankommen, wenn möglich ohne Weiche, mit browserübergreifend gültigem Code
- und da kommt das Document Object Model (DOM) ins Spiel.  

Das DOM

Das DOM beschreibt, wie eine Programmiersprache auf die Elemente z.B. eines HTML-Dokuments zugreifen
können soll. Hierzu wird das HTML-Dokument mit seinen Elementen, dessen Attributen und Text-Portionen
als ein Baum mit Element-Knoten, Attribut-Knoten und Text-Knoten aufgefaßt. Die Knoten sind 'Objekte',
auf deren Eigenschaften und Methoden die Programmiersprache zugreift, um das Dokument zu untersuchen
oder auch zu ändern. - Hier soll es zunächst um Objekte gehen. Mehr zu Bäumen und Knoten vielleicht später.

Element  –  Tag  –  Attribut

Zur Erinnerung an die Begriffe: Ein HTML-Element besteht (meist) aus einem Anfangs- und einem Endtag.
Im Anfangstag stehen der Tagname und evtl. noch Attribute in Form von Name-Wert-Paaren:



Das O in DOM  –  Objekte

Ganz grob: Ein Objekt ist ein Ding mit Eigenschaften (Datenfeldern) und Methoden (objekteigenen
Funktionen). Ein Auto hat als Objekt betrachtet Eigenschaften wie z.B. Geschwindigkeit, Farbe, Tankfüllstand.
Als Methoden kämen in Frage: beschleunige(v), licht_an() usw. Objektorientiertes Autofahren sähe dann so aus:

Code:
var meinAuto = new Auto();                // so einfach geht das ;o)

if (meinAuto.Tankfüllstand > 0)
{
   meinAuto.licht_an();
   meinAuto.beschleunige(30);                // nix überstürzen
}


Elementobjekte

Die HTML-Elemente in einem Dokument werden vom DOM als (Element-)Objekte betrachtet, d.h. sie haben
Eigenschaften und Methoden. Um auf diese zugreifen zu können, beschaffen wir uns erst einmal das gewünschte
Elementobjekt, wofür das DOM 3 Wege vorsieht:
  1. document.getElementById

  2. document.getElementsByTagName

  3. document.getElementsByName
ById liefert ein Objekt (oder null), ByName und ByTagName hingegen liefern ein Array von Objekten - schließlich
kann es ja mehrere Elemente mit gleichem 'name' bzw. Tagnamen geben. Die Elemente stehen dann in der
Reihenfolge im Array, wie sie im HTML-Text vorkommen.
Elementobjekte haben eine ganze Reihe von Eigenschaften und Methoden. An dieser Stelle möchte ich niemanden
mit einer langen Liste langweilen. Mit den folgenden Eigenschaften lässt sich aber schon eine Menge anstellen:

  • Alle Attribute eines HTML-Elements stehen als Eigenschaft des entsprechenden Elementobjekts zur Verfügung:
    die Universattribute id, class als className (!), title, lang, dir, aber auch die elementspezifischen wie src (zu <img>),
    oder disabled (zu <option>).
    Welche Eigenschaften ein bestimmtes HTML-Element hat, erfährt man z.B. in SelfHTML unter dem Stichwort
    HTML-Elementobjekte.


  • Besondere Aufmerksamkeit verdient die Eigenschaft style: Sie gewährt uns Zugang zu den CSS-Eigenschaften
    des HTML-Elements. style ist dabei selbst ein Objekt, dessen Eigenschaften so heißen wie die CSS-Eigenschaften:
    background, border, color usw., float liegt vor als cssFloat (IE: styleFloat).

    Die Namen der CSS-Eigenschaften müssen in JavaScript angepasst werden. Dazu das '-' weglassen
    und das je nachfolgende Wort groß geschrieben anhängen: border-left-color wird zu borderLeftColor.
    Der Grund: In JavaScript bezeichnet das Minuszeichen immer den Minus-Operator. Das Zeichen darf
    deshalb nicht in Namen vorkommen.
    Außerdem: In JavaScript sind float und class reservierte Wörter und dürfen deshalb nicht als Namen verwendet werden; die Eigenschaften bekommen deshalb abgewandelte Namen, nämlich cssFloat bzw. className.

Kurze Beispiele - einige Einzeiler zur Gewöhnung


Code:
//Setze im div mit id 'meindiv' die Schriftfarbe:

    document.getElementById('meindiv').style.color = '#aaaaff';

/* document                                                                  // unser Dokument  
   document.getElementById('meindiv')                        // unser div als Objekt
   document.getElementById('meindiv').style               // die style-Eigenschaft des divs, selbst ein Objekt
  document.getElementById('meindiv').style.color        // die color-Eigenschaft des style-Objekts
*/

//Setze im 4. p-Element die Schriftfarbe:

    document.getElementsByTagName('p')[3].style.color = '#aaaaff';

//Setze 1.Element mit name="passwort" die Schriftfarbe:

    document.getElementsByName('passwort')[0].style.color = '#aaaaff';



Mit dem Element <img src="apfel001.jpg" alt="" id="apfelbild"> geht z.B. folgendes:

Code:
var meinBild = document.getElementById('apfelbild');

meinBild.style.borderColor = 'black';              // Schreibweise!
meinBild.style.display = 'block';

meinBild.src = 'apfelbild002.jpg';                   // Attribute sind als Eigenschaften verfügbar
meinBild.alt = 'Ein Apfelbild';                        
alert(meinBild.id);                                            // simples Debugging ;o)


Nun zu den anfangs erwähnten Anwendungen! Ich stelle keinen ausgefeilten, durchgestylten Komplettcode
vor, sondern jeweils den Teil des Codes, für den das DOM uns eine browserübergreifende Lösung bietet:

Wozu eigentlich ByName und ByTagName?

Die Objekte sind dabei schließlich nur über einen Array-Index erreichbar, und die Zuordnung Index <=> Objekt
kann sich bei jeder Änderung am Quelltext ebenfalls ändern. Es könnte also leicht zu Verwechslungen kommen. -
Arrays haben nun allerdings den Vorteil, dass man ihre Elemente mit Schleifen bequem abarbeiten kann:

Im Obst-Formular von oben sollen die Radio-Buttons gesperrt oder freigegeben werden je nachdem, ob die
Checkbox markiert ist:

Code:
  <form name="obstauswahl" action="">
    <input type="checkbox" id="ok" checked="checked" onClick="rbstate()">Wir möchten gerne folgendes Obst:<br>

    <input type="radio" name="sorte" value="apfel">Apfel<br>
    <input type="radio" name="sorte" value="birne">Birne<br>
    <input type="radio" name="sorte" value="mango">Mango<br>
    <input type="radio" name="sorte" value="pfirsich">Pfirsich<br>
    <input type="radio" name="sorte" value="zitrone">Zitrone<br>
    ...
  </form>

Mit 'onClick' rufen wir die Funktion 'rbstate', die das für uns erledigt:

Code:
function rbstate()
   {  var rb = document.getElementsByName('sorte');           // liefert Array der Radio-Buttons

      var state = document.getElementById('ok').checked;    // checked ist true/false. Möchten wir Obst?

      for (var n=0; n<rb.length; n++)                                       // Array.length, hier 5 (Radio-Buttons)
      {
        rb[n].disabled = !state;                                                 // wenn ja: disabled = false ('!' heißt 'not')
      }
   }


Eine einfache Galerie

Eine Mini-Galerie, bestehend aus einem wechselnden Bild und einem 'nächstes'-Button (wie im Bild oben)
könnte so realisiert werden:

Code:
  <img src="bild001.jpg" alt="" id="pic"> <br>

  <button type="button" onClick="nextpic()">nächstes</button>


Unsere Bilder (Dateinamen) speichern wir nun in einem Array. Welches Bild gerade gezeigt wird, merken wir
uns in 'bildnummer'. Der Eventhandler ruft dann 'nextpic', wo wir die Eigenschaft src des <img> setzen:

Code:
<script type="text/javascript">

   meineBilder = new Array('bild001.jpg','bild002.jpg','bild003.jpg');    // globale Bilderliste
   bildnummer = 0;

   function nextpic()
   {
      bildnummer++;
      if (bildnummer == meineBilder.length) bildnummer = 0;                     // Überlauf verhindern

      document.getElementById('pic').src = meineBilder[bildnummer];    // src auf nä. Bild setzen
   }

  </script>

Mit <body onLoad="window.setInterval('nextpic()', 1000)"> wechselt das Bild übrigens alle 1000 ms,
ganz von alleine ;o)
  

Das aktuelle Objekt  –  this

In diesem letzten Beispiel nutzen wir this, das für das aktuelle Objekt steht:

Code:
<div id="message">

  Neueste Neuigkeit, Werbung, Blubber...

  <button type="button" onClick="this.parentNode.style.display = 'none';">
    Close
  </button>

</div>

Betrachten wir den Eventhandler genauer:

Code:
this                                                       // das aktuelle Objekt, also der Button
this.parentNode                                  // das Elternobjekt, hier das div mit id 'message'
this.parentNode.style                          // das style-Objekt des divs
this.parentNode.style.display             // die Eigenschaft 'display' des styles unseres divs

Wenn wir den Button drücken, verschwindet also das div! Zauberei? Nein, CSS und DOM ;o)

Mit parentNode greife ich vor auf ein (in Arbeit befindliches) weiteres Tutorial, das sich dann etwas grundsätzlicher
mit dem Dokumentenbaum und den Nodes (Knoten) darin beschäftigt. Man kann nämlich sich von einem Node zur
Verwandtschaft bewegen (parents, siblings, children) und sogar die Struktur eines Dokuments ändern, also HTML-
Elemente per Script in ein Dokument einfügen oder daraus löschen...

Hin und wieder

... sieht man auch document.all.xyz oder document.layers.xyz. Auch damit kann man auf die Elemente eines
HTML-Dokuments zugreifen - wenn man kann! Das sind nämlich proprietäre Lösungen, will heißen: all ist eine
IE-Erfindung, layers stammt von Netscape. Und richtig: Der IE kennt layers nicht, und Netscape kennt weder all
noch (seit Version 6) layers. Diese Objekte sind also nicht nur veraltet, sondern auch relativ unpraktisch.

all und layers zwangen uns in der Vergangenheit zu Browserweichen; das DOM bietet nun einen browserübergreifenden
Standard - nutzen wir ihn!

Links

SelfHTML (auch als suchfreundliche chm-Datei), dort dann insbes. HTML-Elementobjekte.
DOM Level 1 Specs des W3C (Index), besonders Kapitel 2.5.4/5.  
Einen tiefen Blick in die Dokumentenstruktur ermöglicht die FireBug-Erweiterung des Firefox, dort der DOM-Inspector.


>> Allgemeine Fragen oder Probleme mit dem Tutorial? Hier gehts zum Forum!

Impressum / Datenschutzerklärung          © der-Webdesigner.net 2002 - 2008           top ▲