about:me

Addy Osmani

Senior Developer Relations Engineer,

 

"Learning JavaScript Design Patterns"

"Developing Backbone.js Applications"

Let's go back in time...

Get A T-Shirt!

Elements are the building blocks of the web

Elements are encapsulated

<select>
  <option>Small</option>
  <option>Medium</option>
  <option>Large</option>
</select>

Elements are configurable

<select id="schwag">
  ...
  <option disabled>Medium</option>
  <option disabled>Large</option>
  <option selected>XX-large</option>
</select>

<select size="4" multiple>
  <option>Do</option>
  <option>Re</option>
  <option>Mi</option>
  ...
</select>

Elements are composable

<select>
  <optgroup label="German Cars">
    <option>Mercedes</option>
    <option>Audi</option>
  </optgroup>
  ...
</select>

<form>
  <select name="size">
    <option value="s">Small</option>
    <option value="m">Medium</option>
    <option value="l">Large</option>
  </select>
</form>

Elements are programmable

var foo = mySelect.selectedIndex;

Good design doesn't date.

So what happened?

Tabs: a common component on the web

Building a tab component today

Pile on the JavaScript

Our markup is terrible

Seriously?

Design isn't just how it looks. It's how it works.

<x-tabs>
  <x-tab>Tab 1</x-tab>
  <x-tab>Tab 2</x-tab>
  <x-tab>Tab 3</x-tab>
</x-tabs>

Web Components are a set of emerging standards that allow developers to extend HTML.

Templates

Custom Elements

Shadow DOM

HTML Imports

Examples

Native Web Components

What we're used to using

<link rel="stylesheet" type="text/css" href="my-widget.css" />
<script src="my-widget.js"></script>
<div data-my-widget />
$(function() {
  $('[data-my-widget]').myWidget();
});
div.innerHTML = '<div data-my-widget />'
$(div).find('[data-my-widget]').myWidget();

Using a Custom Element

<link rel="import" href="my-widget.html" />

<my-widget></my-widget>

Creating a Custom Element

// JS
var MyElement = document.registerElement('my-element');
// or document.createElement(..)

// HTML
<my-element></my-element>
  

Extending a Custom Element

// JS
var MegaButton = document.registerElement('mega-button', {
  prototype: Object.create(HTMLButtonElement.prototype)
});

// HTML
<button is="mega-button">

Callbacks for Custom Elements

document.registerElement('my-element', {
  prototype: Object.create(HTMLElement.prototype, {

    // createdCallback, attachedCallback, detachedCallback
    attributeChangedCallback: {
      value: function(attr, oldVal, newVal) {
        this.innerHTML = 'ATTRIBUTE CHANGED!';
      }
    }

  })
});

Styling a Custom Element

<style>
  x-foo {
    display: block;
  }
  x-foo > [is="x-bar"] {
    opacity: 0;
  }
</style>

<x-foo>
    <div is="x-bar"></div>
</x-foo>

<style>
  x-foo {
    opacity: 1;
    transition: opacity 300ms;
  }
  x-foo:unresolved {
    opacity: 0;
  }
</style>

shadow = this.createShadowRoot();
shadow.innerHTML =
  "<style>span { color: green; }</style>" 
  + "<span>I'm green</span>";

Cross-browser support improving but not there yet

Polymer is a library that uses the latest web technologies to let you create custom HTML elements.

Layers of Polymer

Elements

Reusable custom elements (in progress)

Polymer

An opinionated way to work with Web Components

Platform

Web Components polyfills for all
modern browsers

Native

The current browser landscape

Three ways to work with Polymer

Using elements

Creating elements

Utilizing the modern web platform

Using

polymer-project.org/docs/elements/

Everything is an element

Polymer UI elements

visual elements

<polymer-ui-accordion> demo

<polymer-ui-animated-pages>

<polymer-ui-card> demo

<polymer-ui-sidebar-menu> demo

<polymer-ui-tabs> demo

<polymer-ui-toggle-button> demo

<polymer-ui-theme-aware>

...

Reusability...the non-visual polymer-elements are used to implement these!

Everything is an element

Collapsible elements

<script src="platform.js"></script>
<link rel="import" href="polymer-ui-collapsible.html">
<polymer-ui-collapsible>
  <h3 class="polymer-ui-collapsible-header">Click Me!</h3>
  <div>
    some content...
  </div>
</polymer-ui-collapsible>

Click Me!

Realm of the galaxies at the edge of forever, made in the interiors of collapsing stars dispassionate extraterrestrial observer, rings of Uranus extraplanetary rich in heavy atoms shores of the cosmic ocean, white dwarf finite but unbounded!

Realm of the galaxies at the edge of forever, made in the interiors of collapsing stars dispassionate extraterrestrial observer, rings of Uranus extraplanetary rich in heavy atoms shores of the cosmic ocean, white dwarf finite but unbounded!

Polymer elements

non-visual utility elements

Layout

<polymer-layout>

<polymer-flex-layout>

<polymer-grid-layout>

View

<polymer-media-query>

<polymer-page>

Services / libs

<polymer-shared-lib>

<polymer-google-jsapi>

Data

<polymer-localstorage>

<polymer-xhr>

<polymer-jsonp>

<polymer-file>

<polymer-meta>

Behavior / interaction

<polymer-signals>

<polymer-selector>

Everything is an element

flexbox...using DOM

<script src="platform.js"></script>
<link rel="import" href="polymer-flex-layout.html">
<polymer-flex-layout vertical iscontainer>
  <div>Header</div>
  <div flex>Body</div>
  <div>Footer</div>
</polymer-flex-layout>
Header
Body
Footer

Everything is an element

AJAX...using DOM

<script src="platform.js"></script>
<link rel="import" href="polymer-ajax.html">
<polymer-ajax url="http://gdata.youtube.com/feeds/api/videos/"
              params='{"q":"chrome", "alt":"json"}'>
</polymer-ajax>
var ajax = document.querySelector('polymer-ajax');
ajax.addEventListener('polymer-response', function(e) {
  console.log(JSON.parse(this.response).feed.entry);
});
ajax.go();
Hit run...

Everything is an element

responsive design...using DOM (Bonus)

<script src="platform.js"></script>
<link rel="import" href="polymer-media-query.html">
<polymer-element name="responsive-layout" attributes="responsive">
  <template>
    <polymer-media-query query="max-width:640px" queryMatches="{{isPhone}}"></...
    <template if="{{isPhone && responsive}}"> <!-- Phone markup -->
      <content></content>
    </template>
    <template if="{{!responsive}}"> <!-- Non-responsive case -->
     ...
    </template>
  </template>
  <script>Polymer('responsive-layout', {responsive: false});</script>
</polymer-element>
<responsive-layout responsive>
  <div>...</div>
</responsive-layout>

Creating

polymer-project.org/polymer.html

Declarative element registration

Custom elements without Polymer :(

<template id="template">
  <style>input { color: orange; }</style>
  <input type="text">
</template>

<script>
var proto = Object.create(HTMLElement.prototype, {
  createdCallback: {
    value: function() {
      var t = document.querySelector('#template');
      this.createShadowRoot().appendChild(t.content.cloneNode(true));
    }
  }
});

var MyInput = document.registerElement('my-input', {prototype: proto});
</script>

Declarative registration with it

<link rel="import" href="polymer.html">
<polymer-element name="my-element" noscript>
  <template>
    <style>h2 { color: orange; }</style>
    <h2>Hello from my-element!</h2>
  </template>
</polymer-element>
<my-element></my-element>

Declarative registration

<link rel="import" href="polymer.html">
<polymer-element name="hello-element">
  <template>
    <h2>I can say hello</h2>
  </template>
  <script>
  Polymer({
    sayHello: function() { alert('Howdy folks!'); }
  });
  </script>
</polymer-element>

Binding expressions

Binding Expressions

<polymer-element name="owner-element">
  <template>
    <h2>{{owner}} built me with Polymer</h2>
  </template>
  <script>
  Polymer({
    owner: 'Addy'
  });
  </script>
</polymer-element>
<owner-element></owner-element>

Published properties

Published properties (related)

<polymer-element name="owner-element" attributes="owner">
  <template>
    <h2>{{owner}} built me with Polymer</h2>
  </template>
  <script>
  Polymer({
    owner: 'Addy'
  });
  </script>
</polymer-element>
<owner-element owner="Alex"></owner-element>

Declarative event handlers

Declarative Event Handlers

<polymer-element name="click-element">
  <template>
    <button on-click="{{setMessage}}">Click me</button>
    <span>{{message}}</span>
  </template>
  <script>
  Polymer({
    message: 'Waiting to be clicked...'
    setMessage: function() { this.message = 'I was clicked!' }
  });
  </script>
</polymer-element>

Automatic node finding

Automatic Node Finding

<polymer-element name="focus-element">
  <template>
    <button on-click="{{setFocus}}">Set Focus</button>
    <input id="nameInput" type="text">
  </template>
  <script>
  Polymer({
    setFocus: function() { this.$.nameInput.focus(); }
  });
  </script>
</polymer-element>

Accessibility isn't forgotten

Accessibility Checklist

  • Do all elements have meaningful text alternatives?
  • Can all functions be reached via the keyboard without using a mouse?
  • Do you have sensible focus order and focus target for each element?
  • Are your custom elements marked up to be accessible?
  • Can users understand everything without relying on color?
  • Is the moving or flashing content in your elements stoppable and safe?

ARIA roles with Polymer (Demo)

<polymer-element name="polymer-ui-ratings" 
                 attributes="count value autofocus">
  <template>
    <span id="container" tabindex="0" 
            on-keydown="{{keydownAction}}" role="slider">
      <template repeat="{{star in stars}}">
        <span id="star" index="{{star.index}}" 
          class="{{star.starClass}}" on-tap="{{updateValue}}">
          </span>
      </template>
    </span>
  </template>
  <script>
  .....
  

The

polymer-project.org/docs/start/platform

The platform is a layer of polyfills that adds support for emerging standards, like Web Components, to all modern browsers.

Platform polyfills

supporting new web technologies today

Templates

HTML Imports

Custom Elements

Shadow DOM

Additional features include Mutation Observers, Pointer Events, Web Animations, and much more.

As browsers implement the specifications supported by the platform, the need for this
layer decreases.

...till eventually it's all gone.

Polymer Tooling

Helping you stay more productive

Hopefully you're excited.

Let's componentize the web.

Build elements. Your friends are gonna be like..

<thank-you>