introduction to web components
DESCRIPTION
A short introduction to web components. The talk covers the basic standard specified by W3c like HTML imports, templates, shadow DOM and custom elements. Further a short overview of polyme, x-tags/Brick is given and shows how these bring together native browser implementation, polyfills and framework code to leverage web components technology today.TRANSCRIPT
WEBCOMPONENTS@marcbaechinger
‚web development is overly complex…‘unknown, but desperate software engineer
lack of encapsulation and abstraction
TODAYS STANDARDS BODY
STANDARDS BODY
W3C webcomponents
STANDARDS BODY
W3C webcomponents
heavily in flux
STANDARDS BODY
W3C webcomponents
webcomponents polyfill
heavily in flux
STANDARDS BODY
W3C webcomponents
webcomponents polyfill
heavily in flux
2013: same for x-tags and polymer
STANDARDS BODY
W3C webcomponents
webcomponents polyfill
x-tags polymer
brick polymer elements
heavily in flux
2013: same for x-tags and polymer
STANDARDS BODY
W3C webcomponents
webcomponents polyfill
x-tags polymer
brick polymer elements
heavily in flux
2013: same for x-tags and polymer
wrapper API (JS/HTML)
STANDARDS BODY
W3C webcomponents
webcomponents polyfill
x-tags polymer
brick polymer elements
heavily in flux
2013: same for x-tags and polymer
wrapper API (JS/HTML)element sets (accordion, …)
http://www.w3.org/TR/components-intro/
Templates
Custom elements
Shadow DOM
Imports
June 2013
BROWSER SUPPORTpolymer
BROWSER SUPPORT
x-tags
polymer
HTML IMPORTS
imports.html
<link href="../styles/import.css" rel="stylesheet"/> <section id="root"> <h1>Caption of import</h1> <p>imported text<p> </section> <script> (function (global) { global.markup = { hi: function () { console.log("hi from a fun declared in an import"); } }; }(this)); </script>
HTML IMPORTS
<link id="markup" rel="import" href="imports.html">
import html fragment
var link = __.e("#markup"); var markup = link.import; var fragment = markup.querySelector("#root");
access import
HTML IMPORTS
<link id="markup" rel="import" href="imports.html">
import html fragment
var link = __.e("#markup"); var markup = link.import; var fragment = markup.querySelector("#root");
access import
HTML IMPORTS
<link id="markup" rel="import" href="imports.html">
import html fragment
usually cloned before use
HTML IMPORTS
HTML IMPORTS
check for import property to feature test
SCRIPTS IN IMPORTS// in the import fragment <script> (function (global) { global.markup = { hi: function () {} }; }(window)); </script>
// in the parent document window.markup.hi();
SCRIPTS IN IMPORTS// in the import fragment <script> (function (global) { global.markup = { hi: function () {} }; }(window)); </script>
// in the parent document window.markup.hi();
executed once when imported
SCRIPTS IN IMPORTS// in the import fragment <script> (function (global) { global.markup = { hi: function () {} }; }(window)); </script>
// in the parent document window.markup.hi();
parent global context
executed once when imported
NO PARENT DOCUMENT!
<script> var importDoc = document.currentScript.ownerDocument; var parentDocument = document; </script>
part of the imports.html
NO PARENT DOCUMENT!
<script> var importDoc = document.currentScript.ownerDocument; var parentDocument = document; </script>
part of the imports.html
so scripts behave the same as in parent doc
TEMPLATES
TEMPLATE - LAZY MARKUP
<template id="template"> <h1>Diego Maradona</h1> <img src="maradona.jpg"/> <script> console.log("exec template script"); </script> </template>
TEMPLATE - LAZY MARKUP
<template id="template"> <h1>Diego Maradona</h1> <img src="maradona.jpg"/> <script> console.log("exec template script"); </script> </template>
lazy loaded
TEMPLATE - LAZY MARKUP
<template id="template"> <h1>Diego Maradona</h1> <img src="maradona.jpg"/> <script> console.log("exec template script"); </script> </template>
executed each time when applied
lazy loaded
FEATURE TEST
function supportsTemplate() { var el = document.createElement('template'); return !!('content' in el); }
read-only DocumentFragment
INSERTING A TEMPLATE
var tmpl = __.e("#template"), target = __.e("#target"); target.appendChild( document.importNode(tmpl.content, true) );
IMPORTED TEMPLATES
// select the import root from the ‚link‘ elem var importLink = __.e("#import-1").import; // select the template within the import var tmpl = __.e("template", importLink);
__.e("#target").appendChild( document.importNode(tmpl.content, true) );
SHADOW DOM
!Denn die einen sind im Dunkeln Und die andern sind im LichtUnd man siehet die im Lichte Die im Dunkeln sieht man nicht !aus Mackie Messer von Berthold Brecht
RENDER TREE
t e
RENDER TREE
t e
shadow = target.createShadowRoot()
RENDER TREE
t e
shadow = target.createShadowRoot()
RENDER TREE
t e
shadow = target.createShadowRoot()
sshadow root
RENDER TREE
t e
shadow = target.createShadowRoot() shadow.appendChild(element)
sshadow root
RENDER TREE
t e
shadow = target.createShadowRoot()
<content/>
shadow.appendChild(element)
sshadow root
HTML IMPORTS
HTML IMPORTS
initial child node
HTML IMPORTS
initial child node
shadow DOM from template
HTML IMPORTS
initial child node
shadow DOM from template
insertion point of initial content
SHADOW DOM TEMPLATES
function renderShadow(tmplId, targetSelector) { var tmpl = __.e("#" + tmplId), target = __.e(targetSelector), shadow = target.createShadowRoot(); target.style.display = "block"; shadow.appendChild( tmpl.content.cloneNode(true) ); }
SHADOW DOM TEMPLATES
function renderShadow(tmplId, targetSelector) { var tmpl = __.e("#" + tmplId), target = __.e(targetSelector), shadow = target.createShadowRoot(); target.style.display = "block"; shadow.appendChild( tmpl.content.cloneNode(true) ); }
visually removes all previous children
SHADOW DOM TEMPLATES<div id="name-shadow-hook" class="hook"> <span class="email">[email protected]</span> <span class="address">Webergasse 23, 8408 Winterthur</span> <span class="name">Hans Meier</span> <img src="../images/alaska.jpg" width="480"/> </div>
<template id="person-template"> <section> <h3><content select=".name"/></h3> <p><b>Address</b> <content select=".address"/></p> <p><b>E-Mail</b> <content select=".email"/></p> <div><content select=„img"/></div> </section></template>
SHADOW DOM TEMPLATES<div id="name-shadow-hook" class="hook"> <span class="email">[email protected]</span> <span class="address">Webergasse 23, 8408 Winterthur</span> <span class="name">Hans Meier</span> <img src="../images/alaska.jpg" width="480"/> </div>
<template id="person-template"> <section> <h3><content select=".name"/></h3> <p><b>Address</b> <content select=".address"/></p> <p><b>E-Mail</b> <content select=".email"/></p> <div><content select=„img"/></div> </section></template>
change initial DOM to change shadow dom
SHADOW DOM TEMPLATES
<template id=„person-template"> <article id="master"> <header><content select=".header"/></header> <div><content select=".content"/></div> <footer><content select=".footer"/></footer> </article></template>
CUSTOM ELEMENTS
<woot/>
CUSTOM ELEMENTS<polymer-ui-accordion selected="1" id="accordion"> <polymer-ui-collapsible id="abstraction"> <div class="polymer-ui-collapsible-header">Abstraction and encapsulation</div> <div>…</div> </polymer-ui-collapsible> <polymer-ui-collapsible id="abstraction"> <div class="polymer-ui-collapsible-header">Abstraction and encapsulation</div> <div>…</div> </polymer-ui-collapsible> </polymer-ui-accordion>
CUSTOM ELEMENTS
CUSTOM ELEMENTSinvisible to querySelector and CSS rules
CUSTOM ELEMENTSinvisible to querySelector and CSS rules
use elements and attributes of DOM as API to interact with the
shadow DOM component: !
acc.setAttribute("selected", 1);
CUSTOM ELEMENTS
function (name, spec, callbacks) { var proto = Object.create(HTMLDivElement.prototype); // […] check for callbacks return document.registerElement(name, { prototype: Object.create(proto, spec || {}) });}
CUSTOM ELEMENTS
function (name, spec, callbacks) { var proto = Object.create(HTMLDivElement.prototype); // […] check for callbacks return document.registerElement(name, { prototype: Object.create(proto, spec || {}) });}
returns a constructor
CUSTOM ELEMENTS
function (name, spec, callbacks) { var proto = Object.create(HTMLDivElement.prototype); // […] check for callbacks return document.registerElement(name, { prototype: Object.create(proto, spec || {}) });}
returns a constructor
the prototype of the constructor
CALLBACKS
proto.createdCallback = function () {} proto.attachedCallback = function () {} proto.detachedCallback = function () {}
proto.attributeChangedCallback = f(name,oldV,newV) {}
CALLBACKS
proto.createdCallback = function () {} proto.attachedCallback = function () {} proto.detachedCallback = function () {}
proto.attributeChangedCallback = f(name,oldV,newV) {}
this is the DOM element
CUSTOM ELEMENTS
register( 'x-label', {}, { createdCallback: function() {}, attachedCallback: function() {} } );
WEBCOMPONENTS RECAP
polyfills to use it today
infrastructure for abstraction and encapsulation
infrastructure to build frameworks on top of it
heavily pushed by Google
future in the dust
RECAP
BRICK AND POLYMER
POLYMER
POLYMER
polyfill
POLYMER
polyfill
polymer framework (eg. databinding)
POLYMER
polyfill
polymer framework (eg. databinding)
polymer elements
POLYMER
polyfill
polymer framework (eg. databinding)
polymer elementspolymer elements
X-TAGS
X-TAGS API (IMPERATIVE)
MOZILLA.GITHUB.IO/BRICK/
MOZILLA.GITHUB.IO/BRICK/
available elements
styles and scripts of Brick
THX, GUYS!
RESOURCES
GENERAL
https://html5-demos.appspot.com/static/webcomponents/index.html !
www.html5rocks.com/en/tutorials/webcomponents/customelements/ !!
https://developer.mozilla.org/en-US/Apps/Tools_and_frameworks/x-tags
HTML IMPORTShttp://w3c.github.io/webcomponents/spec/imports/http://www.w3.org/TR/2013/WD-html-imports-20130514/http://www.w3.org/TR/2014/WD-html-imports-20140311/
http://www.html5rocks.com/en/tutorials/webcomponents/imports/ http://www.polymer-project.org/platform/html-imports.html
https://bugzilla.mozilla.org/show_bug.cgi?id=877072http://www.x-tags.org/blog
TEMPLATES
http://www.w3.org/TR/components-intro/#template-section
https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html
http://www.html5rocks.com/en/tutorials/webcomponents/template/