jQuery 202 & Web components

Presenter Notes

Our Presenters

David Luecke

Eric Kryski

Presenter Notes

Our Sponsors

Assembly Co-working Space

Assembly

PetroFeed

PetroFeed

Presenter Notes

Our Sponsors

Village Brewery

Village Brewery

Presenter Notes

jQuery 202

Presenter Notes

What are we going to do?

  • Un-spaghetti and modularize your code
  • Making your code faster
  • Advanced selectors and DOM traversal
  • Writing your own plugins

Presenter Notes

Scope in JavaScript

JavaScript only knows function scope

for(var i = 0; i < 10; i++) {
    var x = 'testing';

    (function(arg) {
        var y = 42;
    })(i);
}

Global variables

function test() {
    var local = 42;
    global = 'global';
}

test();

Presenter Notes

Namespacing

var App = {
    init : function() {
        /* ... */
    },
    Dummy : {
        sayHi : function(name) {
            return 'Hi ' + name;
        }
    }
}

App.Blog = {
    getPosts : function() { /* ... */ }
}

console.log(App.Dummy.sayHi('David'));

Presenter Notes

Modules

var APP = (function() {
    // Do stuff
    var privateVariable = 'Hello ',
        sayHi = function(name) {
            return privateVariable + name;
        };
    // Return API
    return {
        init : function() { /* ... */ },
        hi : sayHi
    }
})();

console.log(APP.sayHi('David'));

Presenter Notes

Asynchronous Module Definition

AMD: CommonJS specification for asynchronously loading dependencies.

// say_hi.js
define(function() {
    var privateVariable = 'Hello ';
    return {
        sayHi : function(name) {
            return privateVariable + name;
        }
    }
});

// module.js
define(['say_hi.js'], function(hisayer) {
    return {
        result : hisayer.sayHi('David'),
        sayHi : hisayer
    }
});

// app.js
var module = require('module.js', function(module) {
    module.sayHi('You'); // Hello You
    module.result; // -> Hello David
});

Presenter Notes

jQuery performance

With an empty list

<ul></ul>

We want to create 2000 list elements using jQuery:

for(var i = 0; i < 2000; i++) {
    $('ul').append('<li>Entry ' + i + '</li>');
}

Storing the selector:

var ul = $('ul');
for(var i = 0; i < 2000; i++) {
    ul.append('<li>Entry ' + i + '</li>');
}

Presenter Notes

Even faster...

DOM manipulation is expensive. Avoid it whenever possible.

Create a string with 2000 list elements, then append it:

var html = '';

for(var i = 0; i < 2000; i++) {
    html += '<li>Entry ' + i + '</li>';
}

$('ul').append(html);

The best:

Separate HTML from your JavaScript and use a client side templating language like _.template, Mustache, Handlebars, EJS or Jade.

Presenter Notes

Advanced selectors

  • Attribute [attributeName]
    • Attribute contains [attributeName*="something"]
    • Attribute equals [attributeName="something"]
  • Parent child parent > child
  • Next adjacent prev + next
  • Contains text :contains("text")
  • First and last :first, :last
  • Not selector :not(otherSelector)

Presenter Notes

A jQuery plugin

It's as simple as:

// myplugin.js
(function($, undefined) {
   $.fn.myButton = function() {
    this.each(function(button) {
      var text = button.text();
      button.click(function() {
        alert(text);
      });
    });

    return this;
   }
})(jQuery);

And can be used like this:

$('button').myButton();

Presenter Notes

Accordion

Building your own jQuery plugin to turn Bootstrap panels with heading into an accordion:

// myplugin.js
(function($, undefined) {
   $.fn.accordion = function() {
     var element = this;

     element.find('.panel-body:not(:first)').hide();

     element.find('.panel-heading').on('click', function() {
       element.find('.panel-body:visible').slideUp();
       $(this).next('.panel-body').slideDown();
     });
   }
})(jQuery);

Use it like this:

$(function() {
  $('#accordion').accordion();
});

Presenter Notes

Web components

Presenter Notes

What are we going to do?

  • Introduction to web components
  • Custom elements
  • Data driven views
  • Build web component style applications now with CanJS

Presenter Notes

The web component model

The component model for the Web ("Web Components") consists of five pieces:

  • Templates, which define chunks of markup that are inert but can be activated for use later.
  • Decorators, which apply templates based on CSS selectors to affect rich visual and behavioral changes to documents.
  • Custom Elements, which let authors define their own elements, with new tag names and new script interfaces.
  • Shadow DOM, which encapsulates a DOM subtree for more reliable composition of user interface elements.
  • Imports, which defines how templates, decorators and custom elements are packaged and loaded as a resource.

Presenter Notes

Presenter Notes

Custom elements

document.registerElement('todo-list');

Lets you do:

<todo-list id="todos"></todo-list>

Which is great because it also allows to:

var todo = Object.create(HTMLElement.prototype);

todo.addTodo = function(description) {
    var paragraph = document.createElement('p');
    paragraph.innerHTML = description;
    this.appendChild(paragraph);
};

document.registerElement('todo-list', {
    prototype: todo
});

And then work with it:

document.getElementById('todos').addTodo('Hello there');

Presenter Notes

The bright future

Directly load third party components and customize them.

<link rel="import" href="http://yycjs.com/davids-awesome-grid.html">

<davids-awesome-grid class="grid">
    <grid-row>
        <grid-column from="name"></grid-column>
        <grid-column>Delete</grid-column>
    </grid-row>
</davids-awesome-grid>

<script>
    document.querySelector('davids-awesome-grid').setData([{
        name: 'Eric'
    }, {
        name: 'David'
    }]);
</script>

Presenter Notes

Data driven views

Use HTML style declarations

<ul>
  <li ng-repeat="todo in todos | filter:statusFilter track by $index"
    ng-class="{completed: todo.completed, editing: todo == editedTodo}">
        ...
  </li>
</ul>

Or a templating language like Handlebars:

{{#each filteredTodos}}
<ul>
  <li class="todo{{#if complete}} completed{{/if}}
    {{#if editing}} editing{{/if}}">
    ...
  </li>
</ul>
{{/each}}

That updates automatically when its data changes.

Presenter Notes

can.Component

The CanJS approach of controller + custom elements + data driven templates:

can.Component.extend({
  tag: "todos-app",
  scope: {
    selectedTodo: null,
    todos: new Todo.List({}),
    select: function(todo){
      this.attr('selectedTodo', todo);
    },
    save: function(todo) {
      todo.save();
      this.removeAttr('selectedTodo');
    }
  }
});

Presenter Notes

can.view.mustache

<todos-app>
  <h2>Todays to-dos</h2>
  {{#selectedTodo}}
  <input type="text"
         can-value="description"
         can-change="save">
  {{/selectedTodo}}
  <ul>
    {{#each todos}}
    <li>
      <input type="checkbox"
             can-value="complete">
      <span class="{{#if complete}}done{{/if}}"
            can-click="select">
        {{description}}
      </span>
      <button can-click="destroy"></button>
    </li>
    {{/each}}
  </ul>
</todos-app>

Presenter Notes

Next Month - Node time

We partner up with Startup Calgary and take over the Hacknight on Tuesday, April 29th.

  1. Node for noobs
  2. Real time mobile web apps

NodeJS logo

Presenter Notes