display: and display: display: That's all great...
.box {
display: ;
: ;
: ;
}
.box {
: ;
}
.box > :nth-child(2) {
: ;
}
Example: distribute toolbar icons evenly as device width changes:
.box > * {
: 1 0 0px;
}
.box > :nth-child(2) {
: px;
}
calc()
width: (200px - 100); width: (2 * 50%); width: (200px / 2); color: hsl((120), (75%), 0.5); background-position: (50% + 5px) center;
min()
width: (150px, 100px, 200px); width: (90px + 50px, 100px); width: (100px, 100%); /* where 100% is 200px; */
max()
width: (150px, 100px, 200px); width: (200px - 50px, 100px); width: (100px, 100%); /* where 100% is 200px; */
.circle {
width: 300px;
height: 300px;
}
div {
display: ;
width: (100% - 4em);
height: (100% - 4em);
border-radius: 50%;
: center;
: center;
}
div:hover {
border-radius: 0;
}
cross-fade()
background-image: (url(first.png), url(second.png), 50%);
@-webkit-keyframes fading {
0% { background-image: (url(first.png), url(second.png), 0%); }
100% { background-image: (url(first.png), url(second.png), 100%); }
}
Apply filter effects to any DOM element:
video, img {
: grayscale(0.5) blur(10px);
}
--enable-accelerated flag for hardware accelerated content.Angular ( angularjs.org ) example:
<div ng-app ng-init="val=25">
Volume: <input type="range" min="0" max="100" ng-model="val">
{{val}}/100
</div>
data-* Attributesattr() to get the value(s):before/:after pseudo elements
<style>
input::after {
content: attr(data-value) '/' attr(max);
position: relative;
left: 135px; top: -20px;
}
</style>
<input type="range" min="0" max="100" value="25">
<script>
var input = document.querySelector('input');
input.dataset.value = input.value; // Set an initial value.
input.addEventListener('change', function(e) {
this.dataset.value = this.value;
});
</script>
Browsers: <input list="browsers"> <datalist id="browsers"> <option value="Chrome"> <option value="Firefox"> <option value="Internet Explorer"> <option value="Opera"> <option value="Safari"> </datalist>
list attribute "binds" data list to an <input>Browsers:
data-* attrs / <datalist>
Opening a filesystem:
window.( TEMPORARY, // persistent vs. temporary storage 1024 * 1024, // size (bytes) of needed space initFs, // success callback opt_errorHandler // opt. error callback, denial of access );
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
};
xhr.send();
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
window.(TEMPORARY, 1024 * 1024, function(fs) {
}, onError);
};
xhr.send();
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
window.(TEMPORARY, 1024 * 1024, function(fs) {
fs.root.getFile('image.png', {create: true}, function(fileEntry) {
}, onError);
}, onError);
};
xhr.send();
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
window.(TEMPORARY, 1024 * 1024, function(fs) {
fs.root.getFile('image.png', {create: true}, function(fileEntry) {
fileEntry.createWriter(function(writer) {
writer.onwriteend = function(e) { ... };
writer.onerror = function(e) { ... };
writer.write(new Blob([xhr.response], {type: 'image/png'}));
}, onError);
}, onError);
}, onError);
};
xhr.send();
filesystem: ) URL:filesystem:http://example.com/temporary/image.png
var img = document.createElement('img');
img.src = fileEntry.toURL();
document.body.appendChild(img);
FileEntry from its filesystem: URL:
window.(img.src, function(fileEntry) { ... });
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
window.(TEMPORARY, 1024 * 1024, function(fs) {
fs.root.getFile('image.png', {create: true}, function(fileEntry) {
fileEntry.createWriter(function(writer) {
writer.onwriteend = function(e) { ... };
writer.onerror = function(e) { ... };
writer.write(new Blob([xhr.response], {type: 'image/png'}));
}, onError);
}, onError);
}, onError);
};
xhr.send();
Callback spaghetti is hard,... let's go shopping!
Wrapper lib that implements common UNIX cmds (ls, cp, mv)
var filer = new Filer();
filer.init({persistent: false, size: 1024 * 1024}, function(fs) {...}, onError);
filer.ls('path/to/some/dir/', function(entries) { ... }, onError);
filer.cp('file.txt', '/path/to/folder', 'newname.txt', function(entry) {
// entry.fullPath == '/path/to/folder/newname.txt'
}, onError);
var b = new Blob(['body { color: red; }'], {type: 'text/css'});
filer.write('styles.css', {data: b, type: b.type}, function(entry, writer) {
...
}, onError);
Force downloads with a server:
Content-Disposition: attachment; filename="MyLogo.png";
Use download to download resources rather than navigate to them:
<a href="http://google.com/logo.png" download="Logo.png">download me</a>
function downloadLink(name, content, mimetype) {
var a = document.createElement('a');
a.href = window.(new Blob([content], {type: mimetype}));
a.download = name;
a.textContent = 'Download ready';
document.body.appendChild(a);
}
downloadLink('MyNovel.txt', document.querySelector('textarea').textContent, 'text/plain');
postMessage()postMessage()1. Basic strings
worker.postMessage('Hello World');
window.postMessage(JSON.stringify({msg: 'Hello World'}), '*');
2. JSON
worker.postMessage({msg: 'Look ma, no strings!'});
postMessage()3. Complex types (File, Blob, ArrayBuffer) via structured cloning
var data = [1, 2, 3, 4];
// Blob() in Chrome 20, FF 13
worker.postMessage(new Blob(data.toString(), {type: 'text/plain'}));
var uint8Array = new Uint8Array(data);
worker.postMessage(uint8Array);
worker.postMessage(uint8Array.buffer);
Same old friend, different semantics (note the vendor prefix):
worker.(arrayBuffer, [arrayBuffer]); window.(arrayBuffer, targetOrigin, [arrayBuffer]);
ArrayBuffer) is transferred to new context (e.g. worker/window). Source buffer becomes unavailable.
var uint8Array = new Uint8Array(1024 * 1024 * 32); // 32MB
// Fill'r up!
for (var i = 0, len = uint8Array.length; i < len; ++i) {
uint8Array[i] = i;
}
worker.(uint8Array, [uint8Array.buffer]);
Pass multiple buffers at once and/or additional data:
worker.({ view1: uInt8Array, buffer2: anotherBuffer, username: 'johndoe' }, [uInt8Array.buffer, anotherBuffer]);
.byteLength goes to zero.var ab = new ArrayBuffer(1); worker.(ab, [ab]); if (ab.byteLength) { alert('Transferables are not supported in your browser!'); } else { // Transferables are supported. }
Device APIs WG: www.w3.org/2009/dap/
navigator.onLine / navigator.connection ( network connectivity )<input type="text" x-webkit-speech>
Plugin-free access to camera/microphone.
navigator.({audio: true, video: true}, function(stream) { var video = document.querySelector('video'); video.src = window.(stream); }, function(e) { console.log(e); });
<video autoplay controls></video>
<input type="button" value="⚫" onclick="record(this)"> <input type="button" value="◼" onclick="stop(this)">
var localMediaStream, recorder;
var record = function(button) {
recorder = localMediaStream.record();
};
var stop = function(button) {
localMediaStream.stop();
recorder.getRecordedData(function(blob) {
// Upload blob using XHR2.
});
};
getUserMedia()
<audio>/<video>Use an HTMLMediaElement as the source to the API:
var ctx = new window.(); var audioElement = new Audio(); audioElement.src = 'sounds/dope_beats.mp3'; audioElement.controls = true; audioElement.autoplay = true; var source = ctx.createMediaElementSource(audioElement); var analyser = ctx.createAnalyser(); source.connect(analyser); analyser.connect(ctx.destination);
Note: There's no source.noteOn(0). Play/pause is controlled by the <audio> element.
File, Blob, or ArrayBuffer types.
var socket = new WebSocket('ws://example.com/sock', ['dumby-protocol']);
socket.binaryType = 'blob'; // or 'arraybuffer'
socket.onopen = function(e) {
window.setInterval(function() {
if (socket.bufferedAmount == 0) {
socket.send(new Blob([blob1, blob2]));
}
}, 50); // rate limit us.
};
socket.onmessage = function(e) {
document.querySelector('img').src = (e.data);
};

Source: github.com/ebidel/html5can