Erreiche, was du erreichen willst

Für unerfahrene JavaScript-Entwickler ist HTML ein Spielplatz:

HTML:
<a href="index.html" 
onmouseover="image1.src='1on.gif'" 
onmouseout="image1.src='1off.gif'">
<img src="1off.gif" name="image1" border="0" height="150" width="150" 
alt="Anfangsseite"></a> 

Die etwas erfahreneren gehen nicht ganz so weit:

HTML:
<a href="index.html" 
onmouseover="roll('home',1)" 
onmouseout="roll('home',0)">
<img src="home.gif" name="home" border="0" 
height="150" width="150" 
alt="Anfangsseite"></a> 

JavaScript:
// Bilder vorladen
homeoff = new Image(); 
homeoff.src = 'home.gif';
homeon = new Image(); 
homeon.src = 'homeoff.gif';
function roll(imgName,a) 
{
 imgState=a==0?eval(imgName + 'on.src'):eval(imgName + 'off.src');
 document.images[imgName].src = imgState;
}

Egal wie, wenn wir JavaScript Aufrufe im HTML einbinden, erschweren wir zukünftige Änderungen: Falls sich der Name der Funktion ändert, muß jedes HTML Dokument umgeschrieben werden. Ausserdem erstellen wir eine Menge Code für jeden einzelnen Bildwechsel, und vergrößern dadurch unnötigerweise das Dokument.

Hinfort! ihr JavaScript Geister!

Vergessen wir einen Augenblick lang dass fast jeder Bildwechseleffekt heutzutage per CSS erstellt werden kann, und nehmen wir an dass unser HTML unveränderbar das Folgende ist:

HTML:
<a href="index.html"><img src="home.gif" id="home" alt="Anfangsseite"></a>

Wie können wir einen Bildwechsel hervorrufen wenn die Maus sich über dem Bild befindet?

Kletterurlaub im Dokument

Jedes XML Dokument (und das beinhaltet HTML), hat eine bestimmte Baumstruktur. Ein Knoten (node) ist Teil dieses Baumes - genauso wie ein Dokument oder ein Verzeichnis im Windows Explorer ein Teil der Festplatte ist. Es gibt zwölf verschiedene Arten von Knoten[1]. In HTML sind allerdings nur drei wirklich interessant: element, TextNode und AttributeNode. Das Erste sind Seitenelemente, wie ein Verweis, das Zweite der Text innerhalb des Verweises und das Dritte zum Beispiel die Adresse, auf die der Verweis zeigt.

Unsere Kletterausrüstung

Wie haben mehrere Methoden und Attribute zur Verfügung, um uns durch das Dokument zu hangeln.

Methoden um ein bestimmtes Element zu erreichen

getElementById('elementID')
gibt uns das Element mit der ID elementID als ein Objekt.
getElementsByTagName('tag')
gibt uns alle Elemente mit dem Namen tag als ein Array.

Wir können diese nach Belieben mischen. Zum Beispiel:

document.getElementById('navigation').getElementsByTagName('a')[3];
	gibt uns den vierten Verweis innerhalb des Elements 
	mit der ID 'navigation'
document.getElementsByTagName('div')[2].getElementsByTagName('p')[0];
	gibt uns den ersten Textabsatz innerhalb des dritten DIV Elements

Attribute - unser Kletterwerkzeug

childNodes
gibt uns alle Knoten, die von dem abzweigen auf den wir uns gerade befinden, als Array. Es gibt firstChild und lastChild, als Abkürzungen für childNodes[0] und childNodes[this.childNodes.length-1].
parentNode
ist der Knoten von dem der derzeitige abzweigt.
nextSibling
ist der nächste Knoten auf der gleichen Ebene wie der, auf dem wir uns befinden.
previousSibling
der vorherige Knoten auf der gleichen Ebene wie der, auf dem wir uns befinden.

Auch diese Attribute können nach Belieben und Notwendigkeit gemischt werden.

JavaScript:
var other=document.getElementById('nav').childNodes[3].firstChild;
	gibt uns den ersten Knoten des vierten Knotens innerhalb
	des Elements mit der ID 'nav'.
var prevlink=o.parentNode.previousSibling.firstChild.childnodes[2];
	gibt uns den dritten Knoten innerhalb des ersten Knotens
	des vorherigen Knotens auf der gleichen Ebene wie das 
	Objekt o.

Attribute und Methoden um Elemente zu verändern

attributes
gibt uns ein Array mit allen Attributen des derzeitigen Elements zurück. Microsoft Internet Explorer unterstützt dieses Attribut erst seit Version 6.0.
data
gibt uns oder setzt den Textinhalt des Knotens
nodeName
gibt uns den Namen des Knotens, z.B. 'INPUT'
nodeType
gibt uns die Art des Knotens — 1 is ein Element, 2 ein Attribut und 3 Text.
nodeValue
gibt uns oder setzt den Wert des Knotens. Dieser Wert ist der Textinhalt bei Textknoten, das Attribut bei Attributknoten und null bei Elementen.
getAttribute(attribute)
gibt uns den Wert des Attributs attribute.
JavaScript:
var other=document.getElementById('nav').firstChild;
if(other.nodeType==3)
{
 other.data='newtext';
} 
if(other.nodeType==1)
{
 other.firstChild.data='newtext';
} 

Um das Bild in unserem Beispiel zu erreichen können wir entweder getElementsByTagName oder getElementById verwenden.

HTML:
<a href="index.html"><img src="home.gif" id="home" alt="home"></a>
JavaScript:
function findimg()
{
 var image;
 image=document.getElementById('home');
 if (image) 
  {
   image.style.border='3px dashed #ccc';
  }
}
oder:
function findimg()
{
 var imgs,i;
 imgs=document.getElementsByTagName('img');
 for(i in imgs)
 {
  if(/home.gif/.test(imgs[i].src))
   {
    imgs[i].style.border='3px dashed #ccc';
   }
  }
}

Die Verwendung von getElementById ist einfacher, da wir nicht durch alle Elemente gehen müssen um unseres zu finden. Wenn wir getElementsByTagName verwenden, brauchen wir ein Erkennungsmerkmal um unser Bild zu erreichen. In diesem Fall welches Bild geladen werden soll. Eine herkömlichere Art und Weise ist es auf eine bestimmte Klasse zu prüfen.

HTML:
<a href="index.html"><img src="home.gif" class="roll" alt="home"></a>
JavaScript:
function findimg()
{
 var imgs,i;
 imgs=document.getElementsByTagName('img');
 for(i in imgs)
  {
  if(/roll/.test(imgs[i].className))
   {
    imgs[i].style.border='3px dashed #ccc';
   }
  }
}

Was wir jetzt benötigen ist eine Funktion, die den Bildwechseleffekt hervorruft, und die nötigen Aufrufe hinzufügt.

function findimg()
{
 var imgs,i;
// gehe durch alle Bilder im Dokument
 imgs=document.getElementsByTagName('img');
 for(i=0;i<imgs.length;i++)
 {
// überprüfe ob die Klasse 'roll' vorhanden ist
  if(/roll/.test(imgs[i].className))
  {
// rufe die Funktion roll() auf wenn der Mauszeiger über
// dem Bild ist und wenn er es verlässt. Übergebe
// das Bild als Objekt.
   imgs[i].onmouseover=function(){roll(this);};
   imgs[i].onmouseout=function(){roll(this);};
  }
 }
}
function roll(o)
{
 var src,ftype,newsrc;
// überpfrüfe, on der Verweis des Bildes schon ein _on beinhaltet
// oder nicht. 
 src = o.src;
 ftype = src.substring(src.lastIndexOf('.'), src.length);
 if(/_on/.test(src))
 {
// falls dem so ist, lösche das _on.
  newsrc = src.replace('_on','');
 }else{
// anderweitig, füge das _on hinzu
  newsrc = src.replace(ftype, '_on'+ftype);
 }
 o.src=newsrc;
}
window.onload=function(){
 findimg();
}
Probier dieses Beispiel aus

So weit, so gut. Was wir allerdings vergessen haben sind Besucher, die keine Maus benutzen können. Um ebenfalls diese Besucher zu erreichen, müssen wir überprüfen ob der Verweis in dem das Bild sich befindet derzeit den Fokus hat oder nicht. Das Bild selbst ist per Tastatur nicht erreichbar.

Um den Verweis zu erreichen, können wir das parentNode Attribut überprüfen. Das ändert allerdings auch das Objekt, das wir an die roll() Funktion übergeben.

Daher müssen wir das Bild nochmals finden indem wir durch die Knoten innerhalb des Verweises gehen. Wir prüfen, ob der Knoten ein Bild ist indem wir nodeType und nodeName überprüfen. Das ist notwendig, da manche Webbrowser Leerzeilen im Dokument als Knoten erkennen, andere aber nicht.

function findimg()
{
 var imgs,i;
// gehe durch alle Bilder im Dokument
// überprüfe ob die Klasse 'roll' vorhanden ist
 imgs=document.getElementsByTagName('img');
 for(i=0;i<imgs.length;i++)
 {
  if(/roll/.test(imgs[i].className))
  {
// füge die Funktion roll() dem übergeordneten 
// Knoten hinzu.
  imgs[i].parentNode.onmouseover=function(){roll(this);};
  imgs[i].parentNode.onmouseout=function(){roll(this);};
  imgs[i].parentNode.onfocus=function(){roll(this);};
  imgs[i].parentNode.onblur=function(){roll(this);};
  }
 }
}
function roll(o)
{
 var i,isnode,src,ftype,newsrc,nownode;
// gehe durch alle Kindknoten
 for (i=0;i<o.childNodes.length;i++)
 {
  nownode=o.childNodes[i];
// falls der Knoten ein Bild ist, stoppe die Schleife und 
// definiere eine Variable
  if(nownode.nodeType==1 && /img/i.test(nownode.nodeName))
  {
   isnode=i;
   break;
  }
 }
// teste den Verweis des Bildes und fuege den Bildwechsel-
// effekt hinzu.
 src = o.childNodes[isnode].src;
 ftype = src.substring(src.lastIndexOf('.'), src.length);
 if(/_on/.test(src))
 {
  newsrc = src.replace('_on','');
 }else{
  newsrc = src.replace(ftype, '_on'+ftype);
 }
 o.childNodes[isnode].src=newsrc;
}
window.onload=function(){
 findimg();
}
Probiere dieses Beispiel mit der Tastatur aus.

Selbstversuche

Lade das das HTML Beispiel herunter und versuche Dich sich an einer der folgenden Aufgaben. Folge den Lösungsverweisen um eine mögliche Lösung zu sehen. Die Lösungsbeispiele beinhalten das notwendige JavaScript , was zwar nicht mit den Grundsätzen des barrierefreien JavaScripts übereinstimmt, aber einfacher zu lesen und verstehen ist.

  1. Ändere die Farbe einer jeden H2 Überschrift nach blau um. Lösung Farbänderung.
  2. Markiere jeden zweiten Paragraph mit einem schwarzen Rand. Lösung Randparagraph.
  3. Überprüfe welcher der Verweise im Dokument zu einem anderen Server führt (indem du prüfst ob in dem href Attribut die derzeitige Seite vorkommt - die derzeitige Seite ist in window.location.hostname gespeichert) und schreibe das Ziel des Verweises innerhalb von Klammern hinter den Verweis. Für den Moment, ändere den Inhalt des Links mittels des innerHTML Attributs des Verweises. Lösung Fremdverweise.
  4. Füge einen onclick Befehl zu jedem Verweis hinzu, der das Attribut target aufweist. Öffne den Verweis in einem 400 mal 400 Pixel großen Pop-Up Fenster. Lösung Pop-Up.

Verweise

[1] DOM Knotentypen: http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ core.html#ID-1950641247

Creative Commons License Unless otherwise expressly stated, all original material of whatever nature created by Christian Heilmann and included in this web site and any related pages is licensed under the Creative Commons License.