Termine für April und Mai 2012

Veröffentlicht am 4. April 2012

Im April und Mai 2012 gibt es für interessierte Webtechnologie-Padawane nur zwei (öffentliche) Möglichkeiten, sich vom Webtechnologie-Erklärbären mit frischem Wissen rund um die neueste Neuheiten in den Browsern dieser Welt ausrüsten zu lassen. Allerdings sind die beiden Termine ganz gut kombinierbar, da sie direkt nacheinander am gleichen Ort stattfinden:

  • 7. - 9. Mai 2012 in München: HTML5-Schulung bei der Open Source School. Mein drei­tä­gi­ges HTML5-Standardprogramm stattet die Teilnehmer im Druckbetankungsverfahren mit (so gut wie) allem aus, was man zu HTML5 wissen muss, von semantischem Markup bis hin zu Canvas-Frameworks. Die Themen sind im Einzelnen:
    • Hintergründe und Entstehungsgeschichte
    • Geolocation und Gerätesensorik
    • HTML5-Schnelleinstieg
    • Semantisches HTML5
    • HTML5-Formulare
    • Offline-Webanwendungen
    • Multimedia im Browser
    • Web Workers
    • Die File-API
    • Polyfills
    • Das Canvas-Element
    Geboten wird ein großer Praxisanteil, kleine Arbeitsgruppen und ein Buch gibt es obendrein.
  • 10. -11. Mai 2012 in München: CSS3-Schulung bei der Open Source School. Mein zweitä­gi­ges CSS3-Standardprogramm katapultiert die Teilnehmer in das CSS3-Zeitalter, in dem Webfonts und Farbverläufe fließen. Das gesamte Programm:
    • Hintergründe und Entstehungsgeschichte
    • CSS3-Selektoren
    • Farben und Farbverläufe
    • Boxen und Rahmen
    • CSS3-Layout
    • Transformationen
    • Transitionen und Animationen
    • Schrifteinbettung und -gestaltung
    • Media-Queries
    Ein großer Praxisanteil, kleine Arbeitsgruppen und ein Buch als Bonus gibt es auch hier.

ECMAScript 6: Block Scope und Konstanten

Veröffentlicht am 2. April 2012

Anders als im ECMAScript 5 rüstet ES6 nicht nur hier und da ein paar Funktionen nach, sondern bietet für viele Neuerungen neue Syntax und Konzepte, wobei einschränkend gesagt werden muss, dass viele der „Neuheiten“ so neu gar nicht sind. Das Meiste ist irgendwo geklaut: aus proprietären Browser-Erweiterungen, aus CoffeeScript, anderen Programmiersprachen oder gar aus dem gescheiterten ES4-Standard. In diese Kategorie der nicht ganz so neuen Neuheiten fallen auch die neuen blockgebundenen Variablen (let) und Konstanten (const), um die es in diesem Artikel geht. Die neuen Features funktionieren zur Zeit in allem, was auf neuere V8-Engines aufsetzt, also Chrome und Node, wobei es nicht mehr lange dauern dürfte, bis auch andere JS-Implementierungen nachrüsten. Wenn es endlich so weit ist, haben die JavaScript-Programmierer dieser Welt zwei Probleme mit Variablen weniger.

Zwei Probleme mit Variablen

Problem Nummer 1 ist, dass in ECMAScript 5 und älter der Geltungsbereich von Variablen die Funktion ist, in der sie deklariert wurden. Wenn man den folgenden Schnipsel ausführt …

function foobar(foo){
    if(foo){
        var bar = 42;
    }
};

… wird der Code interprtiert, als hätte man das folgende geschrieben:

function foobar(foo){
    var bar;
    if(foo){
        bar = 42;
    }
};

Dieses Verhalten bringt es mit sich, dass man, wenn man Variablen innerhalb von Blöcken deklariert, damit auch die Umwelt außerhalb der Blöcke verunreinigt:

function foobar(foo){
    if(foo){
        var bar = 42;
    }
    // "bar" ist hier auch noch 42
};

Das mag zwar in vielen Fällen wie dem obrigen nicht groß stören, in anderen hingegen schon:

var bar = { 'hallo': 1337 };

function foobar(foo){
    if(bar[foo]){
        return bar[foo];
    }
    else {
        var bar = 42 * 666;
        return bar;
    }
};

var x = foobar('hallo'); // Na, wer weiß was hier passiert?

Selbst wenn dieses Verhalten nicht oft zu Problemen führt, so ist es doch weder ist es sonderlich intuitiv, noch wird es wirklich gebraucht. Im Gegenzug ist es recht mühsam, in ECMAScript 5 und älter Variablen auf Blöcke zu beschränken, denn außer sofort ausgeführten Funktionen hilft hier nichts:

function foobar(foo){
    whatever();
    if(foo){
        (function(){
            var bar = 42;
        })();
    }
    // "bar" ist hier undefined
};

Das funktioniert zwar, ist aber der Code-Eleganz nicht besonders zuträglich und für alle mit eher mittlguten JavaScript-Kenntnissen unnötig verwirrend.

Das zweite Problem ist, dass es in ECMAScript 5 und älter eben nur Variablen und keine Konstanten gibt. Es existieren zwar Konventionen, gemäß derer man Variablen durch Allcaps-Namen als „Konstanten“ kennzeichnet, doch das allein hält im Zweifelsfall niemanden davon ab, die „Konstante“ zu überschreiben:

var KONSTANTE = 42;

KONSTANTE = 1337; // Funktioniert!

Die einzige in ES5 denkbare Lösung besteht darin, mittels Property Descriptor die gewünschte Konstante als nicht-überschreibbare Eigenschaft auf einem Objekt anzulegen:

Object.defineProperty(window, 'KONSTANTE', {
    writable: false,
    enumerable: true,
    configurable: false,
    value: 42
});

KONSTANTE = 1337; // TypeError: Cannot assign to read only property 'KONSTANTE'

Auch hier gilt: das funktioniert zwar, aber als ersthafte Lösung kann man dieses Konvolut wohl niemandem verkaufen. ECMAScript 6 schafft nun die Probleme rund um Konstranten und var aus der Welt, indem mit let und const zwei Alternativ-Formen von Variablen eingeführt werden.

Lösung 1: let statt var

Verwendet man zur Deklaration einer neuen Variable das Schlüsselwort let statt var, so erhält man eine an den Block gebundene Variable, die jenseits ihrer Schleife oder Kontrollstruktur nicht sichtbar ist. Damit bleiben zum Beispiel die Zähler einer For-Schleife ausschließlich innerhalb der Schleife gültig:

for(let i = 0; i < 4; i++){
}
console.log(i); // ReferenceError: i is not defined

Hierfür braucht es nicht zwingend echte Kontrollstrukturen oder Schleifen, auch bei leeren Blöcken funktioniert let:

{
    let i = 42;
}
console.log(i); // ReferenceError: i is not defined

Aus der Blockbindung folgt, dass let-Deklarationen nur in einem Block, in Funktionscode oder auf Programmebene vorkommen dürfen:

if(true) var i = 42;    // Klappt
if(true) let i = 42;    // SyntaxError: Illegal let declaration in unprotected statement context
if(true){ let i = 42; } // Klappt

Ansonsten verhält sich let ziemlich genau wie var und unterliegt auch den gleichen Einschränkungen – auch let window = 42 kann in einem Browser das Window-Objekt nicht überschreiben. Insgesamt ist let also nichts weiter als ein repariertes var, dass im JavaScript-Code der Zukunft ersteres in den meisten Fällen anstelle von var ersetzt werden dürfte.

Lösung 2: const statt var

Mit const lassen sich echte Konstanten anlegen, die auch wirklich nicht überschrieben werden können:

const KONSTANTE = 42;
KONSTANTE = 1337; // TypeError: Cannot assign to read only property 'KONSTANTE'

Genau wie let-Variablen sind auch const-Konstanten an ihren Block gebunden:

if(true){
    const KONSTANTE = 42;
}
console.log(KONSTANTE); // ReferenceError: KONSTANTE is not defined

Anders als Variablen (egal ob let oder var) müssen Konstanzen logischerweise auch immer mit einem Wert initialisiert werden:

var foo;   // Kein Problem
let bar;   // Kein Problem
const BAZ; // SyntaxError: Unexpected token ;

Auch wenn JavaScript nun echte Konstanten kennt, ist es sinnvoll, auch bei deren Verwendung weiterhin den Bezeichner komplett groß zu schreiben – so ist immer klar, wann man es mit einer Variablen oder einer Konstanten zu tun hat.

Der Status

Über let und const besteht in der ES6-Arbeitsgruppe weitgehend Konsens und die noch offenen Fragen (nachzulesen auf den entsprechenden Wiki-Seiten) betreffen allesamt Sonderfälle. Aufhalten lassen werden sich diese Features nicht mehr. Und so zeigt die allmächtige Kompatibilitätstabelle schon recht viel grün, doch echte Unterstützung für let und const findet sich zur Zeit nur in den V8-Engines von Chrome ab Version 18 und Node.js. Ab Firefox Version 2.0 sowie einigen anderen Browsern existieren auch Implementierungen von let und const, die jedoch nicht mit dem ES6-Standard kompatibel sind und die man daher weiträumig umfahren sollte.

Und noch mehr Fragen zu HTML5 beantwortet

Veröffentlicht am 19. März 2012

Auch wenn das Weblog den Großteil der letzen Monate stillgelegt war, habe ich natürlich wieder per E-Mail, Twitter, Formspring und andere Kanäle so manche Frage zu HTML5 beantwortet. Diesmal war sogar eine Frage zu JavaScript dabei, um die ich mich natürlich auch gerne kümmere – auch in Sachen CSS, DOM und amderem Webkrempel kann man mich jederzeit löchern! Und weil einige der zuletzt eingegangenen Fragen wieder erheblich zu schade für fortwährende Geheimhaltung waren, werden sie hiermit als ein weiterer Teil der beliebten Serie „Fragen zu HTML5“ befreit.

HTML-Validierung

Nach der Umstellung des doctypes schlägt die Validierung unserer Seiten mit dem W3C-Validator an vielen Stellen fehl - einige davon konnte ich fixen, aber bei den Meta-Tags bin ich nicht ganz sicher, was ich tun soll. Beispiele:

Bad value DC.Subject for attribute name on XHTML element meta: Keyword dc.subject is not registered.
<meta name="DC.Subject" content="" />

Bad value DC.Date for attribute name on XHTML element meta: Keyword dc.date is not registered.
<meta name="DC.Date" content="2011-12-19T14:15:48" />

Die entsprechenden Meta-tags rauszuwerfen ist keine Option, da die SEO-Abteilung sie behalten möchte. Was tun? Sie bei der WHATWG selber definieren bzw. ändern wie in wiki.whatwg.org/wiki/MetaExtensions beschrieben?

Ich würde zu aller erst mal die Option „einfach ignorieren“ in den Raum stellen. Das, was der Validator hier bemängelt, sind allein ungültige bzw. unbekannte Attribut-Angaben, aber so lange nicht die Struktur des HTML kaputt ist, wird das keinerlei negative Folgen für Browser und 99,99% der anderen Endgeräte haben. Was der Browser nicht kennt, ignoriert er einfach. Und wenn die SEO-Abteilung der Meinung ist, diese Meta-Tags wären wichtig, spricht nichts dagegen, sie einfach drin zu lassen. Das macht am wenigsten Arbeit und hat trotzdem keine großen Nachteile.

Unabhängig davon ist der Validator in Sachen HTML5-Syntax auch nicht die letzte Instanz und er hinkt oft etwas hinter dem Standard her. Gerade was kleinere Features angeht (wie z.B. welche Attribute erlaubt sind oder wann man &-Zeichen escapen muss und wann nicht), gibt er oft falsche Auskunft. Das einzige was also wirklich zählt, ist was im Browser funktioniert und was im Standard steht.

Infos zu Browserunterstützung

Auf den WHATWG-Seiten kann ich herausfinden, welcher Tag in den aktuellen Versionen von Safari, Chrome, Firefox und IE unterstützt wird. In Ihrem Buch, z.B. auf Seite 92, 182-13, geben Sie aber die Browser-Versionen exakt an, z.B. Firefox 3.6. Wie kommen Sie zu diesen detaillierten Angaben im Vergleich zur Spezifikation? Haben Sie dies selbst ausprobiert oder steht dies auf einer Website?

Ich habe das seinerzeit selbst durchgetestet und aus diversen Quellen zusammengetragen. Mittlerweile gibt es mit caniuse.com aber eine hervorragende Webseite, die detaillierte Kompatibilitätstabellen zu allem Möglichen sammelt – HTML5, CSS3 und vielem mehr.

Zahlen parsen mit JavaScript

Kannst du mit sagen wieso parseInt('08') 0 ist und parseInt('02') 2?

Das ist einer der vielen „Bad Parts“ in JavaScript. Die Funktion parseInt() macht zwar die Strings zu Zahlen, aber Zahlen mit führender Null werden von Browsern als Oktalzahl behandelt. Das ist im Standard so gar nicht vorgesehen und damit ein Browserbug, der zum Glück vom Strict Mode in ES5 abgestellt wird.

Update-Aufforderungen

Was hältst du von Browser-Update-Aufforderungen in IE auf Seiten, die IE < 8 nicht unterstützen?

Eine Webseite (nicht Webapp) kann man immer in eine für alte Browser komumierbare Form bringen, zur Not, indem man alten IEs einfach alle Styles entzieht. Eine Update-Aufforderung bei gleichzeitig nicht mehr funktionierender Seite fände ich an dieser Stelle einfach nur faul. Wer sich die Mühe macht, eine Update-Aufforderung zu bauen, der kann auch schnell einen auf die Basics reduzierten IE6-Stylesheet anlegen.

Bei Webapplikationen ist das etwas anderes. Wenn bestimmte HTML5-Features zwingend gebraucht werden, ist es OK, entsprechende Systemanforderungen zu formulieren. Wenn das alle anderen Programme auf dieser Welt dürfen, warum nicht auch die Webapps?

Formularvalidierung steuern

Gibt es bei der HTML5 Formularvalidierung eigentlich auch die Möglichkeit, dass man bei dem Kick auf einen bestimmten Submit-Button nicht validiert? Also quasi ein novalidate-Attribute für einen Button bzw. Input-Submit.

Bei Formularen mit mehreren Seiten (z.B. Bestellvorgang) möchte ich einen Zurück-Button verwenden, bei welchem allerdings nicht zwangsläufig das ganze Formular ausgefüllt sein muss. Dennoch sollen bereits ausgefüllte Felder übermittelt werden, was einen normalen Link bzw. die history ausschließt. Hast du eine Idee?

Eine solche Möglichkeit existiert, funktioniert aber nur in wenigen Browsern. Es gibt das novalidate-Attribut für Formulare, mit dem man die Validierung für das gesamte Formular deaktivieren kann und es gibt das formnovalidate-Attribut für Submitbuttons. Wenn man dieses für die speziellen Submits verwendet (also für die, die keine Validierung auslösen sollen) findet die Prüfung nur beim normalen, finalen Submit sattt und nicht mehr bei den Zwischenschritten. Alle weiteren Details verraten die Spezifikationen.

Webfonts und Canvas

Gibt es eine Einschränkung für das Verwenden von Schriftarten in Canvas-Elementen? Ich würde gerne Googles Webfonts verwenden …

Eine Einschränkung gibt es an sich nicht. Das Problem mit Webfonts und Canvas ist nur, dass die Webfonts vollständig geladen sein müssen, bevor man sie auf der Canvas verwenden kann. Und soweit ich weiß, gibt es keine native Möglichkeit in allen Browsern zuverlässig den Zeitpunkt abzupassen, ab dem die (normal via @font-face in CSS eingebetteten) Webfonts da sind. Die Verwendung von Font.js oder Googles WebFont Loader könnte Abhilfe schaffen.

Weitere Fragen?

Eure Fragen zu HTML5, CSS und anderen Webthemen 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.

ECMAScript 6: Die nächste Ausbaustufe von JavaScript

Veröffentlicht am 6. März 2012

ECMAScript 5 darf man spätestens seit dem Erscheinen des Internet Explorer 9 getrost als die aktuelle, tatsächlich benutzbare Version von JavaScript bezeichnen. Alle neueren Versionen der verbreiteten Browser sowie auch Node.js unterstützen den neuen Standard so weit, dass sich Entwickler nur noch von ganz alten Browser-Fossilien aufgehalten fühlen dürfen. Damit wird es also höchste Eisenbahn, sich mit der nächsten Java-Script-Version, ECMAScript 6 (auch Harmony genannt) zu befassen. Dieser Artikel ist der Auftakt zu einer Serie, die der Reihe nach der einzelnen ES6-Features unter die Lupe nimmt, sobald sie in mindestens einem Browser vernünftig implementiert sind. Dieser Beitrag betrachtet zunächst nur das Drumherum; richtig technisch wird es erst im nächsten Teil.

Geschichtlicher Überblick

Wie in der Artikelserie zu ECMAScript 5 beschrieben, handelt es sich bei ES5 um ein ein eher vorsichtiges Update, bei dem die Wahrung der Abwärtskompatibilität über allem steht. Dies ging naturgemäß so manchen Entwickler nicht weit genug und so wurde gefordert, man möge doch bitte die große Axt herausholen und JavaScript von Grund auf reformieren. Das ist allerdings nicht ganz so einfach wie es sich anhört. Schon Version 4 von ECMAScript sollte mit allerlei neuen Features aufwarten, doch zwischen den verschiedenen Interessengruppen kam es nicht zur Einigung. Nach Meinung Einiger uferte das Updatepaket aus und man konnte sich nicht darüber verständigen, wie weit und wie schnell man die Entwicklung vorantreiben sollte.

Als klar wurde, dass es sehr Unterschiedliche Auffassungen über die Zukunft von ECMAScript gab, schwiegen sich die an der Arbeitsgruppe beteiligten Partien zunächst ein Jahr lang gegenseitig an. Da sich aber auch dieser Zustand nicht als besonders vielversprechend heraussetellte, einigte man sich schließlich darauf, die Entwicklung der Sprache in kleineren Schritten voranzutreiben. Zunächst wurde mit ECMAScript 5 die Sprache vor allem ausgemistet. Die wenigen neuen Features waren entweder schon praxiserprobt (z.B. Function.prototype.bind) oder wurden mit viel Mühe so konzipiert, dass sie unter keinen Umständen mit bestehenden Scripts im Web kollidieren konnten (z.B. Strict Mode, Objekterweiterungen).

Mit ES5 wurde ein Fundament gelegt, aus das zukünftige Versionen der Sprache aufsetzen konnten, was mit ES6 nun langsam Realität wird. Zwar kommt die Anzahl der Neuerungen für die sechste Version der Sprache nicht an das heran, was mit ES4 geplant war, aber für Web-Verhältnisse kann sich der Umfang des Gebotenen durchaus sehen lassen.

Ein Rüstprogramm für JavaScript

ES6 ist ein vergleichsweise großes Rüstprogramm für JavaScript. Das Standardisierungskomitee um Brendan Eich war teilweise durchaus willens, auch radikalere Umbauten vorzunehmen und so zum Beispiel Köpfe von Kontrollstrukturen ohne Klammern zuzulassen:

if foo > 42 {
    bar++;
}

Obwohl diese eine Änderung aller Voraussicht nach nun nicht den Weg in den Standard finden wird, demonstriert sie doch sehr schön die Geisteshaltung, mit der an das Projekt ES6 herangegangen wurde: JavaScript sollte gründlich um- und aufgebaut werden! Letztlich sind es wesentlich mehr Aus- als Umbauten geworden; bestehende Scripts samt und sonders nicht mehr lauffähig zu halten, war dann doch etwas viel verlangt. Die komplette Liste der Features, die sich (ziemlich sehr) sicher im neuen Standard wiederfinden werden gibt es im ECMAScript-Wiki. Einige Highlights:

Wie immer bei Webstandards müssen wir natürlich auch das, was auf dem Papier steht, mit dem vergleichen, was in der Realität existiert. Dort ist zwar noch nicht viel von dem neuen Standard angekommen, doch das was schon da ist, kann sich in aller Regel sehen lassen.

Status und Unterstützung

ECMAScript 6 selbst ist Stand Anfang 2012 noch kein fertiger Standard, aber die meisten Teile der Spezifikationen sind schon recht stabil. Anders als bei anderen Webstandards funktioniert JavaScript wirklich fast genau so, wie man es von einem Standard erwartet: erst kommt das Papier, dann folgen die Implementierungen. So gibt es verglichen mit den ebenfalls unfertigen Standards HTML5 und CSS3 bisher nur punktuelle Browserunterstützung.

In Chrome Canary, einem experimentelle Chrome-Build, findet man (Stand Anfang 2012) von allen Browsern die meisten ES6-Features. Um in den Genuss von ES6 zu kommen, muss man unter about:flags den Punkt „Enable Experimental JavaScript“ aktivieren:

Der ES6-Aktivierungs-Dialog in Chrome

Danach stehen in allen Scripts, die im Strict Mode ausgeführt werden, die in Chrome Canary vorhandenen ES6-Features zur Verfügung. Auch in anderen V8-basierten Umgebungen kommt man in den Genuss der Features von Chrome – in Node.js lassen sich verschiedene ES6-Aspekte per Startparameter aktivieren (z.B. --harmony_weakmaps für Weak Maps).

Manche JS-Engines stellen die Neuheiten auch ohne zusätzliche Arbeit bereit, so zum Beispiel der Firefox. Es ist realistischerweise davon auszugehen, dass ich all diese Details zur Aktivierung von ES6 im Wochentakt ändern werden, doch vom Experimentieren mit den neuen Features muss das nicht abhalten – denn diese selbst sind schließlich weitgehend stabil.

Problematisch ist allein die fehlende Dokumentation. Neben dem Standard selbst gibt zur Zeit so gute wie gar keine Quellen, aus denen man Infos über ES6 beziehen könnte (z.B. Browser-Sourcecode und dazugehörige Unit Tests), aber genau dafür ist schließlich diese Artikelserie da.

Wie geht es weiter?

Dieser Artikel ist der Auftakt zu einer Serie, die die neuen Features von ES6 genauer beleuchtet. Zur Vorbereitung empfehle ich, die Artikelserie zu ES5 zu lesen – es ist schließlich immer sinnvoll, den ersten Schritt vor dem Zweiten zu tun. Die Serie wird nach und nach neue Teile erhalten wenn immer mehr ES6-Features in den Browsern verfügbar werden, wobei als erstes Thema voraussichtlich Block Scope und Konstanten auf der Agenda stehen – irgendwann in den nächsten Tagen.