Loading deck

Skating with Web Components

Trey Shugart

DogeScripter, Atlassian



What are web components?

Web Components are a collection of standards that allow the building, and use of, reusable components made with HTML, CSS and JavaScript.

  • Templates
  • Shadow DOM
  • HTML Imports
  • Custom Elements

What are web components?

  • Chrome OS keyboard
  • Chrome OS media player
  • GitHub's <time is="relative-time"> element

What are Web Components?

<div> soup anyone?

What are Web Components?

Let's try that again.
    name="Frank Zappa"
    last-message="Frank: Freak Out!"


  • Google
  • Implemented through polyfills
  • Expands on it to provide data-binding and template expressions
  • Support is mostly usable in IE10, Safari 6 and Safari Mobile
  • Not small, 223k min (Platform + Polymer)
  • Not production ready
 * As of the 25th of June 


  • Mozilla
  • Custom Elements through a proprietary API
  • Adds convenience
  • Nothing polyfilled by default
  • IE9+
  • 31.8k min



  • Me
  • Loosely follows the custom element spec
  • Simple ShadowDOM-style templating
  • Custom Element and HTML Imports polyfill in development
  • Binds components using classes, attributes and tags
  • 6.7k min
  • Already in production!

Skating Classes

You've got some tabs

<ul class="tabs">
  <li><a href="#tab1">Tab 1</a></li>
  <li><a href="#tab2">Tab 2</a></li>

But they only work on DOMReady

jQuery(function ($) {

Just wrap it with Skate!

skate('tabs', {
  type: skate.types.CLASS,
  ready: function (element) {

skating attributes

Input or textarea needs to clear when ESC is pressed

<input type="text" data-clear-on-esc>

// or

<textarea data-clear-on-esc></textarea>

Create an attribute component!

skate('data-clear-on-esc', {
  type: skate.types.ATTR,
  events: {
    keyup: function (element, e) {
      if (e.keyCode === 27) {
        element.value = '';

Skating Elements

You want an auto-complete element

<auto-complete url="some/service.json"></auto-complete>

Add a tag binding

var AutoComplete = skate('auto-complete', {
  type: skate.types.TAG,
  events: {
    'keyup input[type="text"]': function (element, e) {
  template: '<input type="text">'

Element constructors!!

var autoComplete = new AutoComplete();
autoComplete.setAttribute('url', 'some/service.json');

What You Get

Class, attribute and tag bindings

skate('my-component', {
  // binds to classes, attributes and tags by default
  type: skate.types.ANY
  • ANY - class, attr or tag
  • TAG
  • ATTR
  • NOTAG - class or attr
  • NOATTR - class or tag
  • NOCLASS - attr or tag

What You Get

Congruent API


// Component does not support custom elements.
var MyComponent = skate('my-component', {
  type: skate.types.NOTAG

// Will throw an exception!
var myComponent = new MyComponent();

What You Get

Lifecycle callbacks

skate('my-component', {
  ready: calledBeforeVisible,
  insert: calledAfterVisible,
  remove: calledAfterRemoval
* ready(), if specified, prevents element from showing until done

Async ready()

ready: function asyncReady (element, done) {
* Specifying "done" makes callback async

What You Get

Prototype properties / methods

skate('my-component', {
  prototype: {
    someMethod: function () {
      // "this" refers to the element

Somewhere else...


What You Get

Awesome attribute API

skate('my-component' {
  attributes: function handleAnyAttributeChange (element, change) {
    // type: 'insert, update or remove',
    // name: 'attribute-name',
    // newValue: 'new attribute value, undefined if just removed',
    // oldValue: 'old attribute value, undefined if just inserted'


attributes: {
  'attribute-name': handleInsertAndUpdate

or even

attributes: {
  'attribute-name': {
    insert: handleInsert,
    update: handleUpdate,
    remove: handleRemove

What You Get


skate('my-component', {
  events: {
    click: function handleClick (element, e) {

Event delegation, Backbone style!

events: {
  'click .delegate[selector]': function handleDelegateClick (element, e) {
    // use `e.target` to get the delegate

What you get

ShadowDOM-style templating by default

skate('my-component', {
  template: '<article>' +
    '<h2><content select=".heading"></content></h2>' +
    '<section><content></content></section>' +

HTML before

  <span class="heading">My Heading</span>
  <p>First paragraph.</p>
  <p>Second paragraph.</p>

HTML after

    <h2><span class="heading">My Heading</span></h2>
      <p>First paragraph.</p>
      <p>Second paragraph.</p>

What You Get

Custom templating

skate('data-handlebars', {
  template: function (element) {
    var template = Handlebars.compile(element.innerHTML);
    element.innerHTML = template({
        title: 'Handlebars',
        body: 'However, you can use anything you want: React, Mustache, Jade, etc.'

HTML before

<div data-handlebars>
  <h1>{{ title }}</h1>
  <p>{{ body }} </p>

HTML after

<div data-handlebars>
  <p>However, you can use anything you want: React, Mustache, Jade, etc.</p>