Edit in JSFiddle


              
<head>
	<title>Hixie Keyboard — Shiny Demos</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width">
	<link rel="stylesheet" href="styles/screen.css">
	<link rel="stylesheet" href="/styles/panel.css">
</head>
<body>
	<div class="cable"></div>
	<div class="device">
		<p class="lcd" id="lcd">_</p>
		<div class="display">
			<video preload width="170" height="220" class="video" id="video">
				<source src="http://media.shinydemos.com/hixie-keyboard/hixie.mp4" type="video/mp4">
				<source src="http://media.shinydemos.com/hixie-keyboard/hixie.webm" type="video/webm">
				<source src="http://media.shinydemos.com/hixie-keyboard/hixie.ogv" type="video/ogg">
			</video>
			<!-- Video © 2008 Google, CC-BY -->
		</div>
		<ul class="keyboard" id="keyboard">
			<li class="row first">
				<button class="key" id="key-q" data-text="&lt;q&gt; element">Q</button><button class="key" id="key-w" data-text="web workers">W</button><button class="key" id="key-e" data-text="&lt;embed&gt;">E</button><button class="key" id="key-r" data-text="&lt;ruby&gt;">R</button><button class="key" id="key-t" data-text="&lt;track&gt;">T</button><button class="key" id="key-y" data-text="yeah, what's your use case?">Y</button><button class="key" id="key-u" data-text="utf-8">U</button><button class="key" id="key-i" data-text="itemprop is better than microformats">I</button><button class="key" id="key-o" data-text="&lt;output&gt;">O</button><button class="key" id="key-p" data-text="postmessage &lt;progress&gt; pattern placeholder">P</button>
			</li>
			<li class="row second">
				<button class="key" id="key-a" data-text="&lt;article&gt;">A</button><button class="key" id="key-s" data-text="&lt;section&gt;">S</button><button class="key" id="key-d" data-text="&lt;details&gt;">D</button><button class="key" id="key-f" data-text="&lt;figure&gt; and &lt;figcaption&gt;">F</button><button class="key" id="key-g" data-text="geolocation isn't really part of html5">G</button><button class="key" id="key-h" data-text="&lt;header&gt;">H</button><button class="key" id="key-j" data-text="javascript is lovely">J</button><button class="key" id="key-k" data-text="&lt;keygen&gt;">K</button><button class="key" id="key-l" data-text="localstorage">L</button>
			</li>
			<li class="row third">
				<button class="key" id="key-z" data-text="z-index, cause css is part of html5">Z</button><button class="key" id="key-x" data-text="xhtml is for losers">X</button><button class="key" id="key-c" data-text="&lt;canvas&gt;">C</button><button class="key" id="key-v" data-text="&lt;video&gt;">V</button><button class="key" id="key-b" data-text="&lt;bdi&gt;">B</button><button class="key" id="key-n" data-text="&lt;nav&gt;">N</button><button class="key" id="key-m" data-text="&lt;menu&gt; and &lt;meter&gt;">M</button>
			</li>
		</ul>
	</div>
	<script src="/scripts/modernizr.js"></script>
	<script src="/scripts/panel.js"></script>
	<script src="scripts/options.js"></script>
	<script src="scripts/script.js"></script>
<script>
var body = document.body,
video = document.getElementById('video'),
lcd = document.getElementById('lcd'),
keys = document.querySelectorAll('#keyboard button'),
sounds = [], media = 'http://media.shinydemos.com/hixie-keyboard/';

document.addEventListener('DOMContentLoaded', function() {
for(var i=0, l=keys.length; i<l; i++) {
var key = keys[i],
name = key.id.split('-')[1];
var sound = document.createElement('audio');
sound.preload = true;
sound.id = 'sound-' + name;
sounds[i] = sound;
var mp3 = document.createElement('source');
mp3.src = media + name + '.mp3';
mp3.type = 'audio/mpeg';
var ogg = document.createElement('source');
ogg.src = media + name + '.ogg';
ogg.type = 'audio/ogg';

sound.appendChild(mp3);
sound.appendChild(ogg);
body.appendChild(sound);

sound.load();

key.onmousedown =
key.ontouchstart = keyAction;
}
}, false);

function keyAction(e, name) {
var key = (name) ? document.getElementById('key-' + name) : e.target,
sound = document.getElementById('sound-' + key.id.split('-')[1]);
if(allPaused()) {
key.classList.add('pressed');
video.currentTime = 0;
sound.play();
video.play();
lcd.innerText = key.dataset.text;
}
sound.addEventListener('ended', function() {
key.classList.remove('pressed');
video.pause();
lcd.innerText = '_';
}, false);
e.preventDefault();
}

function allPaused() {
for(var i=0, l=sounds.length; i<l; i++) {
if(!(sounds[i].paused || sounds[i].ended)) return false;
}
return true;
}

function keyHandler(e) {
if(e.altKey || e.ctrlKey || e.metaKey) return;
var name;
switch (e.which) {
case 81: name = 'q'; break;
case 87: name = 'w'; break;
case 69: name = 'e'; break;
case 82: name = 'r'; break;
case 84: name = 't'; break;
case 89: name = 'y'; break;
case 85: name = 'u'; break;
case 73: name = 'i'; break;
case 79: name = 'o'; break;
case 80: name = 'p'; break;
case 65: name = 'a'; break;
case 83: name = 's'; break;
case 68: name = 'd'; break;
case 70: name = 'f'; break;
case 71: name = 'g'; break;
case 72: name = 'h'; break;
case 74: name = 'j'; break;
case 75: name = 'k'; break;
case 76: name = 'l'; break;
case 90: name = 'z'; break;
case 88: name = 'x'; break;
case 67: name = 'c'; break;
case 86: name = 'v'; break;
case 66: name = 'b'; break;
case 78: name = 'n'; break;
case 77: name = 'm'; break;
default: return;
}
keyAction(e, name);
}

document.addEventListener('keydown', keyHandler, false);</script>

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin:0;
padding:0;
border:0;
font-size:100%;
font:inherit;
vertical-align:baseline;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display:block;
}
body {
line-height:1;
}
ol, ul {
list-style:none;
}
blockquote, q {
quotes:none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content:'';
content:none;
}
table {
border-collapse:collapse;
border-spacing:0;
}