me

Jordan Kasper | @jakerella

HTML5 Specification

What's in it?

SO. MUCH.

Okay, so we can't cover everything...

Semantic Tags

header

nav

main

section

article

aside

footer

and much more!

CSS 3

(Actually a collection of numerous, separate specifications)

new selectors

animations

transitions

tranforms

shadows

gradients

etc

etc

etc

Forms: input types and validation

<input type='text' name='username' autocomplete='off' required>
<input type='email' placeholder='me@email.com' autofocus>
<input type='date' min='2016-10-21'>
<input type='number' min='1' max='10'>
<input type='text' pattern='[a-z\-0-9]+'>

Forms: input types and validation

input:invalid { background-color: #fdd; }
myFormElem.checkValidity();  // true/false

Forms: new elements

<progress value='25' max='100'></progress>
<progress value='25' max='100' class='styled'></progress>
<input type='text' list='hobbies' placeholder='favorite hobby'>
<datalist id='hobbies'>
  <option value='reading'></option>
  <option value='board games'></option>
  <option value='coding'></option>
</datalist>

Forms: Progress Bars

Styling these is hard.

You'll probably need to use:

  • progress::-webkit-progress-bar
  • progress::-webkit-progress-value
  • progress::-moz-progress-bar
  • and of course, the progress element itself
  • And what about IE? ಠ_ಠ

Forms: contentEditable

<h4 class='username' contentEditable>jakerella</h4>
<p class='bio' contentEditable>
  I am the very model of a modern major general
</p>

jakerella

I am the very model of a modern major general

myHeader.addEventListener('blur', function() {
  alert('Saving username as ' + this.innerText);
});

ARIA

<button aria-hidden='true' aria-describedby='tip1'>Action</button>
<div id='tip1' role='tooltip' aria-hidden='true'>
  This is the tooltip
</div>
<!-- also use css: visibility:hidden; or just: display:none; -->
<ul role='tablist'>
  <li id='tab1' role='tab'>Tab One</li>
  ...
</ul>
<section aria-labelledby='tab1' aria-live='polite'>
  ...
</section>

Manipulating Browser History

window.history.pushState({name: 'Jordan'}, 'Foobar', '/foo/bar');
window.addEventListener('popstate', function(evt) { /* ... */ });

window.history.back();
window.history.forward();
window.history.go(-3);

Cross-Origin Resource Sharing (CORS) *

In other words: Ajax calls to other domains.

GET https://other.server.com HTTP/1.1
  Origin: https://my.server.com
  Host: my.server.com
  ...
HTTP/1.1 200 OK
  Content-Type: application/json
  Access-Control-Allow-Origin: https://my.server.com
  ...

Web Storage *

localStorage and sessionStorage

localStorage.setItem('username', 'jakerella');
sessionStorage.setItem('currentPage', '/html5');

localStorage.getItem('username');

localStorage.setItem('data', JSON.stringify({ foo: 'bar' }));

Storage limits vary around 5-10 MB

Drag and Drop **

hobbes github twitter grunt
    <img src='/hobbes.png' draggable>
    <ul class='image-drops'></ul>
    var dragged = null;
    imgElem.addEventListener('dragstart', function(e) {
      dragged = this;
    });
    
    imgList.addEventListener('dragover', function(e) {
      e.preventDefault(); // tell the browser this is a drop zone
    });
    
    imgList.addEventListener('drop', function(e) {
      e.target.innerHTML += '
  • ' + dragged.outerHTML + '
  • '; dragged = null; });

    Device Information

    Battery Level *

    navigator.getBattery()
      .then(function(battery) {
    
        battery.addEventListener('levelchange', function() {
          let progress = document.querySelector('.bat-level');
          progress.value = battery.level * 100;
        });
    
      });

    Network State Events

    window.addEventListener('offline', function() {
      alert('Hmm... it looks like you may be offline.');
    });
    
    window.addEventListener('online',  updateOnlineStatus);

    Audio and Video

    <video id='myVid' src='myVideoFile.mp4'></video>
    <video id='myVid' src='myVideoFile.mp4' controls></video>
    <audio src='myAudioFile.mp3' controls></audio>
    myVidElement.play();
    myVidElement.pause();
    myVidElement.addEventListener('pause', function() {
      console.log( 'You paused my video!' );
    });

    User Media *

    <video id='my-stream'></video>
    <button id='stream'>Toggle</button>
    window.navigator.webkitGetUserMedia(
    
      {video: true, audio: false},
    
      function success(stream) {
        $('#my-stream').src = window.URL.createObjectURL(stream);
      },
      function fail(e) { /* handle errors */ }
    );
    
    $('#stream').play();  // or .pause()

    Geolocation *

    navigator.geolocation.getCurrentPosition(
      function success( pos ) {
    
        console.log( pos.coords.latitude, pos.coords.longitude );
    
      },
      function failure(err) {
        console.log( 'hmm... something went wrong', err );
      }
    );

    File API *

    <input type='file' id='fileSelector'>
    <img id='preview' style='width:100px;'>
    $('#fileSelector').addEventListener('change', function(e) {
        var reader = new FileReader();
    
        reader.onload = function(readEvent) {
          $('#preview').setAttribute('src', readEvent.target.result);
        };
    
        reader.readAsDataURL(e.target.files[0]);
      });

    Notifications *

    new Notification('Hello World!');
    if (Notification.permission === "granted") {
      new Notification('Hello World!');
    } else {
      Notification.requestPermission().then(function(result) {
        new Notification('Hello World!');
      });
    }
    new Notification('Hello World!', {
      body: 'This is the body of the message',
      icon: '/images/hobbes_icon.png'
    });

    Vibration *

    navigator.vibrate(1000);
    navigator.vibrate([1000, 500, 500, 500, 1000]);

    Can I Use These?

    Obama Maybe

    Just need a quick check?

    CanIUse.com

    Feature Detection

    For new JavaScript APIs this is easy...

    if (!navigator.geolocation) {
      alert('Your browser does not support Geolocation!');
    }

    Feature Detection

    But what about things like the <form> validation?

    • Create a <form> element
    • See if it has a checkValidity method
    • Create an <input> element with the required attribute
    • Add an invalid event handler
    • Check that the handler fires on form submission
    • ಠ_ಠ

    Feature Detection

    Or you could just use a tool like Modernizr!

    if ( Modernizr.geolocation ) {
      // you can use it!
    }
    if ( Modernizr.formvalidation ) {
      // you can use it!
    }
    if ( !Modernizr.csstransitions ) {
      // It can detect cool new CSS3 features, too!
      // So you can provide JS fallbacks if necessary...
    }

    Cool.

    What else is in HTML5/CSS3/JS?

    So. much. more.

    html5index.org

    www.w3.org/TR/html5/

    Bonus Content!

    Service Workers *

    A background, asynchronous intermediary
    between client and server.

    // in your main html page script
    navigator.serviceWorker.register('/foo/my-script.js')
        .then(function(registration) {
    
            // scope restricted to /foo
            console.log('Success!', registration.scope);
    
        }).catch(function(err) {
            console.log('ServiceWorker failed:', err);
        });

    Service Workers *

    // inside the worker script
    
    self.addEventListener('install', function(event) {
        // do whatever install is needed
    });
    
    self.addEventListener('activate', function(event) {
        // do whatever activation is needed
    });

    Service Workers *

    Sending messages back and forth...

    // in main page script
    var channel = new MessageChannel();
    navigator.serviceWorker.controller
        .postMessage('hello worker!', [channel.port2]);

    Then listen for messages back!

    channel.port1.onmessage = function(evt) {
        if (evt.data.error) {
            console.log('message not received', evt.data.error);
        } else {
            console.log('reveived message back!', evt.data);
        }
    };

    Service Workers *

    Listen on the worker end and send a response...

    // in the service worker
    self.addEventListener('message', function (evt) {
        console.log('message received!', evt.data);
    
        evt.ports[0].postMessage({ 'foo': 'this is my response'});
    });

    Service Workers *

    Some Notes...

    Workers have no DOM access.

    Everything is Promise based.

    They only work over HTTPS.

    Workers die when their document is closed.