Cargando...

LimaCON'13: Introducción a HTML5

pinguino linux-malaga

Ésta presentación es una web HTML5 :)
Presiona para avanzar.

Controles
  • y para moverse.
  • Ctrl y tecla + o - para acercar/alejar.
  • s para ver el código fuente.
  • t para cambiar de tema.
  • h para resaltar la sintaxis.
  • n para mostrar u ocultar notas al pie.
  • 3 para des/activar el efecto 3D.
  • 0 para mostrar/ocultar la ayuda.
$ python -m SimpleHTTPServer

Introducción a HTML5*

Desarrollo Web al siguiente nivel

(* y algunas otras nuevas tecnologías web)

http://www.linuxonrails.com/html5/html5.html
https://github.com/linuxonrails/slides.html5rocks.com fork me!

Cronología aproximada de la web
  • 1991 HTML Tim Berners-Lee
  • 1994 HTML 2
  • 1996 CSS 1 + JavaScript
  • 1997 HTML 4
  • 1998 CSS 2
  • 2000 XHTML 1
  • 2002 ¡Diseño web sin tablas!
  • 2005 AJAX
  • 2009 HTML 5
HTML5 ~= HTML + CSS + JS

HTML: HyperText Markup Language, el lenguaje básico de la web.
CSS: Cascading Style Sheets, hojas de estilo para definir el aspecto del HTML
JS: JavaScript, el lenguaje de programación de la web

HTML4 fue un éxito rotundo

HTML5 se basa en HTML4: lo extiende y apenas introduce cambios*.

html4 transicional a html5

*Los cambios introducidos no rompen la web para los viejos navegadores.
¡no tienes excusa para no utilizar HTML5!.

De HTML4 a HTML5: el primer paso

Cambiar la declaración de tipo de documento a:

<!DOCTYPE html>

Es la primera linea y determina el tipo de documento (HTML4, XHTML1, etc)

El objetivo de HTML5 es...

...una web universal

  • accesible desde cualquier dispositivo
  • accesible para aquellos con discapacidades
  • con o sin acceso a internet

Hoy hablaremos de...

Almacenamiento / Offline

Espera lo inesperable

HTML5 Offline & Storage

Cuando se pierde la conexión o queremos desarrollar una aplicación offline...

JS

Web Storage

// se utiliza localStorage para almacenamiento persistente
// se utiliza sessionStorage para almacenamiento en la sesión
saveButton.addEventListener('click', function () {
  window.localStorage.setItem('value', area.value);
  window.localStorage.setItem('timestamp', (new Date()).getTime());
}, false);
textarea.value = window.localStorage.getItem('value');

Ejemplo: guardar el siguiente texto en el lado del cliente

JS

Web SQL Database

var db = window.openDatabase("DBName", "1.0", "description", 5*1024*1024); //5MB
db.transaction(function(tx) {
  tx.executeSql("SELECT * FROM test", [], successCallback, errorCallback);
});

Ver la base de datos generada: Developer > Developer Tools > Storage

    JS

    IndexedDB (en desuso)

    var idbRequest = window.indexedDB.open('Database Name');
    idbRequest.onsuccess = function(event) {
      var db = event.srcElement.result;
      var transaction = db.transaction([], IDBTransaction.READ_ONLY);
      var curRequest = transaction.objectStore('ObjectStore Name').openCursor();
      curRequest.onsuccess = ...;
    };
    
    JS

    Application Cache (Manifest)

    gestión en Chrome: chrome://appcache-internals
    <html manifest="cache.appcache">
    window.applicationCache.addEventListener('updateready', function(e) {
      if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
        window.applicationCache.swapCache();
        if (confirm('A new version of this site is available. Load it?')) {
          window.location.reload();
        }
      }
    }, false);
    
    cache.appcache:
    CACHE MANIFEST
    # version 1.0.0
    
    CACHE:
    /html5/src/logic.js
    /html5/src/style.css
    /html5/src/background.png
    
    NETWORK:
    *
    

    Desactiva la conexión a internet y refresla la página!

    JS

    Quota API

    // Request Status
    webkitStorageInfo.queryUsageAndQuota(webkitStorageInfo.TEMPORARY, function(used, remaining) {
        console.log("Cuota utilizada: " + used + ", cuota restante: " + remaining);
      }
    );
    
    // Request Quota (only for File System API)
    webkitStorageInfo.requestQuota(webkitStorageInfo.PERSISTENT, 10 * 1024 * 1024, function(used) {
        console.log("Cuota utilizada: " + used + ", cuota restante: " + remaining);
      }
    );
    Por defecto (temporal)Cuota requerida (Persistente)
    Web Storage~5Mb (varía según navegador)N/A
    App Cache10% del espacio en disco total
    Usada: -- BytesDisponible: -- Bytes
    IndexedDB
    WebSQL
    File System APIArbitraria
    en Bytes Usada: -- Bytes

    Tiempo Real / Comunicación

    Permanecer conectado

    HTML5 Realtime & Communication
    JS

    Web Workers

    // main.js:
    var worker = new Worker('task.js');
    worker.onmessage = function(event) { alert(event.data); };
    worker.postMessage('data');
    
    // task.js:
    self.onmessage = function(event) {
      // Do some work.
      self.postMessage("recv'd: " + event.data);
    };
    
    Encontrar ruta

    Cargando ruta...

    Prueba a arrastra el mapa mientras la ruta se calcula (¡solo es posible con workers!)

    JS

    WebSocket

    var socket = new WebSocket('ws://html5rocks.websocket.org/echo');
    socket.onopen = function(event) {
      socket.send('Hola Mundodisco!');
    };
    socket.onmessage = function(event) { alert(event.data); }
    socket.onclose = function(event) { alert('closed'); }
    

    Bidireccional y simultánea comunicación en la Web: Tanto el servidor como el cliente pueden enviar información en cualquier momento e incluso a la vez. Solo se envían los datos, sin la sobrecarga de las cabeceras HTTP, reducieno drásticamente el ancho de banda.

    Demostración para probar una conexión WebSocket desde el navegador. Tanto el mensaje que envías como la respuesta recibida viajan por una conexión WebSocket.

    Localización:



    Mensaje:

    Respuesta:
    Demo gracias a
    JS

    Notificaciones

    if (window.webkitNotifications.checkPermission() == 0) {
      // se puede pasar una url como parámetro
      window.webkitNotifications.createNotification(
          tweet.picture, tweet.title,
          tweet.text).show();
    } else {
      window.webkitNotifications.requestPermission();
    }
    

    Nota: Utiliza este botón si quieres reiniciar los permisos


    Una notificación incluye una imagen, un título y un texto

    Acceso a Fichero / Dispositivos

    Integración profunda con el Sistema Operativo

    HTML5 Device Access
    JS

    Drag & Drop nativo

    document.addEventListener('dragstart', function(event) {
      event.dataTransfer.setData('text', 'Texto deseado');
      event.dataTransfer.effectAllowed = 'copy';
    }, false);
    
    1. Selecciona el texto y arrastrar (el texto original será soltado)
    Datos originales
    Área para soltar
    JS

    Desktop Drag-In (File API)

    Arrastrar ficheros desde el escritorio:

    document.querySelector('#dropzone').addEventListener('drop', function(e) {
      var reader = new FileReader();
      reader.onload = function(evt) {
        document.querySelector('img').src = evt.target.result;
      };
    
      reader.readAsDataURL(e.dataTransfer.files[0]);
    }, false);
    
    Arrastra imágenes desde el escritorio
    JS

    Desktop Drag-Out

    Arrastra ficheros hacia el escritorio:

    <a href="src/star.mp3" draggable="true" class="dragout"
       data-downloadurl="MIMETYPE:FILENAME:ABSOLUTE_URI_TO_FILE">download</a>
    
    var files = document.querySelectorAll('.dragout');
    for (var i = 0, file; file = files[i]; ++i) {
      file.addEventListener('dragstart', function(e) {
        e.dataTransfer.setData('DownloadURL', this.dataset.downloadurl);
      }, false);
    }
    
    Arrastra los siguientes ficheros a tu escritorio: .pdf file .mp3 file

    (solo disponible en versiones recientes de Google Chrome)

    JS

    FileSystem APIs

    Escribir asíncronamente un fichero a un sistema de ficheros caja de arena con JavaScript:

    window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function(fs) {
    
      // fs.root is a DirectoryEntry object.
      fs.root.getFile('log.txt', {create: true}, function(fileEntry) {
        // writer es un objeto FileWriter
        fileEntry.createWriter(function(writer) {
            writer.onwrite = function(e) { ... };
            writer.onerror = function(e) { ... };
            var bb = new BlobBuilder();
            bb.append('Hello World!');
    
            writer.write(bb.getBlob('text/plain'));
    
        }, opt_errorHandler);
      }
    
    }, opt_errorHandler);
    

    ( La FileSystem API solo está implementada en Google Chrome 9+ )

    JS

    Geolocalización

    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(function(position) {
        var latLng = new google.maps.LatLng(
            position.coords.latitude, position.coords.longitude);
        var marker = new google.maps.Marker({position: latLng, map: map});
        map.setCenter(latLng);
      }, errorHandler);
    }
    
    JS

    Device Orientation

    window.addEventListener('deviceorientation', function(event) {
      var a = event.alpha;
      var b = event.beta;
      var g = event.gamma;
    }, false);
    

    This sample requires FF3.6+ or Google Chrome on a device with a built in accelerometer or iOS 4.2.

    HTML

    Speech Input

    <input type="text" x-webkit-speech />

    Speech input is not enabled in your browser.
    Try running Google Chrome with the --enable-speech-input flag.

    Semántica & lenguaje de marcado

    Elementos más significativos

    HTML5 Semantics & Markup
    HTML

    Tags más semánticos

    <body>
      <header>
        <hgroup>
          <h1>Título de la página</h1>
          <h2>Subtítulo de la página</h2>
        </hgroup>
      </header>
    
      <nav>
       <ul>
         Menú de navegación...
       </ul>
      </nav>
      <section>
       <article>
         <header>
           <h1>Título</h1>
         </header>
         <section>
           Contenido...
         </section>
       </article>
       <article>
         <header>
           <h1>Título de artículo</h1>
         </header>
         <section>
           Contenido...
         </section>
       </article>
      </section>
    
      <aside>
       Enlaces relacionados...
      </aside>
    
      <figure>
        <img src="..."/>
        <figcaption>Ilustración 1.1</figcaption>
      </figure>
    
      <footer>
       Copyright ©
    <time datetime="2013-11-30">2013</time>. </footer> </body>
    HTML

    Tags para aplicaciones

    <input list="personajes"/>
    <datalist id="personajes">
      <option value="Rincewind"/>
      <option value="DosFlores"/>
      <option value="La Muerte"/>
    </datalist>
    
    
      
    <menu>
      <command type="command" disabled label="Publicar" />
    </menu>
    
    <details>
      <summary>HTML 5</summary>
      Esta presentación es una introduccción a HTML5.
    </details>
    
    HTML 5Esta presentación es una introducción a HTML5
    <meter min="0" max="100" low="40" high="90" optimum="100" value="91">A+</meter>
    Tu puntuación: A+
    <progress>(en progreso)...</progress> Descargando: (en proceso)...
    <progress value="75" max="100">completados 3 de 4</progress> Objetivo: completados 3 de 4
    HTML

    Microdatos

    <div itemscope itemtype="http://example.org/band">
     <p>Mi nombre es <span itemprop="name">Mustrum Ridcully</span>.</p>
     <p>Mi banda es la <span itemprop="band">Soul Music Rock Band</span>.</p>
     <p>Soy itemprop="nationality">Morporkiano</span>.</p>
    </div>
    
    Google Rich Snippets Tool screenshot
    Rich Snippets Testing Tool: http://www.google.com/webmasters/tools/richsnippet
    HTML

    Atributos ARIA (accesibilidad)

    <ul id="tree1"
          role="tree"
          tabindex="0"
          aria-labelledby="label_1">
      <li role="treeitem" tabindex="-1" aria-expanded="true">Razas</li>
      <li role="group">
        <ul>
          <li role="treeitem" tabindex="-1">Humanos</li>
          <li role="treeitem" tabindex="-1">Enanos</li>
          <li role="treeitem" tabindex="-1">Trolls</li>
          ...
        </ul>
      </li>
    </ul>
    
    HTML

    Nuevos tipos para formularios

    <style>
      [required] {
        border-color: #88a;
        box-shadow: 0 0 3px rgba(0, 0, 255, .5);
      }
      :invalid {
        border-color: #e88;
        box-shadow: 0 0 5px rgba(255, 0, 0, .8);
      }
    </style>
    
    <input type="text" required />
    
    <input type="email" value="universidad-invisible.am" />
    
    <input type="date" min="2010-08-14" max="2011-08-14" value="2010-08-14"/>
    
    <input type="range" min="0" max="50" value="10" />
    
    <input type="search" results="10" placeholder="Buscar..." />
    
    <input type="tel"  placeholder="(555) 555-5555"
             pattern="^\(?\d{3}\)?[-\s]\d{3}[-\s]\d{4}.*?$" />
    
    <input type="color" placeholder="e.g. #bbbbbb" />
    
    <input type="number" step="1" min="-5" max="10" value="0" />
    
    HTML

    Tipos de campo en móviles

    type="text"
    teclado android par el tipo text
    Android
    type="number"
    teclado android par el tipo number
    Android
    type="email"
    teclado iphone par el tipo email
    iPhone
    type="tel"
    teclado iphone par el tipo  tel
    iPhone

    Compatibilidad con HTML4

    Cuando IE6 se encuentra con nav, header...

    Los navegadores que no soportan HTML5 tratarán los nuevos tags como si fueran divs.

    IE6 vs input type="email"

    Para el tag input los nuevos tipos tel, date, datetime, time, email, etc... son tratados por los viejos navegadores como si fueran cajas de texto: <input type="text">.

    La mayoría de los nuevos tipos están soportados en practicamente todos los navegadores relativamente recientes.

    ¡Hay soluciones javascript para implementar la misma funcionalidad en el resto navegadores!

    Gráficos / Multimedia

    2D & 3D

    HTML5 3D & Effects HTML5 Multimedia
    HTML JS

    Audio + Vídeo

    <audio id="audio" src="sound.mp3" controls></audio>
    document.getElementById("audio").muted = false;
    
    <video id="video" src="movie.webm" autoplay controls></video>
    document.getElementById("video").play();
    
    HTML JS

    Track

    <video width="390" id="clip" controls>
      <source src="Google_Developer_Stories.webm"
              type='video/webm; codecs="vp8, vorbis"' />
      <track label="Subtítulos en inglés" kind="subtitles" srclang="en"
             src="video-subtitles-en.vtt" default />
    </video>
    
    CSS JS

    FullScreen API

    if (elem.webkitRequestFullScreen) {
      elem.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
    } else if (elem.mozRequestFullScreen) {
      elem.mozRequestFullScreen();
    } else if (elem.requestFullScreen){
      elem.requestFullScreen();
    }
    
    :-webkit-full-screen-ancestor:root {
      overflow: hidden;
    }
    :-webkit-full-screen-ancestor {
      z-index: auto;
      -webkit-transform: none;
      -webkit-transition: none;
    }
    pre:-webkit-full-screen {
      background-color: white;
    }
    
    close: 'ENTER' or 'ESC'
    HTML JS

    Canvas 2D

    <canvas id="canvas" width="838" height="220"></canvas>
    
    <script>
      var canvasContext = document.getElementById("canvas").getContext("2d");
      canvasContext.fillRect(250, 25, 150, 100);
    
      canvasContext.beginPath();
      canvasContext.arc(450, 110, 100, Math.PI * 1/2, Math.PI * 3/2);
      canvasContext.lineWidth = 15;
      canvasContext.lineCap = 'round';
      canvasContext.strokeStyle = 'rgba(255, 127, 0, 0.5)';
      canvasContext.stroke();
    </script>
    HTML JS

    Ejemplo de Canvas

    HTML JS

    Canvas 3D (WebGL)

    <canvas id="canvas" width="838" height="220"></canvas>
    
    <script>
      var gl = document.getElementById("canvas").getContext("experimental-webgl");
      gl.viewport(0, 0, canvas.width, canvas.height);
      ...
    </script>
                
    HTML

    Inline SVG

    <html>
      <svg width="300px" height="300px">
        <defs>
          <linearGradient id="miGradiente" x1="0%" y1="100%" x2="100%" y2="0%">
            <stop offset="5%" stop-color="red"></stop>
            <stop offset="95%" stop-color="blue" stop-opacity="0.5"></stop>
          </linearGradient>
        </defs>
        <circle id="myCircle" class="important" cx="50%" cy="50%" r="100" 
            fill="url(#miGradiente)" onmousedown="alert('hello');"/>
      </svg>
    </html>
    HTML

    Ejemplo de SVG

    CSS3

    Presentación y estilo

    HTML5 Styling
    CSS

    Selectores CSS

    Nuevos selectores

    .row:nth-child(even) {
      background: #dde;
    }
    .row:nth-child(odd) {
      background: white;
    }
    
    Fila 1 (odd)
    Fila 2 (even)
    Fila 3 (odd)
    Fila 4 (even)

    Display tipo imagen

    div {
      display: inline-block;
    }
    

    Atributos específicos

    input[type="text"] {
      background: #eee;
    }

    Negación

    :not(.box) {
      color: #00c;
    }
    :not(span) {
      display: block;
    }
    

    Otros más específicos

    h2:first-child { ... } // 1er hijo
    
    div.text > div { ... } // hijo directo
    h2 + header { ... } // siguiente elem.
    
    CSS

    Webfonts

    @font-face {
      font-family: 'LeagueGothic';
      src: url(LeagueGothic.otf);
    }
    
    @font-face {
      font-family: 'Droid Sans';
      src: url(Droid_Sans.ttf);
    }
    
    header {
      font-family: 'LeagueGothic';
    }
    Tipografía LeagueGothic sin utilizar imágenes

    Muy extendido para añadir iconos, por ejemplo con FontAwesome, iconmonstr, etc...

    CSS

    Text wrapping

    div {
      text-overflow: ellipsis;
    }
    "Hay una puerta". "¿A dónde va?" "Se queda donde está, me parece". "¿Y si utilizas la magía para averiguarlo". Rincewind eran tan dado a la magia como los peces al alpinismo.

    Con { white-space: no-wrap } forzamos que no haya saltos de linea.

    "Hay una puerta". "¿A dónde va?" "Se queda donde está, me parece". "¿Y si utilizas la magía para averiguarlo". Rincewind eran tan dado a la magia como los peces al alpinismo.
    "Hay una puerta". "¿A dónde va?" "Se queda donde está, me parece". "¿Y si utilizas la magía para averiguarlo". Rincewind eran tan dado a la magia como los peces al alpinismo.

    Mueve el deslizador para redimensionar las cajas

    CSS

    Columnas

    -webkit-column-count: 2; 
    -webkit-column-rule: 1px solid #bbb;
    -webkit-column-gap: 2em;

    Havelock Vetinari es el gobernante de Ankh-Morpork.

    Ankh-Morpork tiene como sistema de gobierno ese tipo de democracia que se define por “un hombre, un voto”, en este caso el hombre es el Patricio y el voto el suyo.

    Sus costumbres son muy espartanas, no le gusta el lujo ni los excesos. Su comida suele consistir en una rebanada de pan y un vaso de agua, considerándolo algo sobrio y suficiente.

    La principal afición de Lord Vetinari es trabajar. Se pasa todo el día trabajando y está al corriente de todo lo que ocurre en la ciudad y el Mundodisco, gracias a su extensa red de espías. Es siempre el primero en levantarse por la mañana y el último en acostarse por la noche, hasta el punto de que muchas veces la hora de irse a la cama solo es una excusa para cambiarse de traje. También le gusta la música, pero le parece indigno ponerla en contacto con pieles tensadas en tambores y cuerdas hechas de tripas de gato, por lo que prefiere leerla directamente en las partituras.

    El único ser conocido por el que siente afecto es su perro Galletas, un terrier muy anciano.

    El pensamiento político de Lord Vetinari es absolutamente pragmático y se resume en el lema de su familia: "Si non confectus, non reficiat" (si no está roto, no lo arregles). Esto no significa que su gobierno sea totalmente inmovilista ya que las cosas que sí están rotas son arregladas o eliminadas sin compasión.

    CSS

    Text stroke

    De momento solo en Chrome

    div {
      -webkit-text-fill-color: black;
      -webkit-text-stroke-color: red;
      -webkit-text-stroke-width: 0.00px; 
    }
    Text stroke example
    CSS

    Opacity

      color: rgba(255, 0, 0, 0.75); 
      background: rgba(0, 0, 255, 0.75); 
    
    Transparencias
    CSS

    Hue/saturación/intensidad del color

    color: hsla(
      128 
      74% 
      33% 
      1.00 
            
    HSL example
    CSS

    Esquinas redondeadas

                  face: border-radius: 0px; 
                  left eye: border-radius: 0px; 
                  right eye: border-radius: 0px; 
                  base white: border-radius: 0px; 
                  mouth: border-radius: 0px; 
                  nose: border-radius: 0px; 
                  left black eye: border-radius: 0px; 
                  right black eye: border-radius: 0px; 
                
    CSS

    Gradientes

    background-image: linear-gradient(top, #00abeb 0%, #fff 50%,
                                #66cc00 50%, #fff 100%);
    

    background-image: radial-gradient(center, circle cover, red, #000 40%);
                                                            
    
    CSS

    Sombreados

    text-shadow:
      rgba(64, 64, 64, 0.5)
      0px 
      0px 
      0px; 
    
    box-shadow: rgba(0, 0, 128, 0.25) 0px 0px 0px;
    Ejemplo con sombras
    CSS

    Otros efectos

    text-shadow: rgba(0, 0, 0, 0.5) 0 0px 0px; 
    
    background:
      -webkit-gradient(linear, left top, left bottom, 
                       from(rgba(200, 200, 240, 0)), to(rgba(255, 255, 255, 0)));
    
    border-radius: 0px; 
    
    -webkit-box-reflect: below 10px
      -webkit-gradient(linear, left top, left bottom, 
                       from(transparent), to(rgba(255, 255, 255, 0)));
    
    Web 2.0 Logo Creatr
    CSS

    Mejoras del background

    Background-size

    #logo {
      background: url(logo.gif) center center no-repeat;
      background-size:
        ;
    }
    

    ¡Redimensióname! »

    Múltiples imágenes para el fondo

    div {
      background: url(src/zippy-plus.png) 10px center no-repeat,
                  url(src/gray_lines_bg.png) 0 center repeat-x;
    }
                
    Dos imágenes (rallado y logo de la UI)
    CSS

    Border image

    Border image No.1
    Border image No.2
    Border image No.3
    Border image No.4
    Border image No.5
    -webkit-border-image: url(border_image_1.png) ; border-width: 10px;
    CSS

    Modelo 'Flex Box'

    .box {
      display: -webkit-box;
      -webkit-box-orient: ;
    }
    .box .one, .box .two {
      -webkit-box-flex: 1;
    }
    .box .three {
      -webkit-box-flex: 3;
    }
    
    Caja uno
    Caja dos
    Caja tres
    CSS

    Modelo 'Flex Box'

    .box {
        display: -webkit-box;
        -webkit-box-pack: ;
        -webkit-box-align: ;
      }
    
    CSS

    Transiciones

    #box.izquierda {
      margin-left: 0;
    }
    #box.derecha {
      margin-left: 1000px;
    }
    
    document.getElementById('box').className = 'izquierda'; 
    document.getElementById('box').className = 'derecha'; 
    
    #box {
      -webkit-transition: margin-left 1s ease-in-out;
    }
    
    document.getElementById('box').className = 'izquierda'; 
    document.getElementById('box').className = 'derecha'; 
    
    CSS

    Transformaciones

    Rotar, escalar, etc...

    -webkit-transform: rotateY(45deg);
    -webkit-transform: scaleX(25deg);
    -webkit-transform: translate3d(0, 0, 90deg);
    -webkit-transform: perspective(500px)
    
    #threed-example {
      -webkit-transform: rotateZ(5deg);
    
      -webkit-transition: -webkit-transform 2s ease-in-out;
    }
    #threed-example:hover {
      -webkit-transform: rotateZ(-5deg);
    }
    

    Presiona la tecla 3

    CSS

    Animaciones

    @-webkit-keyframes pulse {
     from {
       opacity: 0.0;
       font-size: 100%;
     }
     to {
       opacity: 1.0;
       font-size: 200%;
     }
    }
    
    div {
      -webkit-animation-name: pulse;
      -webkit-animation-duration: 2s;
      -webkit-animation-iteration-count: infinite;
      -webkit-animation-timing-function: ease-in-out;
      -webkit-animation-direction: alternate;
    }
    

    *Por favor, no lo utilices para molestos parpadeos ;)

    Ejemplo

    “Tuercas & Tornillos”

    Mejoras a la base

    HTML5 Performance & Integration
    JS

    Nuevos selectores

    Buscando elementos por su clase (DOM API)

    var el = document.getElementById('ui');
    el.focus();
    
    var els = document.getElementsByTagName('div');
    els[0].focus();
    
    var els = document.getElementsByClassName('class-name');
    els[0].focus();

    Buscando elementos mediante sintaxis CSS (Selectors API)

    var els = document.querySelectorAll("ul li:nth-child(odd)");
    var tds = document.querySelectorAll("table.test > tr > td");
    var el = document.querySelector("table.test > tr > td"); // el == tds[0]
    
    HTML JS

    Atributos data-*

    Define, almacena y recupera datos en el DOM.

    <div id="tp" data-id="terryp" data-job="escritor" data-screen-name="T. Pratchett"></div>
    // Añadir nuevos atributos mediante JS
    var el = document.querySelector('#out');
    el.setAttribute('data-foo', 'bar');
    // el.data('foo', 'bar'); // ...con jQuery
    
    var html = [];
    for (var key in el.dataset) {
      html.push(key, ': ', el.dataset[key], '<br>');
    }
    
    el.innerHTML = html.join('');
    

    Resultado:

    id: terryp
    job: escritor
    screenName: T. Pratchett
    foo: bar
    
    JS

    Element.classList

    Obtener un array de las clases de un elemento

    <div id="ejemplo" class="sombreado seleccionado"></div>
    var el = document.querySelector('#ejemplo').classList;
    el.add('resaltado');
    el.remove('sombreado');
    el.toggle('resaltado');
    
    console.log(el.contains('resaltado')); // false
    console.log(el.contains('sombreado')); // false
    console.log(el.classList.toString() == el.className); // true
    

    Resultado:

    <div id="ejemplo" class="seleccionado"></div>
    
    JS

    History API

    Controlar el historia de navegación

    link.addEventListener('click', function(event) {
      // añade manualmente un valor a la "pila del histórico"
      // sin hacer que el navegador cargue una nueva página
      history.pushState('Formulario de contacto', 'Página de contacto', '/contactar');
    });
    
    // "capturar" la navegación en caso de que queramos cambiar,
    // por ejemplo, parte del contenido al navegar
    window.addEventListener('popstate', function(event) {
      document.querySelector('h1').innerHTML = event.state; // 'Formulario de contacto'
    });
    

    ¿Qué soporta el navegador?

    Una buena solución es la librería javascript Modernizr que detecta todas las features soportadas por el navegador:

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>Dive Into HTML5</title>
      <script src="modernizr.min.js"></script>
    </head>
    <body>
      ...
    

    añadiendo clases al node raiz html:

    <html class="js flexbox flexboxlegacy canvas canvastext webgl no-touch geolocation [...]
    
    if (Modernizr.canvas) {
      // dibujemos algunos círculos!
    } else { // no hay soporte (IE6) :(
    }
    

    ¿Qué soporta el navegador?

    Si solo vas a usar algunas features puedes tú mismo comprobar el soporte.

    Hay varias técnicas, la mayoría de los trucos utilizan la misma técnica sencilla.

    Por ejemplo:

    function supports_history_api() {
      // Si hay soporte para History API entonces pushState no estará undefined
      return !!(window.history && history.pushState);
    }
    

    Otro ejemplo:

    function supports_input_color() {
      // creamos un input para pruebas
      var i = document.createElement("input");
      // cambiamos su atributo type
      i.setAttribute("type", "color");
      // si el navegador lo soporta mantiene el type del input creado
      return i.type !== "text";
    }
    
    Mas información en Dive into HTML5: el apéndice para detectar casi todo.

    Soporte a toda costa

    Cuando necesitas que se soporte alguna feature en todos los navegadores:

    HTML5 Polyfills

    "The All-In-One Entirely-Not-Alphabetical No-Bullshit Guide to HTML5 Fallbacks"

    ¡Gracias a todos!

    ¿Alguna pregunta?

    Introducción a HTML5

    David Moreno aka @linuxonrails