KEMBAR78
Is html5-ready-workshop-110727181512-phpapp02 | PDF
Is HTML5
   ready for
production?
Hi, I’m Remy

@rem
remy@leftlogic.com

I <3 JavaScript

Questions: interrupt
& ask!
There's a lot more down here.
HTML5 is a spec
sort of
"HTML5" is a ^brand
MOAR!!!
"HTML5"




          Geolocation
          Web Workers
          Web Sockets
          Web SQL Databases
          Web Storage
          Offline applications
HTML5
          Offline events
          Canvas
          Video
          Web Forms
H TM L5
N OT


NOT HTM
           L5
CSS != HTML
But maybe we should have been more careful
caniuse.com
When can I
use "HTML5"?
Making it
work in
the "other"
browser
Polyfill
A shim that mimics a future
API providing a fallback to
       older browsers
    http://goo.gl/0Z9eI
Tools
Modernizr to detect support
yepnode.js to conditionally load
(available as part of Modernizr)
Tools
Modernizr.load({
  test: Modernizr.geolocation,
  nope: 'geo-polyfill.js',
  complete: initMyGeoApp
});
Oh, and learn
JavaScript
Web Storage
Cookies
suck.
Not the edible ones, duh.




Cookies
suck.
The code for cookies
 is a pain - I always
       google it.
"Session" cookies
leak across sessions.
Persistent cookies
require special date
       format
Deleting a cookie, isn't
 really deleting, but
 setting in the past.
Varying degrees of
limitations on size and
       number.
Fuck cookies.
Sexy Web Storage FTW
One Interface


localStorage
sessionStorage

 http://dev.w3.org/html5/webstorage/
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
5mb?
Done! o/
However: utf-16 ∴ 2½Mb
API
void setItem(key, value)
any* getItem(key)
void removeItem(key)
string key(index)
void clear()
readonly number length
var store = sessionStorage;
Play
       store.setItem('name','rem');
       store.getItem('name');
       store.removeItem('name');




                    Do it in the console!
API
setter setItem
getter getItem
deleter removeItem
var store = sessionStorage;
Play
       store.name = 'rem';
       store.name;
       delete store.name;




                     Do it in the console!
t ip
   There's no security
   protecting the API
 // Safari debugger broken:
 ss.setItem('key', 12);
Values are strings

      Work around: JSON
 (and http://www.json.org/json2.js)
Play
       var store = sessionStorage,
           user = { screen_name : ‘rem’,
                    rating : 11 };


       store.user = JSON.stringify(user));
       var gotUser = JSON.parse(store.user);
       alert(gotUser.screen_name);
Events too
window.addEventListener('storage', function (event) {
  console.log(event);
}, false);


                                http://jsbin.com/ahafa3
Storage in all
  browsers
window.name
sessionStorage = (function () {
  var data = window.name ? JSON.parse(window.name) : {};

  return {
     clear: function () {
        data = {};
        window.top.name = '';
     },
     getItem: function (key) {
        return data[key] || null;
     },
     removeItem: function (key) {
        delete data[key];
        window.top.name = JSON.stringify(data);
     },
     setItem: function (key, value) {
        data[key] = value;
        window.top.name = JSON.stringify(data);
     }
  };
})();
                       http://gist.github.com/350433
t ip
 Firefox cookie security
 applies to Storage too :(
t ip
var cookiesEnabled = (function () {
  // the id is our test value
  var id = +new Date();

  // generate a cookie to probe cookie access
  document.cookie = '__cookieprobe=' + id + ';path=/';

  // if the cookie has been set, then we're good
  return (document.cookie.indexOf(id) !== -1);
})();
Web SQL Databases




             http://flic.kr/p/drmCJ
IndexedDB



            http://flic.kr/p/5KXFwB
Questions?
Canvas
Cooler than this guy.
Canvas   SVG
http://vimeo.com/6691519
• It's not one is better than the other,
  they do different things

• Select canvas when it makes sense
• Don't assume interactive means
  canvas

• Check out raphaeljs.com
http://mrdoob.com
canvas-1.html
Play
       <!DOCTYPE html>
       <html lang="en">
       <head>
       <meta charset="utf-8" />
       <title>Canvas</title>
       </head>
       <body>
         <canvas></canvas>
       </body>
       </html>
        http://dev.w3.org/html5/canvas-api/canvas-2d-api.html
2D API

ctx = canvas.getContext('2d')
Start Simple
fillRect, strokeRect
      & colours
ctx.fillRect(10, 10, 100, 100);
ctx.fillRect(10, 10, 100, 100);
ctx.fillStyle = '#c00';
ctx.fillRect(10, 10, 100, 100);
ctx.fillStyle = '#c00';
ctx.fillRect(100, 75, 50, 50);
ctx.fillRect(10, 10, 100, 100);
ctx.fillStyle = '#c00';
ctx.fillRect(100, 75, 50, 50);
ctx.strokeStyle = '#0c0';
ctx.fillRect(10, 10, 100, 100);
ctx.fillStyle = '#c00';
ctx.fillRect(100, 75, 50, 50);
ctx.strokeStyle = '#0c0';
ctx.lineWidth = 5;
ctx.fillRect(10, 10, 100, 100);
ctx.fillStyle = '#c00';
ctx.fillRect(100, 75, 50, 50);
ctx.strokeStyle = '#0c0';
ctx.lineWidth = 5;
ctx.arc(100,50,25,0,Math.PI*2,true);
ctx.fillRect(10, 10, 100, 100);
ctx.fillStyle = '#c00';
ctx.fillRect(100, 75, 50, 50);
ctx.strokeStyle = '#0c0';
ctx.lineWidth = 5;
ctx.arc(100,50,25,0,Math.PI*2,true);
ctx.stroke();
t ip

  Math.PI == 180°
t ip

 Math.PI *2 == 360°
t ip
  d * Math.PI / 180
      == radian
t ip   CSS stretches
Gradient fills
1. Create a gradient object

2.Add colour stops

3.Set the gradient to the
 fillStyle

4.Draw
var w = canvas.width,
    h = canvas.height;

var gradient = ctx.createLinearGradient(0, 0, w, h);
var w = canvas.width,
    h = canvas.height;

var gradient = ctx.createLinearGradient(0, 0, w, h);
gradient.addColorStop(0, '#fff');
gradient.addColorStop(0.5, '#f00');
gradient.addColorStop(1, '#000');
var w = canvas.width,
    h = canvas.height;

var gradient = ctx.createLinearGradient(0, 0, w, h);
gradient.addColorStop(0, '#fff');
gradient.addColorStop(0.5, '#f00');
gradient.addColorStop(1, '#000');

ctx.fillStyle = gradient;
var w = canvas.width,
    h = canvas.height;

var gradient = ctx.createLinearGradient(0, 0, w, h);
gradient.addColorStop(0, '#fff');
gradient.addColorStop(0.5, '#f00');
gradient.addColorStop(1, '#000');

ctx.fillStyle = gradient;
ctx.fillRect(0, 0, w, h);
Play



createRadialGradient(x0,y0,r0,x1,y1,r1)
Pattern Fills
var img = new Image();
img.src = url;
var pattern = ctx.createPattern(img,'repeat');
ctx.fillStyle = pattern;
ctx.fillRect(0, 0, w, h);
t ip   invalid_state

 img.onload = function () {
    // now use image for canvas
 };
Playing with paths
• For drawing irregular shapes
• Can be filled
• ...or stroked.
lineWidth     rect(x,y,h,w)

lineTo(x,y)   arc(x,y,r,s,e,
              anticw)
moveTo(x,y)
              fill()
beginPath()
              stroke()
closePath()
drawImage
<img>    <canvas>   <video>




        <canvas>
drawImage(src, dx, dy)

drawImage(src, dx, dy, dw, dh)

drawImage(src, sx, sy, sw, sh,
          dx, dy, dw, dh)
Play
       img.onload = function () {
          // this == img
          canvas.width = this.width;
          canvas.height = this.height;
          ctx.drawImage(this, 0, 0);
       };




                           canvas-10.html
pixel
pushing
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 pixels = ctx.getImageData(0, 0, w, h),
    l = pixels.data.length,
    i;

for (i = 0; i < l; i += 4) {




}
var pixels = ctx.getImageData(0, 0, w, h),
    l = pixels.data.length,
    i;

for (i = 0; i < l; i += 4) {


                     This says loop
                     over each pixel
}
var pixels = ctx.getImageData(0, 0, w, h),
    l = pixels.data.length,
    i;

for (i = 0; i < l; i += 4) {
  // red:   pixels.data[i+0]



}
var pixels = ctx.getImageData(0, 0, w, h),
    l = pixels.data.length,
    i;

for (i = 0; i < l; i += 4) {
  // red:   pixels.data[i+0]
  // green: pixels.data[i+1]


}
var pixels = ctx.getImageData(0, 0, w, h),
    l = pixels.data.length,
    i;

for (i = 0;   i < l; i += 4) {
  // red:     pixels.data[i+0]
  // green:   pixels.data[i+1]
  // blue:    pixels.data[i+2]

}
var pixels = ctx.getImageData(0, 0, w, h),
    l = pixels.data.length,
    i;

for (i = 0;   i < l; i += 4) {
  // red:     pixels.data[i+0]
  // green:   pixels.data[i+1]
  // blue:    pixels.data[i+2]
  // alpha:   pixels.data[i+3]
}
ctx.putImageData(pixels, 0, 0)
ctx.putImageData(pixels, 0, 0)

           Needs to be a
         CanvasPixelArray
              object
t ip      security_err

 To use getImageData, your document
 must be served over http (or https) -
 i.e. it doesn't work offline.
/workshop/authors-large.jpg
Play
       greyscale = r*.3 + g*.59 + b*.11;
       r = g = b = greyscale;


       saturation = (Math.max(r,g,b) +
       Math.min(r,g,b))/2;
       r = g = b = saturation;




                      http://jsbin.com/aguho3/2/edit
canvas.toDataURL('image/png');
Play
       save.onclick = function () {
          window.open(
             canvas.toDataURL('image/png')
          );
       };




                                canvas-13.html
Questions?
Offline Applications
Offline Apps

• Application cache / manifest
• Events: offline, online
• navigator.onLine property
http://icanhaz.com/rubiks
Using a Manifest
<!DOCTYPE html>
<html manifest="my.appcache">
<body>
<!-- my page -->
</body>
</html>
my.appcache
CACHE MANIFEST
app.html
css/style.css
js/app.js
#version 13
The Manifest

1. Serve as text/manifest, by
   adding to mime.types:

text/cache-manifest appcache
t ip    Firefox caching

 <IfModule mod_expires.c>
  ExpiresActive on
  ExpiresByType text/cache-manifest
  ↪ “access plus 0 seconds”
 </IfModule>
The Manifest

2. First line must be:

    CACHE MANIFEST
The Manifest

3. Including page is implicitly
   included in the cache.
The Manifest

4. Two futher namespaces:
   NETWORK & FALLBACK

    FALLBACK:
    / offline.html
CACHE MANIFEST

/
index.html
range.js
datastore.js

FALLBACK:
# force everything through
# the index url
/ /

# this won't match
# anything unless it's on
# another domain
NETWORK:
*

# v4
CACHE MANIFEST

                    /
                    index.html
Served from cache   range.js
                    datastore.js

                    FALLBACK:
                    # force everything through
                    # the index url
                    / /

                    # this won't match
                    # anything unless it's on
                    # another domain
                    NETWORK:
                    *

                    # v4
CACHE MANIFEST

                          /
                          index.html
                          range.js
Requests for files not    datastore.js

found in the cache, are   FALLBACK:
                          # force everything through
     directed to /        # the index url
                          / /
    i.e. index.html
                          # this won't match
    (when offline).       # anything unless it's on
                          # another domain
                          NETWORK:
                          *

                          # v4
CACHE MANIFEST

                       /
                       index.html
                       range.js
                       datastore.js
Any requests to urls
                       FALLBACK:
that don't match / -   # force everything through
                       # the index url
  i.e. on another      / /

  domain, will be      # this won't match
                       # anything unless it's on
served through the     # another domain
                       NETWORK:
       web.            *

                       # v4
CACHE MANIFEST

                       /
                       index.html
                       range.js
                       datastore.js

                       FALLBACK:
                       # force everything through
                       # the index url
                       / /
   Also ensures
                       # this won't match
  browser even         # anything unless it's on
                       # another domain
attempts to load the   NETWORK:
                       *
       asset
                       # v4
CACHE MANIFEST

                       /
                       index.html
                       range.js
                       datastore.js

                       FALLBACK:
                       # force everything through
                       # the index url
                       / /
The contents of the
                       # this won't match
   manifest must       # anything unless it's on
                       # another domain
change to trigger an   NETWORK:
                       *
      update
                       # v4
The Manifest

5. Include some versioning to
   cache bust your manifest

     # version 16
The process
Browser: I have a
Browser: request   Server: serve all    manifest, cache
                                            assets



                       Browser:
 Server: serve
                   applicationCache    Browser: reload
manifest assets
                       updated



                    Browser: only
 Browser: serve                        Server: 304 Not
                   request manifest
    locally                               Modified
                         file
Browser: I have a
    Problem: serve all
Browser: requestServer:                manifest, cache
                                           assets
    Change of content
    requires 2 refreshes reload
 Server: serve
                   Browser:
               applicationCache Browser:
manifest assets
                       updated



                    Browser: only
 Browser: serve                       Server: 304 Not
                   request manifest
    locally                              Modified
                         file
document.body.onOnline =
function () {
   // fire an update to the cache
   applicationCache.update();
};
applicationCache.onUpdateReady = function () {
   if (confirm("New version ready. Refresh?")) {
     // reload
     window.location.refresh();
   }
};
t ip

 Do offline last
Questions?
Web Sockets
Native or polyfilled
http://github.com/gimite/web-socket-js/
new WebSocket(url)



   http://dev.w3.org/html5/websockets/
ws://node.remysharp.com:8000




 http://github.com/miksago/node-websocket-server
onopen
onmessage
onclose
onerror
var data = JSON.parse(event.data);
.send
var url = 'ws://node.remysharp.com:8000',
       conn = new WebSocket(url);


conn.onopen = function () {
     conn.send('hello world');
};


conn.onmessage = function (event) {
     console.log(event.data);
};
var url = 'ws://node.remysharp.com:8000',
       conn = new WebSocket(url);


conn.onopen = function () {
     conn.send('hello world');
};


conn.onmessage = function (event) {
     console.log(event.data);
};
var url = 'ws://node.remysharp.com:8000',
      conn = new WebSocket(url);


conn.onopen = function () {
     conn.send('hello world');
};


conn.onmessage = function (event) {
     console.log(event.data);
};
var url = 'ws://node.remysharp.com:8000',
       conn = new WebSocket(url);


conn.onopen = function () {
     conn.send('hello world');
};


conn.onmessage = function (event) {
     console.log(event.data);
};
var url = 'ws://node.remysharp.com:8000',
       conn = new WebSocket(url);


conn.onopen = function () {
     conn.send('hello world');
};


conn.onmessage = function (event) {
     console.log(event.data);
};
var url = 'ws://node.remysharp.com:8000',
       conn = new WebSocket(url);


conn.onopen = function () {
     conn.send('hello world');
};


conn.onmessage = function (event) {
     console.log(event.data);
};
var url = 'ws://node.remysharp.com:8000',
       conn = new WebSocket(url);


conn.onopen = function () {
     conn.send('hello world');
};


conn.onmessage = function (event) {
     console.log(event.data);
};


Play
Questions?
      To contact me after my presentation
      – text NHT to INTRO (46876)


      Or --
      remy@leftlogic.com
      @rem

Is html5-ready-workshop-110727181512-phpapp02