Als Erklärbär für HTML5 und andere Webtechnologien bekomme ich jede Woche neue Fragen rund um Webentwicklung gestellt. Da diese Fragen (und Antworten) viel zu schade sind, um sie in meinem E-Mail-Archiv verrotten zu lassen, hole ich sie im Rahmen der Artikelserie „Fragen zu HTML5 und Co“ regelmäßig ans Tageslicht – denn dumme Fragen gibt es schließlich nicht!

Slashes in selbstschließenden Elementen?

Mir ist noch nicht zu 100% klar, wie es sich mit HTML5 und selbstschließenden Elementen verhält. Sollte man diese gar nicht mehr verwenden? Also z.B. statt <input /> nur noch <input> und statt <br /> nur noch <br> verwenden? Ist es, wenn man ein sauberes HTML5-Dokument schreiben möchte, sinnvoll, weg von der XHTML-Syntax zu gehen? Oder ist es völlig egal?

HTML5 ist völlig egal, ob selbstschließende Tags mit einem Slash zugemacht werden oder nicht. Der HTML-Parser des Browser ignoriert den Slash komplett, denn dass es so etwas wie „Inhalt zwischen öffnendem und schließendem Input-Tag“ nicht gibt, ist fest in ihn einprogrammiert. Wenn der Slash aber vorhanden ist, ist er für den Browser reines Hintergrundrauschen und stört nicht groß.

Kurz gesagt ist ist <input /> aus Browser-Sicht genau so richtig wie <input>. Die einzig maßgebliche Entscheidungshilfe in dieser Frage sollte der Code-Standard des eigenen Teams oder Projekts sein.

Warum funktioniert Web Storage nicht?

Ich habe mir zur Einführung in HTML5 (speziell das Thema Local Storage) eine Notizbuch-Applikation aus dem Internet rausgesucht. Diese hat im Firefox, Opera und Chrome auch funktioniert, nur im Safari 5.1 und Internet Explorer 9 wurden die eingegebenen Werte nicht übernommen. Laut meiner Recherche sollte Local Storage aber in der jeweiligen Version vom Safari und Internet Explorer funktionieren. Javascript ist auch aktiviert. Wie kann das sein?

So etwas kann passieren, wenn eine Webseite nicht über einen Webserver, sondern über das lokale Dateisystem (file://) aufgerufen wird. Web Storage arbeitet, wie viele andere HTML5-Technologien auch, auf einer Pro-Origin-Basis. Die Daten werden getrennt nach Host, Protokoll und Port einer Webseite gespeichert, damit http://foo.de nicht die Daten von https://www.bar.com auslesen kann. Bei einem Aufruf über das lokale Dateisystem gibt es aber weder Host noch Protokoll noch Port –also keinen Origin – und einige Browser verweigern dann eben den Dienst. Das ist bei vielen HTML5-Technologien so, nicht nur bei Web Storage.

Mehrere Formular-Ziele mit HTML5

Gibt es in HTML5 die Möglichkeit, mehrere Submit-Buttons in einem Formular zu haben und hinterher zu unterscheiden, welcher gedrückt wurde?

Diese Möglichkeit gibt es, allein die Browserunterstützung ist etwas problematisch. Mit Hilfe eines formaction-Attributs auf einem Submit-Button kann ein Formular dazu gebracht werden, seine Daten an eine andere URL als die im action-Attribut des <form> notierte zu schicken:

<form action="http://foo.com">
  <input type="submit">                            <!-- sendet an foo.com -->
  <input type="submit" formaction="http://bar.de"> <!-- sendet an bar.de -->
</form>

Schade nur, dass es mit der Browserunterstützung vergleichsweise finster aussieht – IE < 10 und der Android-Browser wissen mit dem Attribut nichts anzufangen. Da hilft wohl höchstens ein JavaScript-Hack …

forEach für getElementsByTagName

Funktioniert forEach() eigentlich auch mit Sachen wie document.querySelectorAll() und document.getElementsByTagName()? Ich habe es mit Opera, Firefox und IE9 probiert und es wird der Fehler „forEach ist keine Funktion“ ausgeworfen. Mit „normalen“ Arrays klappt es …

Dieses Verhalten hat so seine Richtigkeit, wenn es auch nicht besonders hilfreich ist. Es ist tatsächlich so, dass forEach() eine Methode von Arrays ist, aber das, was man von getElementsByTagName() und Konsorten zurückbekommt, sind gar keine Arrays! Stattdessen handelt es sich um NodeLists, die außer der length-Eigenschaft und der Möglichkeit, auf enthaltene Elemente über ihren Index zuzugreifen nichts mit Arrays gemein haben. Sie stammen nicht von Array.prototype ab und daher gibt es für sie auch kein forEach().

„Reparieren“ lässt sich dies (in modernen Browsern), indem man die NodeList in ein Array verwandelt. Einfach die slice()-Methode von Array.prototype ausleihen und sie mittels call() auf die NodeList anwenden:

var nodes = document.getElementsByTagName('div');
var arr = Array.prototype.slice.call(nodes);
typeof arr.forEach; // "function"

In nicht ganz so neuen Browsern (IE8 und älter) hilft eine Schleife:

var nodes = document.getElementsByTagName('div');
var arr = [];
for(var i = 0, l = nodes.length; i < l; i++){
    arr.push(nodes[i]);
}

Dieses Prinzip funktioniert mit ziemlich allen Array-ähnlichen Objekten, denen man im so Browser über den Weg läuft (wie z.B. FileList und arguments).

Weitere Fragen?

Eure Fragen zu HTML5, JavaScript und anderen Webtechnologien beantworte ich gerne! Einfach eine E-Mail schreiben oder Formspring bemühen und ein bisschen Geduld haben – falls ich gerade unterwegs bin, kann es mit Antwort manchmal etwas dauern, doch früher oder später schreibe ich garantiert zurück.