Outline

  • MVC vs. Component-based Design
  • Fundamentals of Web Components
  • Introduction to Polymer
  • [Case Study: Glideroom]

About Me

  • Started coding in high school (Turbo Pascal 6.0)
  • Professional developer since 2008
  • 2008-2010: Java / Spring
  • 2010-2013: Ruby / Rails
  • 2013-????: Node / CoffeeScript
  • Joined Panda Strike in 2014

How did we get here?

‘Where shall I begin, please, your Majesty’? ‘Begin at the beginning’, the King said gravely, ‘and go on till you come to the end: then stop.’
Lewis Caroll, Alice’s Adventures in Wonderland

1993: CGI

"Dynamic" web sites are basically Perl scripts

No, not THIS kind of CGI

1995: PHP and JavaScript are released

Wild, Wild West in Frontend-Land

2006: jQuery brings some sanity

A new Sheriff in Town

2010: MVC frameworks hit the scene

Why MVC?

  • A way to structure code
  • Set of Best Practices
  • No more "where does this code go?"
  • Common denominator

Why MVC in the browser?

  • Basically: Rails was ultra-successful
  • Rails = MVC
  • Rails = GOOD
  • Therefore, MVC = GOOD?

"What's good for the server is good for the browser"

What's good for the server is good for the browser?

  • "What's good for the browser is good for the server"
  •   => Node.js
  • But does the reverse hold true?
  • Not necessarily

Problems with MVC in the browser

  • In Rails, every request is handled by exactly ONE controller
  • On the frontend, pages are divided into several controllers
  • Controller hierarchies => entangled code
  • "Dumb" elements => everything is still a div

What if there was a different way?

  • HTML already has "smart" elements
  • Dropdowns
  • Checkboxes
  • Radio buttons
  • All of these provide:
    • User Interface
    • Interactivity
    • Configurability (type, size, etc.)

    What if we could write our OWN elements?

Enter Web Components

What are Web Components?

  • A set of specs designed to enhance HTML
  • Enables developers to build custom elements
  • Provides proper encapsulation
  • Currently "in progress" at the W3C

Core Technologies

  • Custom Elements
  • Shadow DOM
  • HTML Imports

Custom Elements

  • Make your own HTML tags!
  • Allows developers to register new elements with the parser
  • Optional second argument specifies prototype
  • // custom element names MUST include a hyphen (-)
    var MyAwesomeTag = document.registerElement("my-awesome-tag");
    // add it to the DOM
    document.body.appendChild(new MyAwesomeTag());
    

Result

Shadow DOM

  • Basically a "mini-DOM" for custom elements
  • Can be attached to ANY element
  • Provides separation and encapsulation
  • All element IDs, stylesheets, and JavaScript is scoped within
  • No more leaking style classes
// Attach a Shadow DOM to <my-awesome-tag>
var element = document.querySelector('my-awesome-tag');
var shadowRoot = element.createShadowRoot();

HTML Imports

  • Import another HTML document into your HTML document (yo dawg...)
  • A way to load your custom elements
  • <!-- imports my-awesome-tag.html into the DOM -->
    <link rel="import" href="my-awesome-tag.html">
    
    <script type="text/javascript">
      // contents of the import can be accessed like this
      document.querySelector('link[rel="import"]').import;
    </script>
    

Introducing Polymer

What is Polymer?

Mainly: a framework to simplify the creation of custom elements

  • Declarative element creation (No more document.registerElement)
  • Declarative event mapping
  • Declarative layout using attributes

But wait, there's more!

  • Polyfills for old browsers
  • Component library
  • UI designer

Anatomy of a Custom Element

  • Polymer uses custom elements to define custom elements
  • <template> defines the contents of the Shadow DOM
  • noscript attribute lets us define elements without JavaScript
<!-- import Polymer -->
<link rel="import" href="polymer/polymer.html">
<!-- define custom element -->
<polymer-element name="my-element" noscript>
  <template>
    <h2>Hi, I'm a custom element!</h2>
  </template>
</polymer-element>

Let's use it!

<head>
  <!-- load webcomponents polyfills -->
  <script src="webcomponents/webcomponents.js"></script>
  <!-- import custom elements -->
  <link rel="import" href="polymer/polymer.html">
  <link rel="import" href="my-element.html">
</head>

<body>
  <my-element></my-element>
</body>

Result

Data Binding

<polymer-element name="my-element">
  <template>
    <h2>{{greeting}}</h2>
  </template>
  <script src="my-element.js"></script>
</polymer-element>
Polymer("my-element", {
  greeting: "Hi, I'm a custom element!"
});

Result

Declarative Event Mapping

<polymer-element name="my-element" on-click="{{clickHandler}}">
  <template>
    <h2>{{greeting}}</h2>
  </template>
  <script src="my-element.js"></script>
</polymer-element>
Polymer("my-element", {
  greeting: "Click me!",
  clickHandler: function() {
    this.greeting = "Hello, " + prompt("What is your name?") + "!";
  }
});

Declarative Layout

Flexbox made simple

Use attributes, not CSS!

<div horizontal layout>
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

Result

Declarative Layout

Flexbox made simple

Flex it!

<div horizontal layout>
  <div>One</div>
  <div flex>Two</div>
  <div>Three</div>
</div>

Result

Declarative Layout

Flexbox made simple

Flex with proportions

<div horizontal layout>
  <div flex>One</div>
  <div flex two>Two</div>
  <div flex three>Three</div>
</div>

Result

Case Study

Glideroom.com

Overview

What is Glideroom?

  • Video conferencing in your browser
  • Built on WebRTC
  • NO registration necessary
  • Get a room with a single click
  • We call it: "Hangouts without the Hangups"

Architecture

  • Front-end built entirely with Polymer
  • Component-based architecture
  • Everything is a custom element
  • Emphasis on small, focused, reusable components
  • Components interact via well-defined public API
  • Asynchronous communication via events

Show me the Code!

room.html

<body>
  <glideroom-backend configuration="/configuration.json"></glideroom-backend>
  <div vertical layout fit>
    <glideroom-toolbar></glideroom-toolbar>
    <div horizontal layout flex>
      <glideroom-conference flex></glideroom-conference>
      <core-splitter direction="right" touch-action="none"></core-splitter>
      <glideroom-chat></glideroom-chat>
    </div>
    <footer-element></footer-element>
  </div>
  <glideroom-dialog-entry id="entry"></glideroom-dialog-entry>
  <glideroom-dialog-settings id="settings"></glideroom-dialog-settings>
  <script src="js/room.s"></script>
</body>

Show me the Code!

room.js

var backend = document.querySelector("glideroom-backend");
var chat = document.querySelector("glideroom-chat");

window.addEventListener("polymer-ready", function() {
  chat.addEventListener("chat-message", function(event) {
    backend.sendMessage(event.detail);
  });
  backend.addEventListener("room-event", function(event) {
    chat.addMessage(event.detail);
    conference.processEvent(event.detail);
  });
  backend.addEventListener("room-ready", function(event) {
    conference.start(event.detail);
  });
});

Resources

RTFM

<Thank You!>