The Future of the Web ...and the one polyfill that makes it all possible today
Jul 15, 2015
Browser Support
WeakMap:Chrome,FF,IE11
Object.observe:Chrome36
MutationObserver:allbutIE10,Safari6.1,Android4.3
WebComponents:Chrome36,FF32,Android4.4
Use Cases
Associatedatawithanelementw/outaugmentingtheelement
Associatedatawitharead-onlyobject
Moreefficientinformationhiding
e.g.
varmap=newWeakMap();
varsomeEl=document.getElementById('someEl');
map.set(someEl,{foo:'bar'});
if(map.has(document.getElementById('someEl'){map.get(someEl).foo;//bar}
Object.observe
Receivecallbackswhenanobjectchangesinanyway
NativeimplforAngular'sscope.$watch
ForArrays:Array.observe
Angularwilldelegatein2.0
Angular
scope.name='Ray';
scope.$watch('name',function(newV,oldV){console.log('oldname:'+oldV);console.log('newname:'+newV);});
Native
scope.name="Ray";
Object.observe(scope,function(change){if(change.name==='name'){console.log('oldname:'+change.oldValue);
console.log('newvalue:'+change.object[change.name]);}});
MutationObserver
Receivecallbackswhenanelementchangesinanyway
Elementdescendendantscanalsobeobserved
ReplacementforinefficientMutationEvents
e.g.varcallback=function(records){varrecord=records[0];//fordemosimplicityonlyvaradded=record.addedNodes;
if(added.length){varnewTags=0;for(vari=0;i<added.length;i++){if(added[i].className.indexOf('tag')>=0){newTags++;}}
if(newTags){alert(newTags+"newtagsadded.");}}};
varobserver=newMutationObserver(callback);observer.observe(tagsContainerEl,{childList:true});
Templates
Create re-usable content
<template> is not rendered, must be
Any elements can be children
"activated"
<template><div>hithere</div><div>youcan'tseemerightnow</div><blink>luckilyforyou</blink></template>
Live example [jsbin]
HTML Imports
PullanotherHTMLfileintothecurrentdocument
Injectapackagedcomponent(andalldeps)w/oneline
Re-usetemplatesstoredinacentrallocation
<linkrel="import"href="/license.html">
Using an imported document
//Grabthe<link>thatimportsthelicensingblurbvarlicensingLink=document.getElementById('licenseLink');
//Grabtherelevantcontentfromtheimporteddoc
varcontent=licensingLink.import.getElementById('license');
//Appendthecontenttoourdocdocument.body.appendChild(content);
NOTE:ServermustreturnproperCORSheadersforcross-domainimports
Completeexample[jsbin]
Custom Elements
MUST contain a dashTake heed angular directive writers.
Use ember? You're cool.
Why?To avoid conflict w/ future standardized elements.
<my-custom-element></my-custom-element>
Creating Custom Elements
Initiallyan:unresolvedHTMLElement
To"resolve",youmustdocument.registerElement
Twotypes:1. New*CE2. TypeExtensionCE
*Ijustmadeupthisname
Standard Custom Element
<foo-bar><!--unresolvedcontent--></foo-bar>
<script>
</script>
Liveexample[jsbin]
Type Extension CustomElement
<videois="frame-grabber"src="somevideo.mp4">
</video>
varframeGrabber=document.createElement('video','frame-grabber');
frameGrabber.prototype.grab=function(){//grabcurrentframe&dosomethingw/it}
Shadow DOM
Allowscreationofself-contained,sandboxedwebcomponents
AsingleNodecannowbemadeupof3differentsubtrees:
LightDOMShadowDOMComposedDOM
Light DOM Tree
Partofthe"logicalDOM"
Contentofthecustomelementprovidedbyintegrator
<blink-is-back>Bringbacktheblinktag!</blink-is-back>
Displayedpre-shadow-rootrender
Shadow DOM Tree
Partofthe"logicalDOM"Internaltothecustomelement,notachild
NotdirectlyaccessibleviathelightDOM
1. Includeelementonpage2. Register(ifCE)3. myElement.createShadowRoot();4. Appendcontenttoshadowroot5. Liveexample[jsbin]
Composed DOM Tree
Contentthatisactuallyrendered
PiecesofthelightandshadowDOMcombined
ComposedDOMfrom CE:the<blink-is-back>
<blink-is-back><divstyle="text-decoration:line-through;">Bringbacktheblinkelement!</div><div>Butseriously,don'tmaketextblink.</div></blink-is-back>
Polymer
Shimforallspecsdiscussedinthispresentation
Deferstonativeimpls,whenpresent
So,Youcanuseallofthesecoolspecsnow!
The first devolving framework
LessimportantasWebComponentsetal.coverageincreases
Shoulddisappearwhenthesespecsareimplementedeverywhere
A polyfill for Shadow DOM? How?
It'scomplicated
Everythingiswrapped
Requiredto:maintainencapsulationmaintainseparationbetweenlight&shadowDOMelementsretargeteventsoriginallydestinedfortheshadowDOMtree
file-input
WebComponentbuiltusingPolymer
Allows<inputtype='file'>tobeeasilystyled
Built-infilevalidation
Moreintuitiveaccessto(valid)files
e.g.
<file-inputclass="btnbtn-primary"extensions='["jpeg","jpg"]'minSize="500000"maxSize="3000000">
<spanclass="glyphiconglyphicon-file"></span>
Selectafile
</file-input>
ajax-form
WebComponentbuiltusingPolymer
Submitaformwithoutapagereload
Sendcustomheadersw/formsubmit
Easyaccesstoserverresponse
Dirtsimplevalidationsupport/control
Submit<file-input>elementstoo!
e.g.<formis="ajax-form"method="POST"action="form/handler"headers='{"X-Cust-Header":"FooBar"}'>
<inputtype="text"name="fullname"required>
<inputtype="submit">
</form>
form.addEventListener('submitted',function(e){if(event.detail.status>299){//submitmayhavefailed}});
form.addEventListener('invalid',function(e){e.detail.forEach(function(badEl){//dosomethingw/invalidelement});});