The Art of Developing Nano Widgets

Chris Barber

DojoConf 2011 • Sept.16.2011

About Me

Warning!

Alpha Presentation Framework

Failure is an Option

The Problem

Size Matters

Enter Nano Widgets

Definition: Nano Widget

History: Nano Widget

Say Goodbye To…


IE6 has.js results

Sacrifice

Don't need it, don't add it, rip it out, win

What You Can Use

Where To Use dijit

Introducing The New Nano Widgets

New Nano Widgets!

nano.Accordion

Accordion: dijit vs. nano

dijit.layout.AccordionContainer

  • Ford
  • Chevy
  • Dodge
  • Baseball
  • Football
  • Basketball
  • Hockey
  • Tennis

More »

  • Dog
  • Cat
  • Fish
  • Rock

nano.Accordion

  • Ford
  • Chevy
  • Dodge
  • Baseball
  • Football
  • Basketball
  • Hockey
  • Tennis

More »

  • Dog
  • Cat
  • Fish
  • Rock

Accordion: dijit vs. nano

dijit.layout.AccordionContainer nano.Accordion
Declarative & Programmatic
Animated
Keyboard Accessibility
Icons
Disablable
Easily Change Theme
Select Pane w/ JS
Old Ass Browser Support
# Widget Instances 1 + 3 for each pane 1

Accordion: dijit vs. nano

dijit.layout.AccordionContainer nano.Accordion
JavaScript 22,087 bytes 950 bytes 23x smaller!
CSS 6,287 bytes 508 bytes 12x smaller!
Total 28,374 bytes 1,458 bytes 19x smaller!

nano.Tabs

Tabs: dijit vs. nano

dijit.layout.TabContainer

  • Ford
  • Chevy
  • Dodge
  • Baseball
  • Football
  • Basketball
  • Hockey
  • Tennis

More »

  • Dog
  • Cat
  • Fish
  • Rock

nano.Tabs

  • Ford
  • Chevy
  • Dodge
  • Baseball
  • Football
  • Basketball
  • Hockey
  • Tennis

More »

  • Dog
  • Cat
  • Fish
  • Rock

Tabs: dijit vs. nano

dijit.layout.TabContainer nano.Tabs
Declarative & Programmatic
Keyboard Accessibility
Icons
Tabs on Top
Tabs on Bottom or Sides
Sexy Tab Overflow Scrolling
Disablable
Easily Change Theme
Select Pane w/ JS
Old Ass Browser Support
# Widget Instances 5 + 2 for each pane 1

Tabs: dijit vs. nano

dijit.layout.TabContainer nano.Tabs
JavaScript 33,080 bytes 784 bytes 42x smaller!
CSS 7,187 bytes 596 bytes 12x smaller!
Total 40,267 bytes 1,380 bytes 29x smaller!

nano.Lightbox

Lightbox: dijit vs. nano vs. nano

dojox.image.Lightbox

dojox.image.LightboxNano

nano.Lightbox

Lightbox: dijit vs. nano vs. nano

dojox.image.Lightbox dojox.image.LightboxNano nano.Lightbox
Declarative & Programmatic
Keyboard Accessibility
Mobile Support
Image Groups
Efficient with lots of images
Caption
Video Support
Old Ass Browser Support
# Widget Instances 4 1 1

Lightbox: dijit vs. nano vs. nano

dojox.image.Lightbox dojox.image.LightboxNano nano.Lightbox
JavaScript 29,013 bytes 3,626 bytes 1,137 bytes 25x & 3x smaller!
CSS 7,121 bytes 0 bytes 431 bytes 16x smaller!
Total 36,134 bytes 3,626 bytes 1,568 bytes 23x & 2x smaller!

Code & Hacks

and bad programming practices

Declaring Widgets

dijit Way

dojo.declare(
  "my.widget",
  dijit._Widget,
  {
    postCreate: function() {
      this.domNode.innerHTML = "honey";

      // magic goes here
    }
  }
);

Nano Way

dojo.declare(
  "my.widget",
  null,
  {
    constructor: function(params, node) {
      node.innerHTML = "badger";

      // magic goes here
    }
  }
);

Declarative Nano Params

<div data-dojo-type="my.widget"
     data-param1="not cool"
     data-dojo-props="param2:'cool'">
  <div data-param3="cool" data-dojo-props="param4:'not cool'">
  </div>
</div>

if Shortcuts

Not Nano

if (something) {
	do(something);
}

if (something) {
	name = "Colbert";
}

Nano

something && do(something);

something && (name = "Stewart");

Building Nodes

<div class="outer">
  <div class="inner">Dojo!</div>
</div>
dojo.create("div", {
  className: "inner",
  innerHTML: "Dojo!"
}, dojo.create("div", {
  className: "outer"
}, dojo.body()));
var c = dojo.partial(dojo.create, "div");
c({
  className: "inner",
  innerHTML: "Dojo!"
}, c({
  className: "outer"
}, dojo.body()));

One-Time Event Firing

var h = dojo.connect(node, "onclick", function() {
  dojo.disconnect(h);

  // do stuff
});
define(["dojo/on"], function(on){
  on.once(node, "click", function(evt) {
    // do stuff
  });
});

Templating

define([
  "dojo/_base/declare",
  "dojo/string",
  "dojo/text!./templates/MyWidget.html"
], function(decl, str, template){

  return decl("my.widget", null, {

    constructor: function(params, node) {
      node.innerHTML = str.substitute(template, {
        name: "Agent Smith"
      });
    }

  });

});

Do you need templating? Do you care about visual popping artifacts?

Closure Compiler is Smart

Before Build

define([
  "dojo/_base/declare",
  "dojo/dom-class"
], function(decl, css){

  var baseClass = "nano";

  return decl("nano.test", null, {

    constructor: function(params, node) {
    	css.add(node, baseClass);
    }

  });

});

After Build (Closure Compiler)

define([
  "dojo/_base/declare",
  "dojo/dom-class"
], function(a, b){

  return a("nano.test", null, {

    constructor: function(a, c) {
    	b.add(c, "nano")
    }

  })

});

CSS3 Transitions vs. dojo.fx

// .opacityTransition { transition: opacity 1s ease-in-out; }
dojo.style(node, "opacity", 0);
dojo.addClass(node, "opacityTransition");
setTimeout(function(){
  dojo.style(node, "opacity", 1);
}, 0);

Build System

Carefully Pre-Mature Optimize

Get the code working first

The Future of Nano Widgets

Nano Widget Radar

Questions?

Nano Repo: https://github.com/cb1kenobi/nano

Twitter: http://twitter.com/cb1kenobi

Slides: http://talks.cb1inc.com/