Download - HTML5: huh, what is it good for?
![Page 1: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/1.jpg)
HTML5Huh, What is it good for?
![Page 2: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/2.jpg)
Remy Sharp@rem
Plug: Introducing HTML5
![Page 3: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/3.jpg)
๏HTML๏New HTML5 elements
๏Buzzword๏Simple doctype
It's more than
![Page 4: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/4.jpg)
<!doctype html><html lang="en"><head> <meta charset="utf-8"> <title>My HTML5 page</title> <style> body { font-family: sans-serif; } </style></head><body><article> <h1>My story</h1> <p>With JavaScript</p></article><script src="funky.js"></script><script>makeFunky(document.querySelector('article'));</script></body></html>
<!doctype html>
<style> <script>
<article>
![Page 5: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/5.jpg)
JavaScript๏Offline
๏App cache
๏WebStorage
๏WebSQL
๏IndexedDB
๏Multimedia
๏Video & Audio
๏2D Canvas
![Page 6: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/6.jpg)
JavaScript๏X-domain messaging
๏CORS
๏File API
๏Drag & Drop
๏History API
๏Lots, lots more.
![Page 7: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/7.jpg)
JavaScript๏ Drawing๏ Offline๏ URLs๏ Real-time
![Page 8: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/8.jpg)
When can I use "HTML5"?
![Page 9: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/9.jpg)
![Page 10: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/10.jpg)
![Page 11: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/11.jpg)
![Page 12: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/12.jpg)
![Page 13: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/13.jpg)
Making it work in the "other" browser
![Page 14: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/14.jpg)
Polyfillswill/might save youA shim that mimics a futureAPI providing a fallback to
older browsershttp://goo.gl/0Z9eI
![Page 15: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/15.jpg)
ToolsModernizr to detect support
yepnode.js to conditionally load(available as part of Modernizr)
![Page 16: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/16.jpg)
ToolsModernizr.load({ test: Modernizr.geolocation, nope: 'geo-polyfill.js', complete: initMyGeoApp});
![Page 17: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/17.jpg)
Oh, and learn JavaScript
![Page 18: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/18.jpg)
CanvasHan Solo of HTM
L5
![Page 19: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/19.jpg)
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><title>Canvas</title></head><body> <canvas></canvas></body></html>
![Page 20: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/20.jpg)
2D APIctx = canvas.getContext('2d')
![Page 21: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/21.jpg)
![Page 22: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/22.jpg)
๏Gradients๏Pixel manipulation๏Paths๏Shadows๏Export to data url๏State saving
![Page 23: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/23.jpg)
Gradients
![Page 24: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/24.jpg)
var rainbow = ctx.createLinearGradient(0, 0, w, h), colours = { 0: 'red', 0.167: 'orange', 0.333: 'yellow', // etc };
for (var key in colours) { rainbow.addColorStop(key, colours[key]);}
ctx.fillStyle = rainbow;ctx.fillRect(0, 0, w, h);
Gradients
![Page 25: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/25.jpg)
Pixel Pushing
![Page 26: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/26.jpg)
var pixels = ctx.getImageData(0, 0, w, h), len = pixels.data.length;
for (var i = 0; i < len; i += 4) { var rgb = 'rgb(' + // ↵ [ pixels.data[i], // red pixels.data[i+1], // green pixels.data[i+2] // blue ].join(',') + ')';}
Pixel Pushing
![Page 27: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/27.jpg)
Shadows & Paths
![Page 28: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/28.jpg)
ctx.shadowBlur = 2;ctx.shadowOffsetX = 2;ctx.shadowOffsetY = 2;ctx.shadowColor = 'rgba(0,0,0,.7)';
Shadows
![Page 29: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/29.jpg)
var pinsize = 26, pinedge = pinsize * 0.1, centre = pinsize/2, radius = centre - pinedge, circle = Math.PI * 2;
ctx.fillStyle = rgb; // from our pixelctx.beginPath();ctx.arc(centre, centre, // ↵ radius, 0, circle, true);ctx.closePath();ctx.fill();
Paths
![Page 30: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/30.jpg)
![Page 31: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/31.jpg)
ctx.canvas.toDataURL('image/png')
Export
data:image/png;base64,...
![Page 32: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/32.jpg)
Tipcontext.canvas
All context contain back-reference to it's canvas
![Page 33: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/33.jpg)
pinctx.fillStyle = '#fff';pinctx.save();pinctx.fillStyle = '#f00';// do somethingpinctx.restore();// now fillStyle is #fff
State Saving
![Page 34: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/34.jpg)
![Page 35: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/35.jpg)
Offline Applications
![Page 36: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/36.jpg)
Using a Manifest<!DOCTYPE html><html manifest="my.appcache"><body><!-- my page --></body></html>
![Page 37: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/37.jpg)
CACHE MANIFESTapp.htmlcss/style.cssjs/app.js#version 13
my.appcache
![Page 38: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/38.jpg)
The Manifest
1. Serve as text/manifest, by adding to mime.types:
text/cache-manifest appcache
![Page 39: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/39.jpg)
<IfModule mod_expires.c> ExpiresActive on ExpiresByType text/cache-manifest ↪ “access plus 0 seconds”</IfModule>
Firefox caching
![Page 40: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/40.jpg)
The Manifest
2. First line must be:
CACHE MANIFEST
![Page 41: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/41.jpg)
The Manifest
3. Including page is implicitly included in the cache.
![Page 42: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/42.jpg)
The Manifest
4. Two futher namespaces: NETWORK & FALLBACK
![Page 43: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/43.jpg)
CACHE MANIFEST
CACHE:app.jsapp.cssindex.html
NETWORK:http://*https://*
FALLBACK:/ offline.html
![Page 44: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/44.jpg)
CACHE MANIFEST
CACHE:app.jsapp.cssindex.html
NETWORK:http://*https://*
FALLBACK:/ offline.html
What to cache
![Page 45: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/45.jpg)
CACHE MANIFEST
CACHE:app.jsapp.cssindex.html
NETWORK:http://*https://*
FALLBACK:/ offline.html
App cache requires all resources are accounted for.
![Page 46: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/46.jpg)
CACHE MANIFEST
CACHE:app.jsapp.cssindex.html
NETWORK:http://*https://*
FALLBACK:/ offline.html
Requests for files not found in the cache, are directed to offline.html (when offline).
![Page 47: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/47.jpg)
CACHE MANIFEST
CACHE:app.jsapp.cssindex.html
NETWORK:http://*https://*
FALLBACK:/ offline.html
![Page 48: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/48.jpg)
The Manifest
5. Include some versioning to cache bust your manifest
# version 16
![Page 49: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/49.jpg)
![Page 50: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/50.jpg)
applicationCache.onUpdateReady = function () { if (confirm("New version ready. Refresh?")) { // reload window.location = window.location; }};
When your app updates
![Page 51: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/51.jpg)
Do offline last
Tip
![Page 52: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/52.jpg)
Web Storagehttp://www.flickr.com/photos/ph0t0s/64821154
![Page 53: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/53.jpg)
Key / Value pair๏localStorage, persistent๏sessionStorage, temporary๏Extremely simple to use๏Storage events
![Page 54: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/54.jpg)
sessionStorage.name = '@rem';
// page is reloadedvar name = sessionStorage.name;if (name !== undefined) { alert('Welcome back ' + name);}
![Page 55: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/55.jpg)
sessionStorage.name = '@rem';
// page is reloadedvar name = sessionStorage.name;if (name !== undefined) { alert('Welcome back ' + name);}
![Page 56: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/56.jpg)
sessionStorage.name = '@rem';
// page is reloadedvar name = sessionStorage.name;if (name !== undefined) { alert('Welcome back ' + name);}
![Page 57: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/57.jpg)
Storagecoerces to
String
![Page 58: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/58.jpg)
Storagecoerces to
Stringvar sess = sessionStorage;
sess.data = JSON.stringify(data);
![Page 59: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/59.jpg)
Storagecoerces to
Stringvar sess = sessionStorage;
sess.data = JSON.stringify(data);
var data = JSON.parse( sess.data || '{}' // or empty obj);
![Page 60: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/60.jpg)
Eventswindow.onstorage = function(e){ // e.key // e.newValue // e.oldValue // e.url};
![Page 61: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/61.jpg)
![Page 62: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/62.jpg)
URLs
![Page 63: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/63.jpg)
![Page 64: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/64.jpg)
History APIhistory.pushState(obj, title, url);
window.onpopstate = fn;
![Page 65: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/65.jpg)
Detection!!(window.history && history.pushState)
![Page 66: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/66.jpg)
Polyfill
History.jshttps://github.com/balupton/history.js
![Page 67: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/67.jpg)
hashchange
window.onhashchange = function(e) { // user went back or forward // now read location.hash};
![Page 68: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/68.jpg)
Server SentEvents"push based XHR"
![Page 69: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/69.jpg)
Prerequisites๏Persistent connection support
(event based are favourable: ie. node, twisted, etc)
๏Support in browser*
๏ If not native, fails over to polling
but we can fix that :)
![Page 70: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/70.jpg)
Limitations๏Same origin rules
๏No support in Firefox or IE
๏Read only
![Page 71: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/71.jpg)
Usagevar es = new EventSource(url);
es.onopen = function () { console.log('open stream');};
es.onmessage = function (event) { console.log('got message: ' + event.data);};
![Page 72: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/72.jpg)
Server codeapp.get('/sse', function (req, res) { connections.push(res); res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' }); res.write('eventId:0\n\n');});
Using Connect
![Page 73: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/73.jpg)
Server codeconnections.forEach(function (c) { c.write('data:' + JSON.stringify(req.body) + '\n\n');});
req.body is an object of key/values
![Page 74: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/74.jpg)
![Page 75: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/75.jpg)
Web SocketsTwo way real-time comms
http://www.flickr.com/photos/44442915@N00/4960579336
![Page 76: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/76.jpg)
In a nutshell๏Persistent connection๏Tiny chunks of data exchanged๏Bi-directional & no origin rules
![Page 77: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/77.jpg)
Some Uses๏Chat / "hello world"
๏Streaming data like stock share prices
๏Multi-player game state
๏Google Wave remember? :)
![Page 78: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/78.jpg)
Native or polyfilled
IE6✓ :'(
![Page 79: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/79.jpg)
http://github.com/gimite/web-socket-js/
![Page 80: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/80.jpg)
var url = 'ws://node.remysharp.com:8000', conn = new WebSocket(url);
conn.onopen = function () { conn.send('@rem says Hi!');};
conn.onmessage = function (event) { console.log(event.data);};
![Page 81: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/81.jpg)
var url = 'ws://node.remysharp.com:8000', conn = new WebSocket(url);
conn.onopen = function () { conn.send('@rem says Hi!');};
conn.onmessage = function (event) { console.log(event.data);};
![Page 82: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/82.jpg)
var url = 'ws://node.remysharp.com:8000', conn = new WebSocket(url);
conn.onopen = function () { conn.send('@rem says Hi!');};
conn.onmessage = function (event) { console.log(event.data);};
![Page 83: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/83.jpg)
var url = 'ws://node.remysharp.com:8000', conn = new WebSocket(url);
conn.onopen = function () { conn.send('@rem says Hi!');};
conn.onmessage = function (event) { console.log(event.data);};
![Page 84: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/84.jpg)
var url = 'ws://node.remysharp.com:8000', conn = new WebSocket(url);
conn.onopen = function () { conn.send('@rem says Hi!');};
conn.onmessage = function (event) { console.log(event.data);};
![Page 85: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/85.jpg)
var url = 'ws://node.remysharp.com:8000', conn = new WebSocket(url);
conn.onopen = function () { conn.send('@rem says Hi!');};
conn.onmessage = function (event) { console.log(event.data);};
![Page 86: HTML5: huh, what is it good for?](https://reader033.vdocuments.us/reader033/viewer/2022052410/5558bdefd8b42aa52a8b5082/html5/thumbnails/86.jpg)
var url = 'ws://node.remysharp.com:8000', conn = new WebSocket(url);
conn.onopen = function () { conn.send('@rem says Hi!');};
conn.onmessage = function (event) { console.log(event.data);};