Preflight

Checking compatibility...

If things look good, press to move on.

Bleeding Edge HTML5

  -  

Of course we're using Geolocation!

Who?

+


@


Blog:

Agenda

Web Apps

<details> / <summary>

<details open>
  <summary>Information</summary>
  <p>If your browser supports this element, it should allow
  you to expand and collapse these details.</p>
</details>
Information

If your browser supports this element, it should allow you to expand and collapse these details.

Example

Question 1

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.

Question 2

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.

<output>

<form oninput="result.value=a.valueAsNumber + b.valueAsNumber">
0<input type="range" name="b">100 +<input type="number" name="a"> =
<output name="result"></output>
</form>
0100 + =

<mark>

Semantically highlight parts of your text:

Lorem ipsum dolor, <mark>consectetur</mark> adipiscing...

Lorem ipsum dolor, consectetur adipiscing elit. Maecenas egestas facilisis lectus a sagittis. Integer imperdiet nisl non tortor blandit lobortis at eu justo. Etiam viverra nunc id dolor hendrerit vestibulum lobortis tellus ornare.

Speech input

<input type="text" x-webkit-speech>
function inputChange(e) {
  if (e.results) { // e.type == 'webkitspeechchange'
    for (var i = 0, result; result = e.results[i]; ++i) {
      console.log(result.utterance, result.confidence);
    }
    console.log('Best result: ' + this.value);
  }
}

var input = document.querySelector('[x-webkit-speech]');
input.addEventListener('change', inputChange, false);
input.addEventListener('webkitspeechchange', inputChange, false);

Web Apps

Smarter animations

Common technique for JS animations:

window.setTimeout(function() {
  // move element. Call this again.
}, 1000 / 60); // 60fps.

Preferred technique:

window.requestAnimationFrame = window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame || window.msRequestAnimationFrame;

var reqId_ = null;
(function callback(time) { // time is the Unix time.
  // move element.
  reqId_ = window.requestAnimationFrame(callback, opt_elem /* bounding elem */);
})();

Example

function draw() {
  var now = new Date().getTime();
  // update models.
  paintScene(canvas);
  window.setTimeout(draw, 10);
}
draw();

function draw(time) {
  // update models.
  paintScene(canvas);
  window.requestAnimationFrame(draw, canvas);
}
draw();

Page Visibility API / Prerendering

Determine if your app is visible or not:

document.addEventListener('visibilitychange', function(e) {
  console.log('hidden:' + document.hidden,
              'state:' + document.visibilityState)
}, false);

Demo

Prerendering pages:

<link rel="prerender" href="http://example.org/index.html">

Demo

Know when you're connected

Status:

if (navigator.onLine) {
  console.log('ONLINE!');
} else {
  console.log('Connection flaky');
}

Online/offline events:

window.addEventListener('online', function(e) {
  // Re-sync data with server.
}, false);

window.addEventListener('offline', function(e) {
  // Queue up events for server.
}, false);

Custom (web-based) protocol handlers

navigator.registerProtocolHandler(
    'web+myscheme', 'http://example.com/handler?q=%s', 'My App');

<a href="web+myscheme:some%20data%20here">send data</a>
GET http://example.com/handler?q=web+myscheme:some%20data%20here
send data

Web Intents

The web has a problem...

Imagine integrating with all of these!

Web Intents is a framework for client-side service discovery and inter-application communication

How does it work?

  1. Service registers its intention to handle an action for the user
  2. App requests to start an action (share, edit, pick, view, ...)
  3. User selects which service to handle the action.

Sound familiar?

1. Service provider's application registers itself

Declare intention to handle image sharing:

<intent action="http://webintents.org/share" type="image/*" />
action
Required. A verb describing the action to be performed
type
Optional. Mimetype filters
href
Optional. If specified it will point to the action that is loaded when the user chooses the service. If undefined, use the current page.

2. Client app starts an action

App says it wants to use someone's sharing functionality:

var intent = new Intent();
intent.action = 'http://webintents.org/share';
intent.type = 'image/*';
intent.data = imgData;

window.navigator.startActivity(intent);

( 2b. user selects which awesome service to use )

3. Provider handles the action

Passed data ( optional ) is set on page load:

window.intent.data

Then what?

Nothing! - you have just integrated your apps and services

...but there's more!

Two-way communication

Client:

var intent = new Intent('http://webintents.org/pick', 'image/*');

window.navigator.startActivity(intent, function(intentData) {
  var img = document.querySelector('img');
  img.src = intentData.data[0];
});

Service: can post a callback message when it's done:

window.intent.postResult([ ... some data ... ]);

Demo

Demo App

Multimedia

Pasting files

document.body.onpaste = function(e) {
  var items = e.clipboardData.items;
  for (var i = 0; i < items.length; ++i) {
    if (items[i].kind == 'file' && items[i].type == 'image/png') {
      var blob = items[i].getAsFile();

      var img = document.createElement('img');
      img.src = window.URL.createObjectURL(blob);

      document.body.appendChild(img);
    }
  }
};

Click in this window and paste and image ( Copy image from a right-click )

MediaSource API

Allows the developer to define how media is fetched

const NUM_CHUNKS = 5;

var video = document.querySelector('video');
video.src = video.webkitMediaSourceURL;
video.addEventListener('webkitsourceopen', function(e) {
  var chunkSize = Math.ceil(file.size / NUM_CHUNKS);

  // Slice the video into NUM_CHUNKS and append each to the media element.
  for (var i = 0; i < NUM_CHUNKS; ++i) {
    var startByte = chunkSize * i;
    // file is a video file.
    var chunk = file.slice(startByte, startByte + chunkSize);

    var reader = new FileReader();
    reader.onload = (function(idx) {
      return function(e) {
        video.webkitSourceAppend(new Uint8Array(e.target.result));
        logger.log('appending chunk:' + idx);
        if (idx == NUM_CHUNKS - 1) {
          video.webkitSourceEndOfStream(HTMLMediaElement.EOS_NO_ERROR);
        }
      };
    })(i);
    reader.readAsArrayBuffer(chunk);
  }
}, false);

MediaSource API

Camera & microphone access

Plugin-free camera, microphone, device access.

<video autoplay controls></video>
<input type="button" value="⚫" onclick="record(this)" id="start">
<input type="button" value="◼" onclick="stop(this)" id="stop" disabled>
var localMediaStream, recorder;

var record = function(button) {
  recorder = mediaStream.recorder();
};

var stop = function(button) {
  mediaStream.stop();
  recorder.getRecordedData(function(blob) {
    // Upload blob using XHR2.
  });
};

window.navigator.getUserMedia('video', function(stream) {
  document.querySelector('video').src = window.URL.createObjectURL(stream);
  localMediaStream = stream;
}, function(e) {
  console.log(e);
});

Fullscreen content

<video width="300" src="movie.webm" controls></video>
<button onclick="enterFullscreen()">Get Huge!</button>
function enterFullscreen() {
  var elem = document.querySelector('body');
  elem.onwebkitfullscreenchange = function(e) {
    console.log("Entered fullscreen!");
    elem.onwebkitfullscreenchange = onFullscreenExit;
  };
  elem.webkitRequestFullScreen();
}

Demo

Fullscreen API

Control of the entire document and elements:

document.webkitIsFullScreen ( bool )
document.webkitCurrentFullScreenElement ( DOMElement )
document.webkitFullScreenKeyboardInputAllowed ( bool )
document.webkitCancelFullScreen();
Element.webkitRequestFullScreen();
//Element.webkitRequestFullScreenWithKeys();

Control of media elements:

MediaElement.webkitSupportsFullscreen ( bool )
MediaElement.webkitDisplayingFullscreen ( bool )
MediaElement.webkitEnterFullScreen()
MediaElement.webkitExitFullScreen()

New pseudo-classes, an attributes:

Web RTC

What's the problem?

The demand for RTC is real!

GMail Video Chat
Google Plus Hangout
Facebook Video Chat
Tokbox

...all browser based. All requiring a special download or Flash

What is WebRTC?

high quality real-time voice/video communication in the browser


Example

var pc = new PeerConnection('STUN example.com:8000', onSignalingMessage);

function onSignalingMessage(msg, source) {
  // send message to the other side via the signaling channel.
  pc.processSignalingMessage(msg);
}

pc.onaddstream = function(e) {
  remoteVideo.src = window.webkitURL.createObjectURL(e.stream);
};

pc.onremovestream = function(e) {
  video.src = '';
};

window.navigator.webkitGetUserMedia('video,audio', function(localStream) {
  localVideo.src = window.webkitURL.createObjectURL(localStream);
  pc.addStream(localStream); // Start sending video
}, function(e) { ... });

Build the future...

Robot

Community effort

Web Audio API

Don't we already have HTML5 <audio>?

Scheduled playback

var ctx = new window.webkitAudioContext();

function playSound(arrayBuffer) { // Obtain arrayBuffer from XHR2.
  ctx.decodeAudioData(arrayBuffer, function(buffer) {
    var src = ctx.createBufferSource();
    src.buffer = buffer;
    src.looping = false;
    src.connect(ctx.destination);
    src.noteOn(0); // Play immediately.
  }, function(e) {
    console.log(e);
  });
}

Shoot:

Generating sound

var sine = new Oscillator(DSP.SINE, 440, 1.0, 2048, 44100).generate(); // dsp.js

var src = ctx.createBufferSource();
src.buffer = ctx.createBuffer(1 /*channels*/, 2048, 44100);
src.buffer.getChannelData(0).set(sine);
src.looping = true;

src.connect(ctx.destination);
src.noteOn(0);

Audio processing

var ctx = new webkitAudioContext();
var analyser = ctx.createAnalyser();

function initAudio(arrayBuffer) {
  ctx.decodeAudioData(arrayBuffer, function(buffer) {
    var src = ctx.createBufferSource();
    src.buffer = buffer;
    src.connect(analyser); // src -> analyser -> destination
    analyser.connect(ctx.destination);
    render(src);
  }, function(e) {
    console.log('Error decoding audio file', e);
  });
}

function render(src) {
  (function callback(timeStamp) {
    var byteData = new Uint8Array(analyser.frequencyBinCount);
    analyser.getByteFrequencyData(byteData);

    // draw byteData to <canvas> visualization...

    window.requestAnimationFrame(callback, src);
  })();
}

That was a lot!

chromestatus.com

updates.html5rocks.com

Chrome Frame

Meta tag:

<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">

Header:

X-UA-Compatible: IE=Edge,chrome=1

Resources



Thanks! Questions?

@   +