browsers with wings
DESCRIPTION
HTML5 is all the rage with the cool kids, and although there’s a lot of focus on the new language, there’s plenty for web app developers with new JavaScript APIs both in the HTML5 spec and separated out as their own W3C specifications. This session will take you through demos and code and show off some of the outright crazy bleeding edge demos that are being produced today using the new JavaScript APIs. But it’s not all pie in the sky – plenty is useful today, some even in Internet Explorer!TRANSCRIPT
Browserswith
Wings:HTML5 & APIs
HTML5 brand
HTML5 is: markup, JavaScript, CSS, SVG, jQuery & your dinner.
HTML5 is: markup, JavaScript, CSS, SVG, jQuery & your dinner.
Lie.Don't be stoopid, but...
HTML5 is anything & everything to mere mortal beings.
Today
Media
<video src=bruce.mp4>
<video src=bruce.mp4> <a href="bruce.mp4">Download</a></video>
Codec Wars
<video> <source src=bruce.mp4> <source src=bruce.ogv></video>
<video> <source src=bruce.webm> <source src=bruce.mp4> <source src=bruce.ogv></video>
<video controls> <source src=bruce.mp4> <source src=bruce.ogv></video>
<video> works in IE6
<video> works in IE6Lie.
<video width="640" height="360" controls preload="none"> <!-- MP4 must be first for iPad! --> <source src="__VIDEO__.MP4" type="video/mp4" /><!-- WebKit video --> <source src="__VIDEO__.OGV" type="video/ogg" /><!-- Firefox / Opera --> <!-- fallback to Flash: --> <object width="640" height="384" type="application/x-shockwave-flash" data="__FLASH__.SWF"> <!-- Firefox uses the `data` attribute above, IE/Safari uses the param below --> <param name="movie" value="__FLASH__.SWF" /> <param name="flashvars" value="image=__POSTER__.JPG&file=__VIDEO__.MP4" /> <!-- fallback image. note the title field below, put the title of the video there --> <img src="__VIDEO__.JPG" width="640" height="360" alt="__TITLE__" title="No video playback capabilities, please download the video below" /> </object></video><!-- you *must* offer a download link as they may be able to play the file locally. customise this bit all you want --><p> <strong>Download Video:</strong> Closed Format: <a href="__VIDEO__.MP4">"MP4"</a> Open Format: <a href="__VIDEO__.OGV">"OGG"</a></p>
http://camendesign.com/code/video_for_everybody
Custom player style
function toggle() { if (video.paused) { video.play(); this.innerHTML = 'Pause'; } else { video.pause(); this.innerHTML = 'Play'; }}
var play = document.getElementById('play');play.onclick = toggle;
function toggle() { if (video.paused) { video.play(); this.innerHTML = 'Pause'; } else { video.pause(); this.innerHTML = 'Play'; }}
var play = document.getElementById('play');play.onclick = toggle;
function toggle() { if (video.paused) { video.play(); this.innerHTML = 'Pause'; } else { video.pause(); this.innerHTML = 'Play'; }}
var play = document.getElementById('play');play.onclick = toggle;
function toggle() { if (video.paused) { video.play(); this.innerHTML = 'Pause'; } else { video.pause(); this.innerHTML = 'Play'; }}
var play = document.getElementById('play');play.onclick = toggle;
// get & setvideo.currentTime
// half speedvideo.playbackRate = 0.5
// actual loaded videovideo.currentSrc
// etc
video.ontimeupdate = function () { updatePlayhead(this.currentTime);};
Fullscreen?
⚠Warning! User agents should not provide a public API to cause videos to be shown full-screen. A script, combined with a carefully crafted video file, could trick the user into thinking a system-modal dialog had been shown, and prompt the user for a password. There is also the danger of "mere" annoyance, with pages launching full-screen videos when links are clicked or pages navigated. Instead, user-agent specific interface features may be provided to easily allow the user to obtain a full-screen playback mode.
Ca
nv
as
Cooler than a fake Han Solo.
First consider SVG: Standard Vertical Graphing
First consider SVG: Standard Vertical Graphing Lie.
First consider SVG: Standard Vertical Graphing Lie.
Not a lie.
SVG: Vector based, good for simple and interactive
Canvas: Pixel based, good for pixel manipulation & high animation
Check out raphaeljs.com
Mix & match to the technology's strength
pixelpushing
var ctx = canvas.getContext('2d');
ctx.getImageData(0,0,w,h)
ctx.getImageData(0, 0, w, h);
0 1 2 3
i = 0 r g b a
i = 1 r g b a
i... r g b a
pixels.data[i * 4 + 0];
0 1 2 3
i = 0 r g b a
i = 1 r g b a
i... r g b a
pixels.data[i * 4 + 1];
0 1 2 3
i = 0 r g b a
i = 1 r g b a
i... r g b a
pixels.data[i * 4 + 2];
0 1 2 3
i = 0 r g b a
i = 1 r g b a
i... r g b a
pixels.data[i * 4 + 3];
0 1 2 3
i = 0 r g b a
i = 1 r g b a
i... r g b a
var px = ctx.getImageData(0, 0, w, h), l = px.data.length, i;
for (i = 0; i < l; i += 4) {
}
var px = ctx.getImageData(0, 0, w, h), l = px.data.length, i;
for (i = 0; i < l; i += 4) {
}
This says loop over each pixel
var px = ctx.getImageData(0, 0, w, h), l = px.data.length, i;
for (i = 0; i < l; i += 4) { px.data[i+0] = 255 - px.data[i+0];
}
var px = ctx.getImageData(0, 0, w, h), l = px.data.length, i;
for (i = 0; i < l; i += 4) { px.data[i+0] = 255 - px.data[i+0]; px.data[i+1] = 255 - px.data[i+1];
}
var px = ctx.getImageData(0, 0, w, h), l = px.data.length, i;
for (i = 0; i < l; i += 4) { px.data[i+0] = 255 - px.data[i+0]; px.data[i+1] = 255 - px.data[i+1]; px.data[i+2] = 255 - px.data[i+2];
}
var px = ctx.getImageData(0, 0, w, h), l = px.data.length, i;
for (i = 0; i < l; i += 4) { px.data[i+0] = 255 - px.data[i+0]; px.data[i+1] = 255 - px.data[i+1]; px.data[i+2] = 255 - px.data[i+2]; // don't need to do the alphachannel}
var px = ctx.getImageData(0, 0, w, h), l = px.data.length, i;
for (i = 0; i < l; i += 4) { px.data[i+0] = 255 - px.data[i+0]; px.data[i+1] = 255 - px.data[i+1]; px.data[i+2] = 255 - px.data[i+2]; // don't need to do the alphachannel}
ctx.putImageData(px, 0, 0);
You can do that in SVG, but you can't do this:
canvas.toDataURL()
canvas.toDataURL()
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAgAElEQVR4Ae2dCaBd073/f2e692YghpAYQuYQQaP9U8UrnbyktEWjraFNVaU8Q4gSwXNbREIaqVKlpVFPq6G0pMmjeIpXw1NjBkmIVIhMZJDc3OEM/99v7b3P2efcfc49e5+9z9nDd4d79tl7r7V+67PWWd+95liOD8IBAiAAAiAAAjYJxG0+j8dBAARAAARAQBGAgCAjgAAIgAAIOCIAAXGEDY5AAARAAAQgIMgDIAACIAACjghAQBxhgyMQAAEQAAEICPIACIAACICAIwIQEEfY4AgEQAAEQAACgjwAAiAAAiDgiAAExBE2OAIBEAABEICAIA+AAAiAAAg4IgABcYQNjkAABEAABCAgyAMgAAIgAAKOCEBAHGGDIxAAARAAAQgI8gAIgAAIgIAjAhAQR9rVjTqHDxx5Kq9bzaC45+BVqcP
1. Silverlight Bridge2. excanvas.js
Shims
Storage
Cookies suck.
(for most situations)
The code for cookies is painful: so we google it.
"Session" cookies
leak across "sessions".
Non-session cookies require "special" date format
Deleting cookies,
doesn't delete, but sets it
in the past.
Fuck cookies.
Sexy Web Storage FTW
Key/value pair
One APIsetItem(key, value)
One APIsetItem(key, value)
string* getItem(key)
One APIsetItem(key, value)
string* getItem(key)
removeItem(key)
One APIsetItem(key, value)
string* getItem(key)
removeItem(key)
string key(index)
One APIsetItem(key, value)
string* getItem(key)
removeItem(key)
string key(index)
clear()
One APIsetItem(key, value)
string* getItem(key)
removeItem(key)
string key(index)
clear()
.length
Two instances
localStoragesessionStorage
localStorage
• Persists
• Applied to document origin, i.e. scheme/host/port tuple
• No expiry
sessionStorage
• Lasts whilst on the document origin
• Doesn't leak
• Exactly the same API as localStorage
var ss = sessionStorage;
ss.setItem('version', 12);
ss.getItem('version');
Values are strings
Warning!
Values are strings
Work around: JSON(and http://www.json.org/json2.js)
Warning!
var ss = sessionStorage,
user = { screen_name : ‘rem’,
rating : 11 };
ss.setItem(‘user’, JSON.stringify(user));
var obj = JSON.parse(ss.getItem(‘user’));
alert(obj.screen_name);
window.name shim
http://gist.github.com/350433
Alternatives
Web SQL Database
IndexedDB
Geolocation
navigator.geolocation
getCurrentPosition
watchPosition
clearPosition
var geo = navigator.geolocation;
geo.getCurrentPosition(function(data){
map(data.coords.latitude,
data.coords.longitude);
});
var geo = navigator.geolocation;
geo.getCurrentPosition(function(data){
map(data.coords.latitude,
data.coords.longitude);
});
var geo = navigator.geolocation;
geo.getCurrentPosition(function(data){
map(data.coords.latitude,
data.coords.longitude);
});
var geo = navigator.geolocation;
geo.getCurrentPosition(function(data){
map(data.coords.latitude,
data.coords.longitude);
});
var geo = navigator.geolocation;
geo.getCurrentPosition(function(data){
map(data.coords.latitude,
data.coords.longitude);
});
Check your accuracy
if (!navigator.geolocation) { navigator.geolocation = (function (window) { function getCurrentPosition(callback) { // source: http://www.maxmind.com/app/javascript_city var geourl = 'http://j.maxmind.com/app/geoip.js_' + Math.random(), iframe = document.createElement('iframe'), doc, win;
iframe.style.display = 'none'; window.document.body.appendChild(iframe); doc = iframe.contentDocument || iframe.contentWindow.document; win = iframe.contentWindow; // once the script has loaded, it triggers an onload event iframe.onload = function () { // assign all the captured values across to our geo object var geo = { coords: { latitude: win.geoip_latitude(), longitude: win.geoip_longitude() // other values are supported, i.e. accuracy, speed, heading, etc }, timestamp: (new Date()).getTime() }; // then remove the iframe from the body to clear the memory...I hope! window.document.body.removeChild(iframe); callback.call(callback, geo); }; // create a document on the fly doc.open(); doc.write('<' + 'script src="' + geourl + '"><' + '/script>'); doc.close(); } return { clearWatch: function () {}, getCurrentPosition: getCurrentPosition, // TODO shouldn't be too difficult :) watchPosition: function () {} };})(this); }
http://j.mp/geoshim
Sock
ets
Move over
comet.
Low latency.Direct connection.Simple API.
var url = 'ws://apps.leftlogic.com:8000/',
conn = new WebSocket(url);
conn.onmessage = function (event) {
console.log(JSON.parse(event.data));
};
conn.send('hello world');
var url = 'ws://apps.leftlogic.com:8000/',
conn = new WebSocket(url);
conn.onmessage = function (event) {
console.log(JSON.parse(event.data));
};
conn.send('hello world');
var url = 'ws://apps.leftlogic.com:8000/',
conn = new WebSocket(url);
conn.onmessage = function (event) {
console.log(JSON.parse(event.data));
};
conn.send('hello world');
var url = 'ws://apps.leftlogic.com:8000/',
conn = new WebSocket(url);
conn.onmessage = function (event) {
console.log(JSON.parse(event.data));
};
conn.send('hello world');
var url = 'ws://apps.leftlogic.com:8000/',
conn = new WebSocket(url);
conn.onmessage = function (event) {
console.log(JSON.parse(event.data));
};
conn.send('hello world');
var url = 'ws://apps.leftlogic.com:8000/',
conn = new WebSocket(url);
conn.onmessage = function (event) {
console.log(JSON.parse(event.data));
};
conn.send('hello world');
http://github.com/gimite/web-socket-js/
Partial
Offline
Using a Manifest<!DOCTYPE html>
<html manifest="my.manifest">
<body>
<!-- my page -->
</body>
</html>
CACHE MANIFEST
app.html
css/style.css
js/app.js
#version 13
my.manifest
The Manifest
1. Serve as text/manifest, by adding to mime.types:
text/cache-manifest manifest
<IfModule mod_expires.c>
ExpiresActive on
ExpiresByType text/cache-manifest
↪ “access plus 0 seconds”
</IfModule>
tip Firefox caching
The Manifest
2. First line must be:
CACHE MANIFEST
The Manifest
3. Including page is implicitly included in the cache.
The Manifest
4. Include some versioning to cache bust your manifest
# version 16
The Manifest
5. Two futher namespaces: NETWORK & FALLBACK
FALLBACK:/ offline.html
CACHE MANIFEST
CACHE:app.jsapp.cssindex.html
NETWORK:/live/*
FALLBACK:* offline.html
CACHE MANIFEST
CACHE:app.jsapp.cssindex.html
NETWORK:/live/*
FALLBACK:* offline.html
Served from cache
CACHE MANIFEST
CACHE:app.jsapp.cssindex.html
NETWORK:/live/*
FALLBACK:* offline.html
Requests to
http://mysite.com/live/x
must go via the web
CACHE MANIFEST
CACHE:app.jsapp.cssindex.html
NETWORK:/live/*
FALLBACK:/ offline.html
Requests for files not
found in the cache,
are directed to
offline.html (when
offline).
Browser: request Server: serve allBrowser: I have a manifest, cache
assets
Server: serve manifest assets
Browser: applicationCache
updatedBrowser: reload
Browser: serve locally
Browser: only request manifest
file
Server: 304 Not Modified
Browser: request Server: serve allBrowser: I have a manifest, cache
assets
Server: serve manifest assets
Browser: applicationCache
updatedBrowser: reload
Browser: serve locally
Browser: only request manifest
file
Server: 304 Not Modified
Browser: request Server: serve allBrowser: I have a manifest, cache
assets
Server: serve manifest assets
Browser: applicationCache
updatedBrowser: reload
Browser: serve locally
Browser: only request manifest
file
Server: 304 Not Modified
Browser: request Server: serve allBrowser: I have a manifest, cache
assets
Server: serve manifest assets
Browser: applicationCache
updatedBrowser: reload
Browser: serve locally
Browser: only request manifest
file
Server: 304 Not Modified
Browser: request Server: serve allBrowser: I have a manifest, cache
assets
Server: serve manifest assets
Browser: applicationCache
updatedBrowser: reload
Browser: serve locally
Browser: only request manifest
file
Server: 304 Not Modified
Browser: request Server: serve allBrowser: I have a manifest, cache
assets
Server: serve manifest assets
Browser: applicationCache
updatedBrowser: reload
Browser: serve locally
Browser: only request manifest
file
Server: 304 Not Modified
Browser: request Server: serve allBrowser: I have a manifest, cache
assets
Server: serve manifest assets
Browser: applicationCache
updatedBrowser: reload
Browser: serve locally
Browser: only request manifest
file
Server: 304 Not Modified
Browser: request Server: serve allBrowser: I have a manifest, cache
assets
Server: serve manifest assets
Browser: applicationCache
updatedBrowser: reload
Browser: serve locally
Browser: only request manifest
file
Server: 304 Not Modified
Browser: request Server: serve allBrowser: I have a manifest, cache
assets
Server: serve manifest assets
Browser: applicationCache
updatedBrowser: reload
Browser: serve locally
Browser: only request manifest
file
Server: 304 Not Modified
File API
files[0].getAsDataURL()
files[0].getAsDataURL()
Link prefetching
Web Workers
Web Forms
Hash change event, history state management
Contenteditable
Native drag and drop - embedding of data
Microdata
Cross server messaging
embedded attribute data
mime-type registration
DXHTML6
Link prefetching
Web Workers
Web Forms
Hash change event, history state management
Contenteditable
Native drag and drop - embedding of data
Microdata
Cross server messaging
embedded attribute data
mime-type registration
DXHTML6Lie.
"Should I be using HTML5today?"
1. doctype, script & styles only
1. doctype, script & styles only
2. New HTML5 elements
1. doctype, script & styles only
2. New HTML5 elements
3. Existing APIs
1. doctype, script & styles only
2. New HTML5 elements
3. Existing APIs
4. Shims
Yes.