Dirk Ginader | Yahoo! Inc.


Javascript done right



                             @ginader
Kriterien für “gutes” Javascript

• Aus Benutzersicht:
  –   macht die Page-Handhabung leichter
  –   sofort/immer benutzbar (blockt nicht)
  –   ist Barrierefrei
  –   bereichert die Webseite
  –   “stört nicht”
  –   ist nicht zum Selbstzweck
  –   beschleunigt Abläufe
  –   in meiner Sprache
Kriterien für “gutes” Javascript

• Aus Entwicklersicht:
  – verständlich, wartbar,
    wiederverwendbar, erweiterbar,
    dokumentiert, optimiert, sicher,
    performant, sauber getrennt, optional,
    international, barrierefrei
verständlich

• vermeide “zu clevere” Konstrukte
verständlich

• nicht jeder versteht:
  – Ternary:
     • var d = (x < m) ? 'l' : 'r';
verständlich

• nicht jeder versteht:
  – Regex:
     • ^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-
       z0-9]+.+)|([A-Za-z0-9]+++))*[A-Za-z0-9]+@
       ((w+-+)|(w+.))*w{1,63}.[a-zA-Z]{2,6}$
verständlich

• nicht jeder versteht:
  – Shakespeare:
     • /(bb|[^b]{2})/
verständlich

• wenn doch notwendig/sinnvoll dann
  gute Variablen Namen + Doku!
mehr WTF auf

• http://wtfjs.com
Gut Wartbar

• Wie schreibst Du Javascript?
  – jQuery, YUI und Konsorten?
  – alles von Hand?
Gut Wartbar

• Du verwendest und verstehst nur ein
  Javascript Framework?
  – Du solltest Javascript lernen!
  – Verstehe was hinter den Kulissen
    passiert!
  – Lerne Fehlermeldungen zu verstehen!
  – Viele Fehler werden offensichtlich
Gut Wartbar

• Du verwendest aus Prinzip keine
  Javascript Frameworks?
  – Du solltest!
Gut Wartbar

• Javascript Frameworks/Libraries
  helfen
  –   nicht immer das Rad neu zu erfinden
  –   Code aktuell zu halten
  –   Qualität zu sichern
  –   Modulare Applikationen zu entwerfen
      anstatt Scripts zu schreiben
Gut Wartbar

• “Standing on the Shoulders of
  Giants”
• “Zwerge auf den Schultern von
  Riesen”
• “nanos gigantium humeris
  insidentes”
Wiederverwendbar

• finde patterns
• “grösste” gemeinsame Nenner
• wenn Du jeden Monat ein neues
  Dropdown Menü schreibst ist etwas
  sehr falsch
• schreibe EIN Dropdown Menü und
  entwickele es weiter
• mit einheitlichen Schnittstellen
Wiederverwendbar

• Open Source != “ich gebe meine
  kostbaren Ideen umsonst weg”
• Open Source == “ich kriege
  kostenlose Tester, Entwickler,
  Ruhm und Ehre!”
• github ist voll mit großartigem Code
• “FORK OFF” - mach es besser!
• Ein Plugin für eine Library ist ein
  super start!
Erweiterbar
•Was ist das populärste an jQuery?
     - DIE PLUGINS!

 $.fn.extend({
      accessibleTabs: function(config) {
         return this.each(function() {
             //...
         }
      }
 });


 $(".tabs").accessibleTabs();
Erweiterbar
• Jedes Modul kann plugins haben!

• Formular Validierung
 addValidator : function(name,func){
   this.validators[name] = func;
 }

 this.addValidator('isText',function(el){
       var filter   = /^[a-zA-Z ]+$/;
       return filter.test(el.get('value'));
 });

 if( !this.validators['isText'](el) ){ //error!}
Erweiterbar
•Bestehendes Erweitern anstatt alles noch
 mal neu schreiben!
•Für noch unbekannte Ansprüche
 gewappnet sein
Dokumentiert

• Dokumentation schreiben macht
  nicht Spass
• Code lesen den man vor 5 Jahren
  geschrieben und nicht dokumentiert
  hat noch weniger...
• Undokumentierten Code lesen den
  andere geschrieben haben am
  allerwenigsten...
Dokumentiert

• Klare Variablen und
  Funktionsnamen nutzen:
  – a = b(c) // Hä?
  – user = getUserOfProduct(productId) // Ah!

• Gute Kommentare
  – // IE seems to break here...
  – // dirty hack. This must never go live!
  – // this works. No idea why. Better don’t touch.
Dokumentiert

• Besonders gute Kommentare!
  – YUI Doc: http://developer.yahoo.com/
    yui/yuidoc/
  – erzeugt die YUI API Doku automatisch
  – Einfache Javadoc syntax
   /**
   * Kurzer Beschreibungstext
   * @method methodName
   * @param {bool}
   * @returm {type}
   */
Dokumentiert

• YUI Doc jetzt noch schöner
  dank Carlo & Dana:
  http://www.yuiblog.com/blog/
  2010/10/01/yuidoc-dana-theme/
Optimiert

• Guter Development Code != guter
  Production Code
• Gut für Development:
  – Code granular auf viele Dateien Verteilt
    • Modul / config / i18n / init / etc
  – Viele Kommentare
  – Beispiele
Optimiert

• Guter Development Code != guter
  Production Code
• Gut für Production:
  – Code kombiniert in wenige bis eine
    Datei
  – Kommentare & Whitespace weg
  – optionale Code-Minification
Optimiert

• YUI Compressor
  http://developer.yahoo.com/yui/
  compressor/
• Google Closure Compiler
  http://code.google.com/closure/
  compiler/
Sicher

• XSS ist das grösste
  Sicherheitsproblem
• Keine User Eingaben direkt wieder
  ausgeben
• Eingaben filtern!
  whitelisting nicht blacklisting
• Datentypen definieren
• traue nichts und niemanden
• Sei Paranoid...
Sicher

• Caja
  http://en.wikipedia.org/wiki/
  Caja_project
• “virtuelle iFrames”
• keine direkten Zugriffe auf native
  Objekte
• Übersetzer auf dem Server
• YUI3 erste Javascript Library die
  kompatibel ist
Performant

• Caching von DOM-Zugriffen
 var el = document.getElementById('bla');

• CSS ist viel schneller als Javascript
  wenn es darum geht den DOM zu
  ändern
 el.addClass('bla');
 statt
 el.css({
    width:'20px',
    height:'20px',
    ...
 });
Performant

• “reflows” vermeiden
  Bei jeder DOM-Manipulation muss
  der Browser neu rendern!
• Bei Style Änderung von grossen
  Mengen von Elementen ist CSS
  Modifikation sogar noch schneller!
 $('<style type="text/css"> a { color: red; } </
 style>').appendTo('head');
Performant

• DOM ändern mit:
  – klassischen DOM Methoden:
   el = document.getElementById('list');
   l1 = document.createElement('li');
   t1 = document.createTextNode('hallo 1');
   l2 = document.createElement('li');
   t2 = document.createTextNode('hallo 2');
   l3 = document.createElement('li');
   t3 = document.createTextNode('hallo 3');
   l1.appendChild(t1);
   l2.appendChild(t2);
   l3.appendChild(t3);
   el.appendChild(t1).appendChild(t2).appendChild(t3);
Performant

• DOM ändern mit:
  – innerHTML:
   el = document.getElementById('list');
   li = '<li>hallo 1</li>';
   li += '<li>hallo 2</li>';
   li += '<li>hallo 3</li>';
   el.innerHTML = li;

  – Schneller als DOM-Methoden (wegen IE)
Performant

• DOM ändern mit:
  – innerHTML:
   el = document.getElementById('list');
   li = [];
   li.push('<li>hallo 1</li>');
   li.push('<li>hallo 2</li>');
   li.push('<li>hallo 3</li>');
   el.appendChild(li.join());

  – noch schneller weil string
    concatenation in IE langsam ist
Performant

• DOM ändern mit:
  – innerHTML:
   el = document.getElementById('list');
   li = [];
   li[0] = '<li>hallo 1</li>';
   li[1] = '<li>hallo 2</li>';
   li[2] = '<li>hallo 3</li>';
   el.appendChild(li.join());

  – noch schneller weil auch array.push in
    IE langsam ist
Performant

• DOM ändern mit:
  – DOM Fragment:
   l = document.getElementById('list');
   f = document.createDocumentFragment();
   l1 = document.createElement('li');
   t1 = document.createTextNode('hallo 1');
   ...
   l1.appendChild(t1);
   l2.appendChild(t2);
   l3.appendChild(t3);
   f.appendChild(l1).appendChild(l2).appendChild(l3);
   el.appendChild(f);

  – Noch schneller! Nur ein DOM-Zugriff!
Sauber getrennt

• HTML
  – Markup
• CSS
  – Design
• Javascript
  – Interaktion
Sauber getrennt

• CSS für Javascript
  – <script>
       document.documentElement.className += ' js';
    </script>
  – <style>
    .module{
        /* ohne JS */
    }
    .js .module{
        /* mit JS */
    }
    </style>
Sauber getrennt

• HTML für Javascript
  – Partials mit Mustache Templating
    für Ajax content
  – /partials/login_success.html
  – Hallo {{user_name}}
    Sie haben sich erfolgreich angemeldet.
    Ihr Punkte Stand ist {{user_points}}
  – {
        user_name   : “Spundekäs”,
        user_points : 123
   }

  – http://mustache.github.com/
Optional

• Progressive Enhancement
  – Basis Funktionalität der Webseite/
    Webbapp muss gewährleistet sein auch
    wenn der Useragent kein Javascript
    spricht!
    • Mobile != iPhone (Opera Mini ist No.1!)
    • Suchmaschinen
    • Paranoide Sysadmins
    • Yahoo hat ~1% non-js User
    • ...
Optional

• Basis Seite hat Interaktion dank:
  – Links
  – Formulare
  – Alles wichtige ist sichtbar
• Mit Javascript:
  – Links die die Seite ändern werden zu
    Buttons
  – Formulare werden direkt verarbeitet
  – Info kann versteckt/gezeigt werden
International/Multilingual

• UTF-8
• RTL
• Wenn möglich Strings aus der
  HTML-Seite übernehmen
• Übersetzungsstandards nutzen
  – Text {0} mehr text {1} noch mehr text {2}
    Text {0:currency} mehr text {1:symbol} noch
    mehr text {2:amount} // {variable:comment}
International/Multilingual

• Variabler Satzbau = mehrstufige
  Übersetzung
  – T_WELCOME : {
       en_US:”We welcome {0:user}”
       de_DE:”Wir heissen {0:user} willkommen”
    }
  – getText(‘de_DE’,‘T_WELCOME’,{user:Schoppekopp})

• ISO Standards beachten
• HTML in Strings ist nicht ideal aber
  besser als pseudo code
• bold macht Asia Schriften unlesbar
International/Multilingual
     TRANSLATIONS = { // siehe http://internationalisationtips.com
!    O:    "{market} open",
!    OT:   "{market} open in {timePeriod}",
!    OE:   "{market} open early",
!    OET: "{market} open early in {timePeriod}",
!    OER: "{market} open early for {reason}",
!    OERT: "{market} open early for {reason} in {timePeriod}",
!    OL:   "{market} open late",
!    OLT: "{market} open late in {timePeriod}",
!    OLR: "{market} open late for {reason}",
!    OLRT: "{market} open late for {reason} in {timePeriod}",
!    C:    "{market} close",
!    CT:   "{market} close in {timePeriod}",
!    CE:   "{market} close early",
!    CET: "{market} close early in {timePeriod}",
!    CER: "{market} close early for {reason}",
!    CERT: "{market} close early for {reason} in {timePeriod}",
!    CL:   "{market} close late",
!    CLT: "{market} close late in {timePeriod}",
!    CLR: "{market} close late for {reason}",
!    CLRT: "{market} close late for {reason} in {timePeriod}",
!    X:    "{market} closed"
};
Barrierefrei

• Tab Reihenfolge ist entscheidend
• mit focus() kann der Nutzer geführt
  werden
• tabindex=-1 macht alles
  fokussierbar (für Javascript)
• Ajax funktioniert aber die Ladezeit
  muss erklärt werden
• Virtual Buffer aktualisieren
Barrierefrei

• manche Effekte können die
  Javascript Version verständlicher/
  Barrierefreier machen als ohne
  – highlight() // yellow fade zur
    temporären Hervorhebung eines
    geänderten Bereiches
  – auf-/zuklappen // mit guter Animation
    leichter verständlich als hart auf/zu
Barrierefrei

• WAI-ARIA
  – bringt bekannte Desktop-
    Bedienkonzepte barrierefrei in den
    Browser
  – Bringt unsemantischem Markup
    Semantik bei
Barrierefrei

• WAI-ARIA
  – echte realtime updates
    • Live Regions
  – echter Formular Validierungsstatus
    • aria-required="true"
    • aria-invalid="true"
  – echte Dialoge
    • role="alert"
Danke :-)

• http://ginader.de
• http://twitter.com/ginader
• http://github.com/ginader/
• http://www.slideshare.net/ginader
• http://speakerrate.com/speakers/
  225-ginader

Javascript done right

  • 1.
    Dirk Ginader |Yahoo! Inc. Javascript done right @ginader
  • 2.
    Kriterien für “gutes”Javascript • Aus Benutzersicht: – macht die Page-Handhabung leichter – sofort/immer benutzbar (blockt nicht) – ist Barrierefrei – bereichert die Webseite – “stört nicht” – ist nicht zum Selbstzweck – beschleunigt Abläufe – in meiner Sprache
  • 3.
    Kriterien für “gutes”Javascript • Aus Entwicklersicht: – verständlich, wartbar, wiederverwendbar, erweiterbar, dokumentiert, optimiert, sicher, performant, sauber getrennt, optional, international, barrierefrei
  • 4.
    verständlich • vermeide “zuclevere” Konstrukte
  • 5.
    verständlich • nicht jederversteht: – Ternary: • var d = (x < m) ? 'l' : 'r';
  • 6.
    verständlich • nicht jederversteht: – Regex: • ^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za- z0-9]+.+)|([A-Za-z0-9]+++))*[A-Za-z0-9]+@ ((w+-+)|(w+.))*w{1,63}.[a-zA-Z]{2,6}$
  • 7.
    verständlich • nicht jederversteht: – Shakespeare: • /(bb|[^b]{2})/
  • 8.
    verständlich • wenn dochnotwendig/sinnvoll dann gute Variablen Namen + Doku!
  • 9.
    mehr WTF auf •http://wtfjs.com
  • 10.
    Gut Wartbar • Wieschreibst Du Javascript? – jQuery, YUI und Konsorten? – alles von Hand?
  • 11.
    Gut Wartbar • Duverwendest und verstehst nur ein Javascript Framework? – Du solltest Javascript lernen! – Verstehe was hinter den Kulissen passiert! – Lerne Fehlermeldungen zu verstehen! – Viele Fehler werden offensichtlich
  • 12.
    Gut Wartbar • Duverwendest aus Prinzip keine Javascript Frameworks? – Du solltest!
  • 13.
    Gut Wartbar • JavascriptFrameworks/Libraries helfen – nicht immer das Rad neu zu erfinden – Code aktuell zu halten – Qualität zu sichern – Modulare Applikationen zu entwerfen anstatt Scripts zu schreiben
  • 14.
    Gut Wartbar • “Standingon the Shoulders of Giants” • “Zwerge auf den Schultern von Riesen” • “nanos gigantium humeris insidentes”
  • 15.
    Wiederverwendbar • finde patterns •“grösste” gemeinsame Nenner • wenn Du jeden Monat ein neues Dropdown Menü schreibst ist etwas sehr falsch • schreibe EIN Dropdown Menü und entwickele es weiter • mit einheitlichen Schnittstellen
  • 16.
    Wiederverwendbar • Open Source!= “ich gebe meine kostbaren Ideen umsonst weg” • Open Source == “ich kriege kostenlose Tester, Entwickler, Ruhm und Ehre!” • github ist voll mit großartigem Code • “FORK OFF” - mach es besser! • Ein Plugin für eine Library ist ein super start!
  • 17.
    Erweiterbar •Was ist daspopulärste an jQuery? - DIE PLUGINS! $.fn.extend({ accessibleTabs: function(config) { return this.each(function() { //... } } }); $(".tabs").accessibleTabs();
  • 18.
    Erweiterbar • Jedes Modulkann plugins haben! • Formular Validierung addValidator : function(name,func){ this.validators[name] = func; } this.addValidator('isText',function(el){ var filter = /^[a-zA-Z ]+$/; return filter.test(el.get('value')); }); if( !this.validators['isText'](el) ){ //error!}
  • 19.
    Erweiterbar •Bestehendes Erweitern anstattalles noch mal neu schreiben! •Für noch unbekannte Ansprüche gewappnet sein
  • 20.
    Dokumentiert • Dokumentation schreibenmacht nicht Spass • Code lesen den man vor 5 Jahren geschrieben und nicht dokumentiert hat noch weniger... • Undokumentierten Code lesen den andere geschrieben haben am allerwenigsten...
  • 21.
    Dokumentiert • Klare Variablenund Funktionsnamen nutzen: – a = b(c) // Hä? – user = getUserOfProduct(productId) // Ah! • Gute Kommentare – // IE seems to break here... – // dirty hack. This must never go live! – // this works. No idea why. Better don’t touch.
  • 22.
    Dokumentiert • Besonders guteKommentare! – YUI Doc: http://developer.yahoo.com/ yui/yuidoc/ – erzeugt die YUI API Doku automatisch – Einfache Javadoc syntax /** * Kurzer Beschreibungstext * @method methodName * @param {bool} * @returm {type} */
  • 23.
    Dokumentiert • YUI Docjetzt noch schöner dank Carlo & Dana: http://www.yuiblog.com/blog/ 2010/10/01/yuidoc-dana-theme/
  • 24.
    Optimiert • Guter DevelopmentCode != guter Production Code • Gut für Development: – Code granular auf viele Dateien Verteilt • Modul / config / i18n / init / etc – Viele Kommentare – Beispiele
  • 25.
    Optimiert • Guter DevelopmentCode != guter Production Code • Gut für Production: – Code kombiniert in wenige bis eine Datei – Kommentare & Whitespace weg – optionale Code-Minification
  • 26.
    Optimiert • YUI Compressor http://developer.yahoo.com/yui/ compressor/ • Google Closure Compiler http://code.google.com/closure/ compiler/
  • 27.
    Sicher • XSS istdas grösste Sicherheitsproblem • Keine User Eingaben direkt wieder ausgeben • Eingaben filtern! whitelisting nicht blacklisting • Datentypen definieren • traue nichts und niemanden • Sei Paranoid...
  • 28.
    Sicher • Caja http://en.wikipedia.org/wiki/ Caja_project • “virtuelle iFrames” • keine direkten Zugriffe auf native Objekte • Übersetzer auf dem Server • YUI3 erste Javascript Library die kompatibel ist
  • 29.
    Performant • Caching vonDOM-Zugriffen var el = document.getElementById('bla'); • CSS ist viel schneller als Javascript wenn es darum geht den DOM zu ändern el.addClass('bla'); statt el.css({ width:'20px', height:'20px', ... });
  • 30.
    Performant • “reflows” vermeiden Bei jeder DOM-Manipulation muss der Browser neu rendern! • Bei Style Änderung von grossen Mengen von Elementen ist CSS Modifikation sogar noch schneller! $('<style type="text/css"> a { color: red; } </ style>').appendTo('head');
  • 31.
    Performant • DOM ändernmit: – klassischen DOM Methoden: el = document.getElementById('list'); l1 = document.createElement('li'); t1 = document.createTextNode('hallo 1'); l2 = document.createElement('li'); t2 = document.createTextNode('hallo 2'); l3 = document.createElement('li'); t3 = document.createTextNode('hallo 3'); l1.appendChild(t1); l2.appendChild(t2); l3.appendChild(t3); el.appendChild(t1).appendChild(t2).appendChild(t3);
  • 32.
    Performant • DOM ändernmit: – innerHTML: el = document.getElementById('list'); li = '<li>hallo 1</li>'; li += '<li>hallo 2</li>'; li += '<li>hallo 3</li>'; el.innerHTML = li; – Schneller als DOM-Methoden (wegen IE)
  • 33.
    Performant • DOM ändernmit: – innerHTML: el = document.getElementById('list'); li = []; li.push('<li>hallo 1</li>'); li.push('<li>hallo 2</li>'); li.push('<li>hallo 3</li>'); el.appendChild(li.join()); – noch schneller weil string concatenation in IE langsam ist
  • 34.
    Performant • DOM ändernmit: – innerHTML: el = document.getElementById('list'); li = []; li[0] = '<li>hallo 1</li>'; li[1] = '<li>hallo 2</li>'; li[2] = '<li>hallo 3</li>'; el.appendChild(li.join()); – noch schneller weil auch array.push in IE langsam ist
  • 35.
    Performant • DOM ändernmit: – DOM Fragment: l = document.getElementById('list'); f = document.createDocumentFragment(); l1 = document.createElement('li'); t1 = document.createTextNode('hallo 1'); ... l1.appendChild(t1); l2.appendChild(t2); l3.appendChild(t3); f.appendChild(l1).appendChild(l2).appendChild(l3); el.appendChild(f); – Noch schneller! Nur ein DOM-Zugriff!
  • 36.
    Sauber getrennt • HTML – Markup • CSS – Design • Javascript – Interaktion
  • 37.
    Sauber getrennt • CSSfür Javascript – <script> document.documentElement.className += ' js'; </script> – <style> .module{ /* ohne JS */ } .js .module{ /* mit JS */ } </style>
  • 38.
    Sauber getrennt • HTMLfür Javascript – Partials mit Mustache Templating für Ajax content – /partials/login_success.html – Hallo {{user_name}} Sie haben sich erfolgreich angemeldet. Ihr Punkte Stand ist {{user_points}} – { user_name : “Spundekäs”, user_points : 123 } – http://mustache.github.com/
  • 39.
    Optional • Progressive Enhancement – Basis Funktionalität der Webseite/ Webbapp muss gewährleistet sein auch wenn der Useragent kein Javascript spricht! • Mobile != iPhone (Opera Mini ist No.1!) • Suchmaschinen • Paranoide Sysadmins • Yahoo hat ~1% non-js User • ...
  • 40.
    Optional • Basis Seitehat Interaktion dank: – Links – Formulare – Alles wichtige ist sichtbar • Mit Javascript: – Links die die Seite ändern werden zu Buttons – Formulare werden direkt verarbeitet – Info kann versteckt/gezeigt werden
  • 41.
    International/Multilingual • UTF-8 • RTL •Wenn möglich Strings aus der HTML-Seite übernehmen • Übersetzungsstandards nutzen – Text {0} mehr text {1} noch mehr text {2} Text {0:currency} mehr text {1:symbol} noch mehr text {2:amount} // {variable:comment}
  • 42.
    International/Multilingual • Variabler Satzbau= mehrstufige Übersetzung – T_WELCOME : { en_US:”We welcome {0:user}” de_DE:”Wir heissen {0:user} willkommen” } – getText(‘de_DE’,‘T_WELCOME’,{user:Schoppekopp}) • ISO Standards beachten • HTML in Strings ist nicht ideal aber besser als pseudo code • bold macht Asia Schriften unlesbar
  • 43.
    International/Multilingual TRANSLATIONS = { // siehe http://internationalisationtips.com ! O: "{market} open", ! OT: "{market} open in {timePeriod}", ! OE: "{market} open early", ! OET: "{market} open early in {timePeriod}", ! OER: "{market} open early for {reason}", ! OERT: "{market} open early for {reason} in {timePeriod}", ! OL: "{market} open late", ! OLT: "{market} open late in {timePeriod}", ! OLR: "{market} open late for {reason}", ! OLRT: "{market} open late for {reason} in {timePeriod}", ! C: "{market} close", ! CT: "{market} close in {timePeriod}", ! CE: "{market} close early", ! CET: "{market} close early in {timePeriod}", ! CER: "{market} close early for {reason}", ! CERT: "{market} close early for {reason} in {timePeriod}", ! CL: "{market} close late", ! CLT: "{market} close late in {timePeriod}", ! CLR: "{market} close late for {reason}", ! CLRT: "{market} close late for {reason} in {timePeriod}", ! X: "{market} closed" };
  • 44.
    Barrierefrei • Tab Reihenfolgeist entscheidend • mit focus() kann der Nutzer geführt werden • tabindex=-1 macht alles fokussierbar (für Javascript) • Ajax funktioniert aber die Ladezeit muss erklärt werden • Virtual Buffer aktualisieren
  • 45.
    Barrierefrei • manche Effektekönnen die Javascript Version verständlicher/ Barrierefreier machen als ohne – highlight() // yellow fade zur temporären Hervorhebung eines geänderten Bereiches – auf-/zuklappen // mit guter Animation leichter verständlich als hart auf/zu
  • 46.
    Barrierefrei • WAI-ARIA – bringt bekannte Desktop- Bedienkonzepte barrierefrei in den Browser – Bringt unsemantischem Markup Semantik bei
  • 47.
    Barrierefrei • WAI-ARIA – echte realtime updates • Live Regions – echter Formular Validierungsstatus • aria-required="true" • aria-invalid="true" – echte Dialoge • role="alert"
  • 49.
    Danke :-) • http://ginader.de •http://twitter.com/ginader • http://github.com/ginader/ • http://www.slideshare.net/ginader • http://speakerrate.com/speakers/ 225-ginader