The Future of the Web

...and the one polyfill that makes it all possible today

Browser Support

WeakMap: Chrome, FF, IE11

Object.observe: Chrome 36

MutationObserver: all but IE10, Safari 6.1, Android 4.3

Web Components:  Chrome 36, FF 32, Android 4.4


keys are objects

values can be anything

does not prevent garbage collection of keys 

Use Cases

Associate data with an element w/out augmenting the element

Associate data with a read-only object

More efficient information hiding


var map = new WeakMap();

var someEl = 

map.set(someEl, {foo: 'bar'}); 

if (map.has(document.getElementById('someEl') {
    map.get(someEl).foo; // bar


Receive callbacks when an object changes in any way

Native impl for Angular's scope.$watch

For Arrays: Array.observe

Angular will delegate in 2.0

Angular = 'Ray';

scope.$watch('name', function(newV, oldV) {
    console.log('old name: ' + oldV);
    console.log('new name: ' + newV);

Native = "Ray";

Object.observe(scope, function(change) {
    if ( === 'name') {
        console.log('old name: ' + 

        console.log('new value: ' + 


Receive callbacks when an element changes in any way

Element descendendants can also be observed

Replacement for inefficient Mutation Events


var callback = function(records) {
    var record = records[0]; // for demo simplicity only
    var added = record.addedNodes;
    if (added.length) {
        var newTags = 0;
        for (var i = 0; i < added.length; i++) {
            if (added[i].className.indexOf('tag') >= 0) {

if (newTags) { alert(newTags + " new tags added."); } } }; var observer = new MutationObserver(callback); observer.observe(tagsContainerEl, {childList: true});

Web Components


Custom Elements

Shadow DOM


Create re-usable content

<template> is not rendered, must be "activated"

Any elements can be children

    <div>hi there</div>
    <div>you can't see me right now</div>
    <blink>luckily for you</blink>
Live example [jsbin]

HTML Imports

Pull another HTML file into the current document

Inject a packaged component (and all deps) w/ one line

Re-use templates stored in a central location

<link rel="import" href="/license.html">

Using an imported document

// Grab the <link> that imports the licensing blurb
var licensingLink = document.getElementById('licenseLink');
// Grab the relevant content from the imported docvar content = licensingLink.import.getElementById('license');
// Append the content to our doc document.body.appendChild(content);

NOTE: Server must return proper CORS headers for cross-domain imports

Custom Elements


MUST contain a dash
Take heed angular directive writers.  
Use ember?  You're cool. 

To avoid conflict w/ future standardized elements.

Creating Custom Elements

Initially an  :unresolved  HTMLElement

To "resolve", you must  document.registerElement

Two types:
  1. New* CE
  2. Type Extension CE

* I just made up this name

Standard Custom Element

   <!-- unresolved content -->


Type Extension Custom Element

<video is="frame-grabber" src="somevideo.mp4"></video>

var frameGrabber = 
   document.createElement('video', 'frame-grabber');

frameGrabber.prototype.grab = function() {
   // grab current frame & do something w/ it

Shadow DOM

Allows creation of self-contained, sandboxed web components

A single Node can now be made up of 3 different subtrees:

  • Light DOM 
  • Shadow DOM
  • Composed DOM

Light DOM Tree

Part of the "logical DOM"

 Content of the custom element provided by integrator

   Bring back the blink tag!

Displayed pre-shadow-root render

Shadow DOM Tree

Part of the "logical DOM"
Internal to the custom element, not a child

Not directly accessible via the light DOM

  1. Include element on page
  2. Register (if CE)
  3. myElement.createShadowRoot();
  4. Append content to shadow root
  5. Live example [jsbin]

Composed DOM Tree

Content that is actually rendered

Pieces of the light and shadow DOM combined

Composed DOM from the <blink-is-back> CE:

   <div style="text-decoration: line-through;">
      Bring back the blink element!
   <div>But seriously, don't make text blink.</div>


Shim for all specs discussed in this presentation

Defers to native impls, when present

So, You can use all of these cool specs now!

The first devolving framework

Less important as Web Components et al. coverage increases

Should disappear when these specs are implemented everywhere

A polyfill for Shadow DOM?  How?

It's complicated

Everything is wrapped

Required to:
  • maintain encapsulation 
  • maintain separation between light & shadow DOM elements
  • retarget events originally destined for the shadow DOM tree


Web Component built using Polymer

Allows <input type='file'> to be easily styled

Built-in file validation

More intuitive access to (valid) files


<file-input class="btn btn-primary" 
            extensions='["jpeg", "jpg"]' 

   <span class="glyphicon glyphicon-file"></span>    Select a file



Web Component built using Polymer

Submit a form without a page reload

Send custom headers w/ form submit

Easy access to server response

Dirt simple validation support/control

Submit <file-input> elements too!


<form is="ajax-form"
    headers='{"X-Cust-Header": "FooBar"}'>

    <input type="text" name="fullname" required>    <input type="submit">

    function(e) {
        if (event.detail.status > 299) {
            // submit may have failed

    function(e) {
        e.detail.forEach(function(badEl) {
            // do something w/ invalid element

Useful Links

The future of the web

By Ray Nicholus

The future of the web

Web Components, Object observers, mutation observers, and the polyfill that makes it all usable now

  • 2,222