Preflight
Checking compatibility...
navigator.registerProtocolHandler(), window.requestAnimationFrame(),
Page Visibility API.
--enable-fullscreen flag for 15.
Checking compatibility...
navigator.registerProtocolHandler(), window.requestAnimationFrame(),
Page Visibility API.
--enable-fullscreen flag for 15.
-
<details open> <summary>Information</summary> <p>If your browser supports this element, it should allow you to expand and collapse these details.</p> </details>
If your browser supports this element, it should allow you to expand and collapse these details.
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.
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.
<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>
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.
<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);
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 */);
})();
display:none )
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();
Determine if your app is visible or not:
document.addEventListener('visibilitychange', function(e) {
console.log('hidden:' + document.hidden,
'state:' + document.visibilityState)
}, false);
Prerendering pages:
<link rel="prerender" href="http://example.org/index.html">
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);
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
Web Intents is a framework for client-side service discovery and inter-application communication
Declare intention to handle image sharing:
<intent action="http://webintents.org/share" type="image/*" />
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 )
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!
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 ... ]);
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 )
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);
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);
});
<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();
}
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:
:-webkit-full-screen:-webkit-full-screen-document:-webkit-full-screen-root-with-targetallowFullScreen attribute added for <iframe>
The demand for RTC is real!




...all browser based. All requiring a special download or Flash
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) { ... });
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:
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);
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);
})();
}
Meta tag:
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
Header:
X-UA-Compatible: IE=Edge,chrome=1