Frühjahrsputz

Web-Entwicklung hat sich in den letzten Jahren drastisch verändert: Wir haben aufgehört, Darstellung mit Struktur zu mischen und es damit viel einfacher gemacht, eine Webseite nur durch Änderung des CSS-Dokuments komplett neu zu gestalten.

Weiterhin haben wir es geschafft, unsere Seiten noch sauberer zu halten, indem wir auf interne Stilbefehle und Klassen verzichten und stattdessen verschaltelte Selektoren verwenden.

HTML:
<table border="0" cellpadding="0" width="100%" cellspacing="5">
<tr>
 <td><font face="Arial" size="-2">Lorem Ipsum</font></td>
</tr>
</table>

wurde zu

CSS:
td.content {font-family:Arial,sans-serif;font-size:12px;}
HTML:
<table cellpadding="0" 
style="width:100%;border:none" cellspacing="5">
<tr>
 <td class="content">Lorem Ipsum</td>
</tr>
</table>

und letztendlich zu

CSS:
body {font-family:Arial,sans-serif;font-size:12px;}
p {padding:5px;}

HTML:
<p>Lorem Ipsum</p>

Um barrierefreie Seiten zu gestalten, muß diese Evolution auch für JavaScript stattfinden.

Trennung von HTML und JavaScript

Es gibt einige Regeln, die wir befolgen sollten um "barrierefreies JavaScript" zu schreiben.

Mische niemals JavaScript und HTML

Eine der größten Stärken von JavaScript ist, dass es als ein eigenes Dokument erstellt werden kann. Wie auch CSS erlaubt es, Funktionen in jedem Dokument einer Webseite zu verwenden. Änderungen des Verhaltens der Webseite müssen nur in einem Dokument anstatt von allen innerhalb der Seite vorgenommen werden. Ein weiteres Plus ist, dass der Webbrowser das Skript temporär speichert, es muss also nur einmal vom Server geladen werden. Das spart Servertraffic und macht die Seiten schneller für den Besucher.

Daher sollten - von Sonderfällen abgesehen - unsere HTML Dokumente nur das Folgende an JavaScript haben:

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

Das ist alles was nötig ist, kein eingebundenes JavaScript mehr. Wiederholen bitte!

Nutze JavaScript als Erweiterung, anstatt dich darauf zu verlassen

Wir sollten JavaScript nur verwenden, um eine bestehende Funktionalität zu verbessern. JavaScript kann abgeschaltet sein, oder von Sicherheitsmassnahmen wie Proxyservern in Hochsicherheitsumgebungen ausgefiltert werden.

Wir können uns niemals darauf verlassen, dass JavaScript ausgeführt werden kann.

Das bedeutet nicht, das wir kein JavaScript verwenden sollten. Es bedeutet lediglich, dass es eine Möglichkeit ist, keine Basis.

HTML:
<form action="index.php" onsubmit="return checkform(this)">
 <p><label for="login">Login:</label>
 <input type="text" name="login" id="login" /></p>
 <p><label for="pw">Passwort:</label>
 <input type="password" name="pw" id="pw" /></p>
 <p><input type="submit" value="send" /></p>
</form>
JavaScript:
function checkform(f)
{
 var error='';
 error+=f.login.value==''?'\nlogin':'';
 error+=f.pw.value==''?'\npassword':'';
 if (error!='')
 {
  alert('Bitte geben Sie das Folgende ein:'+error);
 } 
 return error=='';
}

Ist eine vollkommen legtitime Anwendung von JavaScript, die es dem Benutzer erspart, die Seite neu laden zu müssen wenn er vergessen hat einen Wert einzugeben.

HTML:
<form action="index.php">
 <p><label for="login">Login:</label>
 <input type="text" name="login" id="login" /></p>
 <p><label for="pw">Passwort:</label>
 <input type="password" name="pw" id="pw" /></p>
 <p><input type="button" onclick="checkform()" value="send" /></p>
</form>
JavaScript:
function checkform()
{
 var f=document.forms[0];
 var error='';
 error+=f.login.value==''?'\nlogin':'';
 error+=f.pw.value==''?'\npassword':'';
 if (error!='')
 {
  alert('Bitte geben Sie das Folgende ein:'+error);
 } else {
  f.submit();
 }
}

Dieses Beispiel hat augenscheinlich den gleichen Effekt, hat aber ein Problem: Wenn JavaScript abgeschaltet ist, hat der Knopf keinen Effekt, egal wie oft der frustrierte Besucher ihn anklickt. Wiederholen wir: Wir können uns nicht auf JavaScript verlassen.

Drum prüfe, wer sich ewig bindet...

Eine ganze Menge JavaScript Fehler enstehen lediglich dadurch, dass der Programmierer zu faul war zu prüfen ob eine Methode oder ein Objekt vorhanden ist bevor er es verwendet.

JavaScript:
function color(o,col)
{
 o.style.background=col;	
}

endet in einem JavaScript Fehler, wenn das Objekt o nicht vorhanden ist.

JavaScript:
function color(o,col)
{
 if(o)
 {
  o.style.background=col;
 }	
}

funktioniert dagegen immmer.

Diese Technik wird meistens angewendet, um zu prüfen ob der derzeit verwendete Browser ein bestimmtes JavaScript ausführen kann oder nicht.

In der grauen Vorzeit der Webentwicklung, in der es normal war, etwas erstmal falsch zu machen um es dann zu verbessern (Die Kunden, oder die .com-Firma die uns beschäftigte, haben so oder so gezahlt) haben wir versucht zu bestimmen, ob ein Browser etwas kann, indem wir den Namen des Browsers prüften.

Das war eine Sackgasse in der Entwicklung, da wir jedesmal wenn ein neuer Browser herauskam unsere Skripte ändern mussten.

Für die meisten Anwendungen heutzutage ist es nötig, zu prüfen ob der Browser das W3C[1] DOM[2] versteht, was uns zur nächsten Regel bringt:

Schreibe JavaScript, keine Browserdialekte

Wenn es keinen wirklich guten Grund dafür gibt, sollten wir niemals browerspezifische Erweiterungen verwenden, sondern uns an den Standard halten. Damit können wir sicher gehen, dass unsere Bemühungen auch in der Zukunft noch funktionieren. Die Zeiten, in denen wir auf document.layers (Netscape 4.x) oder document.all (Internet Explorer < 5) prüfen mussten sind vorbei. Moderne Browser unterstützen alle das document.getElementsById DOM des W3C.

JavaScript:
function doDOMstuff()
{
 if(document.getElementById && document.createTextNode)
 {
  [...]
 }
}

Die zweite Prüfoption ist nötig, da ältere Versionen von Opera zwar vorgaben, das DOM zu verstehen, es allerdings nicht schafften, richtige Ergebnisse zu liefern. Ähnlich wie Netscape 4.x und CSS.

Vermeide die Entführung von Variablen

Funktionen sollten nur lokal deklarierte Variablen verwenden. Das macht es einfacher, auch andere Skripte zu verwenden und beugt lästigen Folgefehlern vor.

Javascript:
var i=42; // globale variable
function dothings()
{
 for (i=0;i<200;i++) // i wird verändert
 {
  // weiterer Code
 }
}
function dothingsright()
{
 var i; // definiere i lokal
 for (i=0;i<200;i++)
 {
  // weiterer Code
 }
}
alert(i); // = 42
dothingsright()
alert(i) // = 42 (da i lokal definiert wurde)
dothings()
alert(i) // = 200, Aua!

Effekte müssen unabhängig vom Eingabegerät sein

Sich nicht auf JavaScript zu verlassen ist nur die halbe Miete. Wir müssen auch an die Besucher denken, die keine Maus verwenden können. Daher ist es nötig, alle Effekte auch per Tastatur zugänglich zu machen.

Der am meisten verbreitete Fehler ist es, Formularelemente per onchange oder onblur zu prüfen. Diese Art der Überprüfung ist zwar direkt und schnell und damit augenscheinlich hilfreich, kann aber das Ausfüllen eines Formulars per Spracherkennung zu einer Tortur machen.

Die wohl am meisten verbreitete Anwendung dieser Technik sind Dropdown Menüs:

HTML:
<form>
<p>
<label for="go2">Gehe nach:</label>
<select name="go2" id="go2" onchange="send(this)">
 <option value="index.html">Anfangsseite</option>
 <option value="chapter1.html">Frühjahrsputz</option>
 <option value="chapter2.html">Erreiche, was du 
 erreichen willst</option>
</select>
</p>
</form>
JavaScript:
function send(f)
{
 var chosen;
 chosen=f.options[f.selectedIndex].value;
 self.location=chosen;
}    
Probier dieses nicht-barrierefreie Beispiel aus.

Das Hauptproblem hier scheint zu sein, dass wenn man per Tastatur versucht mittels Tabulator und Pfeil nach unten eine Option auszuwählen, niemals weiter als die erste Möglichkeit kommt, da die Funktion send() ausgeführt wird sobald sich etwas ändert.

Erfahrene Tastaturbenutzer wissen jedoch, dass man zuerst per Alt+Pfeil nach unten die Liste anzeigen muss, um dann die Option mittels der Pfeiltasten und Eingabe auszuwählen.

Allerdings ist das nicht jedem Besucher bekannt, und es passiert nichts, wenn JavaScript abgeschaltet ist.

HTML:
<form action="send.php" method="post" onsubmit="return send(this)">
<p>
<label for="go2">Gehe zu:</label>
<select name="go2" id="go2">
 <option value="index.html">Anfangsseite</option>
 <option value="chapter1.html">Frühjahrsputz</option>
 <option value="chapter2.html">Erreiche, was 
 du erreichen willst</option>
</select>
<input type="submit" value="Abschicken" />
</p>
</form>
JavaScript:
function send(f)
{
 var chosen;
 chosen=f.go2.options[f.go2.selectedIndex].value;
 self.location=chosen;
 return false;
}    
PHP:
<?PHP if(isset($_POST['go2'])){
 header('Location:'.$_POST['go2']);
}?>
Probier dieses barrierefreie Beispiel aus.

Dieses Beispiel funktioniert immer, und erspart uns einen Serverbesuch wenn JavaScript vorhanden ist. Sollte JavaScript abgeschaltet sein, übernimmt das serverseitige send.php Skript.

Und was ist mit onkeypress?

Wenn man die Richtlinien für barrierfreies Webdesign[3] durchliest, stößt man auf den Abschnitt, Aktionen ausschließlich über Befehle aufzurufen, die unabhängig vom Eingabegerät sind:

Otherwise, if you must use device-dependent attributes, provide redundant input mechanisms (i.e., specify two handlers for the same element): Use "onmousedown" with "onkeydown". Use "onmouseup" with "onkeyup" Use "onclick" with "onkeypress"

Das klingt plausibel, wirft in der realen Welt allerdings Probleme auf. Der onkeypress Befehl ist in einigen Browsern sehr schlecht eingebunden. Mozilla zum Beispiel startet die Aktion, wenn man die Tabulator Taste betätigt, was einen Mausklick nicht ersetzen, sondern zum nächsten interaktiven Element gehen sollte.

Websurfer, die auf Tastaturen angewiesen sind, haben eine Taste als Ihre "Klicktaste" definiert, meistens die Leertaste oder Eingabe, um einen onclick Befehl auszuführen. Wenn wir zusätzlich zu diesem noch einen onkeypress Befehl verwenden, kann es sein, dass wir notwendige Tastaturkürzel blockieren oder die Funktion mehrmals aufrufen.

Beispiele fuer Tastaturfunktionen sind Mozillas Such- und Tippfunktion[4], Operas Tastaturkürzel[5] (wie zum Beispiel 'A' für den nächsten Verweis) oder die Tastaturkürzel von JAWS [6].

Es kann also passieren, dass wir, indem wir die Richtlinien bis ins letzte Detail befolgen, Besucher aussperren oder es Ihnen schwieriger machen unsere Seite zu benutzen.

Die Beispiele in diesem Kurs beinhalten einen auskommentierten onkeypress Aufruf. Sollte es nötig sein, diesen zu aktivieren, beispielsweise um einen automatisierten Accessibilitytest zu bestehen oder einer Vorgabe zu folgen, können wir den Kommentar entfernen.

Verweise

[1] Das World Wide Web Consortium: http://www.w3.org

[2] Das W3C Document Object Model: http://www.w3.org/DOM/

[3] Richtlinien für barrierfreies Webdesign: http://www.w3.org/TR/WCAG10-HTML-TECHS/#directly-accessible-scripts

[4] Mozillas Such- und Tippfunktion: http://www.mozilla.org/projects/ui/accessibility/typeaheadfind.html

[5] Operas Tastaturkürzel: http://www.opera.com/features/keyboard/complete/

[6] JAWS Tastaturkürzel: http://www.webaim.org/techniques/jaws/keyboard-shortcuts

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.