Beyond jQuery Plugins: 

JS UI Library Design

BackboneConf 2013


coursera + backbone


but this isn't a talk about backbone.

this is about  
UI library design!


And no, not that kind of design.

in case that wasn't painfully obvious.

We started with
jQuery Plugins...

A Brief Timeline of jQuery Plugins

January, 2006: 
jQuery released, with plugins built-in

January 25, 2006: 

June 18, 2007: 

September 17, 2007:

May 5, 2009:

jQuery plugins are totally rad
in many ways.

jQuery Plugins:

Encouraged US to Create UI Libraries

You can make your own plugins and use them privately in your code or you can release them into the wild. The barrier to creating a plugin of your own is so low that you'll want to do it straight away!

One of the great aspects of jQuery is its extensibility, as evidenced by the many excellent plugins that have been developed for it.

jQuery Plugins:

Gave US a Standard TO WRITE UI Libs

jQuery Plugins:

Encouraged US to Share UI Libraries

jQuery Plugins 
Aren't Perfect

  1. They have inconsistent or non-existent architecture
  2. They depend on jQuery and often jQuery UI JS/CSS

A Thought Exercise:

What would
JS UI Libraries
look like if they were invented today?

  1. Easy to customize
  2. Not dependent on any libraries
  3. Compatible in AMD and non-AMD environments
  4. Usable by both developers *and* designers
  5. ....the list goes on.

Let's bring 
<Marquee> back! a modern 
JS UI Library.

The Basic Library

<div id="marquee-me">Yo Wassssup!</div>

The Usage:

var marquee = new Marquee(document.getElementById("marquee-me"));
window.setTimeout(function() { marquee.stop(); }, 5000);

The Code:

Hide Private Functionality

Library developers should not be able to call:
marquee.moveItMoveIt(); let's hide it!

The Code: 
(Added _private)

Idempotent Constructor

Developers should be able to call:
var marquee = new Marquee(document.getElementById("marquee-me"));
var marquee2 = new Marquee(document.getElementById("marquee-me"));
window.setTimeout(function() { marquee.stop(); }, 5000); 
...without it doing everything twice.

The Code:
(Added _private.getOrMakeMarquee)


Developers should be able to specify options:
var marquee = new Marquee(document.getElementById("marquee-me"), 
    {direction: 'forwards', distance: 100});
...And re-specify them:
window.setTimeout(function() {
  var marquee2 = new Marquee(document.getElementById("marquee-me"), 
       {direction: 'backwards', distance: 1});
}, 2000);

The Code:
(Added _private.customizeMarquee)

Clear Defaults

Developers should have one place where they can see all the possible customization options and defaults, a la:
defaults: {
    'direction': 'forwards',  // 'forwards' or 'backwards',
    'distance' : '10' // any integer

The Code:
(Added _private.defaults)

Declarative Customization

Designers should be able to configure in HTML:
<div id="marquee-me" 
     Yo Wassssup!

The Code:
(Changed _private.customizeMarquee) 

Declarative Construction

Designers should be able to construct in HTML, too:
<div id="marquee-me" 
     Yo Wassssup!

The Code:
(Added _public.start)


Developers should be able to listen for events:
var marquee = new Marquee(document.getElementById('marquee-me'));
marquee.on('reverse', function() {
  document.getElementById('marquee-me').innerHTML = marquee.direction;

The Code:
(Added EventTarget, .fire() calls)


Developers should be able to use the library in AMD environments:
define("lib/marquee", function(Marquee) {
  var marquee =  new Marquee(document.getElementById('marquee-me'));

The Code: 
(Added define block)

Declared dependencies

If there *are* any dependencies, 
they should be explicitly declared and imported in a clean way.

Common dependencies:


UI libraries should be tested even *more* than normal code, 
because they are more likely to be reused and abused.

The Code:


At minimum, the documentation should show example usage.

Bonus information: 
  • Where to find real usage examples in the codebase
  • Why the library was written in the first place
  • What can be improved in the future

The "Code":

When in doubt, document.



<div data-readme="watchlist-announcement" data-readme-show-count="1" data-readme-show-until-closed="data-readme-show-until-closed" data-readme-show-expires="Jun 15, 2013" class="hide readme">  We now give students the ability to "watch" classes they're interested in, which replaces the need for TBA sessions.
  <a href="" target="_blank" data-readme-close="data-readme-close">Read more here.</a>  <div data-readme-close="data-readme-close" class="readme-close-icon"><span class="icon-remove"></span></div></div>
new Readme(this.$('.readme'));

(Note: data-readme-close, cookie prefix)


<div data-modal-overlay-class="coursera-overlay-dark" class="modal coursera-course-selfstudy-modal hide"> 
   <div class="modal-header"><h2>What is "self study"?</h2></div>
   <div class="modal-body"><p>Self-Study bla bla bla....</p></div>
   <div class="modal-footer"><button data-modal-close="data-modal-close" class="btn btn-primary">OK, I got it!</button></div>
<a data-modal=".coursera-course-selfstudy-modal" role="button">?</a>
(Note: bootstrap optional, singleton enforced)


<li class="course-topbar-nav-list-item"
    tabindex="0" role="button" aria-haspopup="true"
    aria-expanded="false" aria-owns="course-topbar-aboutus"
    data-popup-bind-open="mouseenter" data-popup-direction="se">
    <a>About <i class="icon-caret-down"></i></a>
<div id="course-topbar-aboutus" class="course-topbar-sublist">
    <a class="course-topbar-sublist-item" href="/about/jobs">Jobs</a>
    <a class="course-topbar-sublist-item" href="/about/team">Team</a>
(Note: accessibility, click/touch, singleton enforced)


  • A/B framework
  • Transloadit Uploader
  • Rich Text Area
  • Tooltips
  • Calendar Date Picker
  • Draggable/Sortable

js UI Library
Design Principles:

  • Hidden private functionality
  • Idempotent constructor
  • Customizable with clear defaults
  • Declarative declaration & customization
  • Observable
  • AMD-compatible (but not required)
  • Optional declared dependencies
  • Testable
  • Documented
  • Optional CSS
  • Singletons enforced
  • Accessibility built-in/documented

Improve the Developer Experience


Couldn't you 
do all that 
with jQuery Plugins?

mos def.

You can apply those to anything. so do it!

...or don't, and tell us 
what you do do.

It's good to learn how to do something. It's better to learn many ways of doing something. But it's best to learn all these ways as suggestions or hints . Not truth.
Bret Victor

JS UI Library Design

By pamelafox

JS UI Library Design

  • 13,855