<Web-Components>

Carlos Cañado

web components

HOW DO
YOU USE

bootstrap?

HOW DO
YOU USE

SEMANTIC UI?

HOW DO
YOU USE

fundation?

1. go to docs

2. COPY ALL THE THINGs

<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left" role="search">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

3. recive widget

we can do better

2. COPY ALL THE THINGs

<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left" role="search">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

2. use the thing


    <twbs-navbar>
      <a href="#">Home</a>
      <a href="#">About</a>
      <a href="#">Bacon</a>
    </twbs-navbar>

1. Create your own HTML element

2. Scope your styles

3. React with lifecycle callbacks

Not a new concept

Components for the web have been around for a long time, the idea of being able to write reusable and portable code is nothing new.

web components

web component

A web component is a standardised way of creating encapsulated, reusable user interface elements for the web.

  • Set of standards that allow us to bundle markup, styles and scripts into custom HTML elements
  • Slowly gaining support on browsers - but for now we need a polyfill (webcomponents.js)
  • Google as the main driving force
  • We have been using them but now we can also create our own

aspiration of any type of component

Extensibility

Composability

reusability

built on nothing more than web standards, this has some huge benefits

interoperability

lifespan

portability

Web Components Resources

Eric Bidelman

@ebidel

Meet the Web Components Family

based on a standart set of W3C Especification

Custom Elements

Shadow DOM

HTML Templates

HTML Imports

a bit of history

<div> soup

Custom Elements

the <div> soup story

Familiar with this kind of code?


<div class="abFed">
    <div class="gTef">
        <div class="ErkF">
            <div class="qcSx">
                <div class="iYrh">
                </div>
            </div>
        </div>
    </div>
</div>

Should not we expect more from the Web Platform?

the <div> soup story

with no soup anymore


<chat-app org="acme">
    <room-list show-lobby="true" />
    <message-list view="detailed">
        <message user="..." text="..." />
        <message user="..." text="..." />
        <message user="..." text="..." />
        <message user="..." text="..." />
    </message-list>
</chat-app>

Sounds better, no?

Custom Elements

Especification to use new types of DOM elements in a document and extend

There are already custom elements shipped with HTML5

<video> <figure> <article> <header> <aside> <nav> ...

one element, one feature / role / function

Custom Elements Allow

  1. Define new HTML elements.
  2. Bundle together custom functionality into a single tag.
  3. Extend other elements.
  4. Extend the API of other DOM elements.

CODE AHEAD!!

define our own tag

Do you think that will be created?

[ Tag name must have a dash ]

<!-- find a name to your element -->

<my-element></my-element>

apply a style

Is it right? is it solved?

[ pseudo-class :unresolved ]

<style>
    my-element { color: red; }
    :unresolved { border: 1px solid black; }
</style>

register own OUR element

Create with custom prototypes

[ Proto must inherit from HTMLElement ]

var proto = Object.create(
  HTMLElement.prototype
);
var MyEl = document.registerElement(
  'my-element', { prototype: proto }
);

Now we can be imperative

Using JavaScript

<my-element></my-element>             // OR
document.createElement('my-element'); // OR
new MyEl();

Extend existing native elements

This type of element is called a Type Extension Custom Element. It lets you extend native elements APIs with your own properties

document.registerElement('x-super-input', {
  extends: 'input',
  prototype: Object.create(
    HTMLInputElement.prototype, {
      // custom prototype properties
    })
});

hooks: reactive composability

Supported callback functions for custom elements are called lifecycle callbacks

var proto = Object.create(
  HTMLElement.prototype
);
proto.createdCallback = function () {
  this.innerHTML =
    (this.getAttribute('name') || '?');
}
document.registerElement(
  'my-header', {prototype: proto}
);

Custom Elements callbacks

  1. createdCallback() - Called every time a custom element is created.
  2. attachedCallback() - Called when the element is attached to the DOM.
  3. detachedCallback() - Called when the element is removed from the DOM.
  4. attributeChangedCallback() - Called whenever one of the elements' attributes changes.

Shadow DOM

Shadow DOM

  • Shadow DOM refers to the browser's ability to include a subtree of DOM elements into the rendering of a document.
  • This allows developers to encapsulate their HTML, styles and script into a single component.

Shadow DOM Example

In example, let's consider the audio tag


    <audio src="http://developer.mozilla.org/@api/deki/files/2926/=AudioTest_(1).ogg"
      autoplay="autoplay" controls="controls">
        Your browser does not support the <code>audio</code> element.
    </audio>

Inspecting the element with Shadow Dom activated from dev tools, we can see the HTML markup for all rendered elements, inside the audio's shadow root.

 

Shadow host

The node that contains all of our shadow DOM

Shadow Root

The first node in the shadow DOM

Shadow Boundary

The barrier that protects our shadow DOM

<audio>

#document-

fragement

<div>

<div>

CODE AHEAD!!

Building the shadow dom

[ createShadowRoot is deprecated but, new API hasn't been standardized and none of the browsers currently support it ]

<div id="host"></div>

<script>
  var host = document.querySelector('#host');
  var root = host.createShadowRoot();
//  host.attachShadow({mode: 'open'});
</script>

Encapsulation

Encapsulation semi-permeably blocks content access and style leakage

  var span = document.createElement('span');

  span.textContent = 'This is Shadow DOM';

  root.appendChild(span); 

Style encapsulation

Encapsulation of shadowed content access and style targeting can be breached if a developer explicitly chooses to do so

var span = host.querySelector('span');
// this query will return NULL

div span { color: red; }
/* this style will not be applied */

var span = host.querySelector('::shadow span');
// this query will return the shadowed span

<CONTENT> INSERTION

To show the shadow hosts' content in the presentation layer you have to add the <content> tag.
<content> will cherry pick all content from the shadow host and append it inside the shadow root.

<div class="widget">
  Hello, world!
  <p>This also gets rendered</p>
</div>  
<script>  
  var host = document.querySelector('.widget');
  var root = host.createShadowRoot();
  root.textContent += 'Im inside yr div!';
  root.textContent += '<content></content>';
</script> 

<CONTENT> SELECTORS

Specific content can be taged with the select attribute.

<h3>Last Name:
  <content select=".last-name"></content>
</h3>
<h3>First Name:
  <content select=".first-name"></content>
</h3>
<h3>
  <content select=""></content>
</h3>

<div class="widget">
  Hello World
  <span class="first-name">Rob</span>
  <span class="last-name">Dodson</span>
</div>

Applying styles

  • ::shadow pseudo element
  • /deep/ combinator, which was replaced with a >>> combinator (or shadow piercing descendant combinator)
  • ::content pseudo-element
  • :host pseudo-class and :host() functional pseudo-class
  • :host-context() functional pseudo-class

The editor's draft of CSS Scoping specification defines the selectors which are related to Shadow DOM. Specifically, it defines the following selectors related to Shadow DOM:

HTML Templates

TEMPLATES ARE INERT CHUNKS OF DOM THAT CAN BE REUSED

HTML Templates

Declare fragments

<template> allows to declare HTML fragments

  • parsed by browser
  • inert at load time, not rendered
  • only instantiated at runtime

which means

  • <script> won't be executed
  • <audio> won't  be played
  • no request to fetch <img> src

CODE AHEAD!!

Defining templates

Create your own, reusable templates using HTML markup

<template id="tmpl">
  <style>
    ...
  </style>
  <div>
    <h1>Web Components</h1>
    <img src="image.jpeg">
  </div>
</template>

Deep copy and using

Generate copies of your templates

var tmpl = document.querySelector('#tmpl');
var clone = tmpl.content.cloneNode(true);
document.body.appendChild(clone);

// var clone = document.importNode(
  tmpl.content, true
);

This example uses cloneNode() on the template's contents; it could equivalently have used document.importNode(), which does the same thing. The only difference between these two APIs is when the node document is updated: with cloneNode() it is updated when the nodes are appended with appendChild(), with document.importNode() it is updated when the nodes are cloned.

HTML Imports

IMPORTS LOAD
EXTERNAL DOCUMENTS INTO YOUR PAGE

Import HTML sub-documents

Fetches included scripts, styles, and templates

<head>
  <link rel="import" href="/path/import.html">
</head>

callbacks

Act on import documents when they arrive, or fail due to an error

<script async>
  function importLoad(event) { }
  function importError(event) { }
</script>

<link rel="import"
      href="file.html"
      onload="importLoad(event)"
      onerror="importError(event)" />

imported resources

Utilize the imported resources when they arrive by accessing the import document attached to the link element

<script async>
function importLoad(event) {
  var doc = event.target.import;
  var tmpl = doc.querySelector('#widget');
  // do something with assets
}
</script>

Access parent document

Access the importing parent document or the imported sub-document via script from within the import sub-document

<!-- assume this is inside imported doc -->
<script> 
  var doc =
    document.currentScript.ownerDocument;
  // hook to the imported sub-doc

  var mainDoc = doc;
  // the 'doc' variable is a reference
  // to the parent document that is
  // bringing in the import
</script>

Importing HTML documents

<head>
  <link rel="import" href="warnings.html">
</head>

<body>
  <script>
    var link = document.querySelector('link[rel="import"]');
    var content = link.import;

    // Grab DOM from warning.html's document.
    var el = content.querySelector('.warning');

    document.body.appendChild(el.cloneNode(true));
  </script>
</body>

Web Components Wrapping up

// component.html
<template id="template">
    <style>
        h1 { color: orange; }
    </style>
    <div>
        <h1>Web Components</h1>
        <img src="http://webcomponents.org/img/logo.png">
    </div>
</template>
<script>
    var template = document.getElementById("template");
</script>
<script src="js/component.js"></script>

An example with all the pieces together

// component.js
var myComponent = document.registerElement('my-component', {
    prototype: Object.create(HTMLElement.prototype, {
        createdCallback: {
            value: function() {
               var templateClone = template.content.cloneNode(true);
               var root = this.createShadowRoot()
               root.appendChild(templateClone);
            }
        }
    });
});
// index.html
...
    <link rel="import" href="component.html">
</head>
<body>
    <my-component>
        <h1>This is a Custom Element</h1>
    </my-component>
...

Native Status

Native browser support is landing, but we'll still need polyfills for the foreseeable future

Polyfills

Piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively. Flattening the API landscape if you will.

There is a list of polyfills ranging from SVG to Android, Canvas for IE (using Silverlight as a bridge) to support <video>, <audio>, etc.
HTML5 Cross browser Polyfills

webcomponents.js is a set of polyfills built on top of the Web Components specifications. It makes it possible for developers to use these standards today across all modern browsers.

Libraries

Polymer

X-Tag

Bosonic

SkateJS

Polymer is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern browsers.

X-Tag is a small JavaScript library, created and supported by Mozilla, that brings Web Components Custom Element capabilities to all modern browsers.

Bosonic is a set of tools that enable you to build Web Components as the spec currently describes, and supporting not-so-modern browsers like IE9.

SkateJS is a superset of the web component specs, with a very small footprint, that enables you to write performant web components using a functional rendering pipeline.

References

Challenge 1: Meme Tag

Description: Build a tag that displays top and bottom text over a meme picture

Requirements:

  • The image and top/bottom text should be dynamically configurable via attributes

Extra Credit:

  • Leverage a meme API to allow for grabbing meme pics on-demand

Challenge 2: Photo Stack

Description: Build a tag that arranges image elements in an organically uneven stack appearance

Requirements:

  • Enable cycling through the stack on click and touch with an animated transition
  • Handle new image elements being added dynamically

Extra Credit:

  • Allow the order of the photo stacked images to be reversed using a boolean attribute

Challenge 3: Comment Feed

Description: Create a comment feed element that supports custom child elements for comments/replies

Requirements:

  • Use custom elements for the main feed element, and the comment/reply elements it contains
  • Store the page's comment data so it repopulates the feed on refresh
  • Support common actions used in comments/replies: edit, delete, up-vote.

Extra Credit:

  • Sync your comment data to a remote source that works regardless of the containing page's domain

Copy of Web Components

By Michael PAMBO OGNANA

Copy of Web Components

  • 420