Jordan Kasper | @jakerella
What's in it?
Okay, so we can't cover everything...
(Actually a collection of numerous, separate specifications)
input:invalid { background-color: #fdd; }
myFormElem.checkValidity(); // true/false
You'll probably need to use:
progress::-webkit-progress-bar
progress::-webkit-progress-value
progress::-moz-progress-bar
progress
element itself<h4 class='username' contentEditable>jakerella</h4>
<p class='bio' contentEditable>
I am the very model of a modern major general
</p>
I am the very model of a modern major general
myHeader.addEventListener('blur', function() {
alert('Saving username as ' + this.innerText);
});
<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>
window.history.pushState({name: 'Jordan'}, 'Foobar', '/foo/bar');
window.addEventListener('popstate', function(evt) { /* ... */ });
window.history.back();
window.history.forward();
window.history.go(-3);
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
...
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
<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;
});
navigator.getBattery()
.then(function(battery) {
battery.addEventListener('levelchange', function() {
let progress = document.querySelector('.bat-level');
progress.value = battery.level * 100;
});
});
window.addEventListener('offline', function() {
alert('Hmm... it looks like you may be offline.');
});
window.addEventListener('online', updateOnlineStatus);
<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!' );
});
<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()
navigator.geolocation.getCurrentPosition(
function success( pos ) {
console.log( pos.coords.latitude, pos.coords.longitude );
},
function failure(err) {
console.log( 'hmm... something went wrong', err );
}
);
<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]);
});
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'
});
navigator.vibrate(1000);
navigator.vibrate([1000, 500, 500, 500, 1000]);
For new JavaScript APIs this is easy...
if (!navigator.geolocation) {
alert('Your browser does not support Geolocation!');
}
But what about things like the <form>
validation?
<form>
elementcheckValidity
method<input>
element with the required
attributeinvalid
event handlerOr 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...
}
What else is in HTML5/CSS3/JS?
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);
});
// inside the worker script
self.addEventListener('install', function(event) {
// do whatever install is needed
});
self.addEventListener('activate', function(event) {
// do whatever activation is needed
});
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);
}
};
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'});
});
Workers have no DOM access.
Everything is Promise based.
They only work over HTTPS.
Workers die when their document is closed.