Wednesday, June 20, 2012

Backbone UI


Overview

Backbone UI provides a simple way to represent your Backbone Models and Collections as UI components. The need to shuffle data in and out of your UI is replaced with simple data binding techniques. All components are skinnable with CSS, and will render consistently accross browsers. The source is hosted on github with an MIT license.

Philosophy

This framework is written to embrace the DOM rather than fight it. You won't see any messy HTML templates or innerHTMLreferences hanging around. What you will see is heavy use of the laconic library to help ease the pain of DOM manipluation so we can happily stay in the context of writing JavaScript.
Not all people will agree with this philosophy, and not all projects will benefit from embracing it. This framework facilitates the creation of highly dynamic front-end clients that request only data from the back-end, not markup. If you have a more traditional application in which your markup is generated before your JavaScript executes, you may still find this framework useful, but keep in mind that it was not designed for such a case.
Another major theme you'll encounter is the concept of data binding. This means that you tell your component which property of the model it's responsible for rendering, and then you forget about shuffling data back and forth. If the model's value changes, the component will re-render. If the user changes the value, the model will be updated. Easy.

Dependencies

Backbone UI depends on BackboneUnderscorejQuery, and laconic. If you'd like to use the calendar or date picker components, than you'll also need a copy of moment.js.

Components

All components inherit from Backbone.View, and each render method will return a reference to the view itself. Feel free to pass any standard Backbone View option when creating these components. As a convenience, the underscored version of the component's class name will be added to each component's element.
Components can be broken down into four categories:
  • Model Bound
  • Model Bound with Alternatives
  • Collection Bound
  • Non-Bound
The following data will be used throughout the examples:
window.regions = new Backbone.Collection([{
  name: 'Americas',
  notes: 'Bright'
}, {
  name: 'Africa',
  notes: 'Fruity'
}]);

window.coffee = new Backbone.Model({
  roaster: 'Counter Culture',
  name: 'Baroida',
  roastedOn: new Date(2012, 2, 28, 6, 30),
  acidic: true,
  region: regions.at(0)
});

Model-Bound

Model-Bound components are those that interact directly with one property of a single model.

Options

  • model
    The Backbone.Model instance the view is bound to
  • content
    The property of the bound model this component should render / update. If a function is given, it will be invoked with the model and will expect an element to be returned. If no model is present, this property may be a string or function describing the content to be rendered

Button

var button = new Backbone.UI.Button({
  model: coffee,
  content: 'roaster'
}).render();

Options

  • onClick
    A callback to invoke when the button is clicked
  • isSubmit
    renders this button as an input type=submit element as opposed to an anchor.
  • disabled
    true will disable the button (muted non-clickable)
  • active
    true will activate the button (depressed and non-clickable)

Calendar

var calendar = new Backbone.UI.Calendar({
  model: coffee,
  content: 'roastedOn'
}).render();
Mar 2012
SMTWTFS
26
27
28
29
123
45678910
11121314151617
18192021222324
25262728293031
1
2
3
4
5
6
7

Options

  • date
    the selected calendar date
  • weekStart
    the week's start day (0 = Sunday, 1 = Monday, etc.)
  • onSelect
    a callback to invoke when a new date selection is made. The selected date will be passed in as the first argument

Checkbox

var checkbox = new Backbone.UI.Checkbox({
  model: coffee,
  content: 'acidic',
  labelContent: 'roaster'
}).render();

Options

  • labelContent
    The property of the model describing the label that should be placed next to the checkbox
  • disabled
    enables / disables the checkbox

Date Picker

var picker = new Backbone.UI.DatePicker({
  model: coffee,
  content: 'roastedOn'
}).render();

Options

  • format
    a moment.js format : http://momentjs.com/docs/#/display/format

Text Area

var area = new Backbone.UI.TextArea({
  model: coffee.get('region'),
  content: 'name'
}).render();

Options

  • disabled
    disables the text area
  • textAreaId
    id to use on the actual textArea

Text Field

var field = new Backbone.UI.TextField({
  model: coffee,
  content: 'roaster'
}).render();

Options

  • maxLength
    if given, the text field will limit it's character count
  • type
    The type of input (text, password, number, email, etc.)
  • tabIndex
    the tab index to set on the underlying input field
  • disabled
    disables the input text
  • name
    the value to use for both the name and id attribute of the underlying input element
  • onKeyPress
    a callback to invoke when a key is pressed within the text field

Time Picker

var picker = new Backbone.UI.TimePicker({
  model: coffee,
  content: 'roastedOn'
}).render();

Options

  • interval
    minute interval to use for pulldown menu
  • format
    a moment.js format : http://momentjs.com/docs/#/display/format
  • name
    the name given to the text field's input element

Model-Bound with Alternatives

These components are similar to regular Model-Bound components, but also include a bound collection of alternatives. Themodel and property options are still used to define the selected value, and following additional options describe the collection of alternatives:

Options

  • altValueContent
    The property of the individual choice that represents the value to be stored in the bound model's property. Omit this option if you'd like the choice object itself to represent the value.
  • altGlyph
    The property of the individual choice representing the glyph to be displayed to the left of the item's label
  • altGlyphRight
    The property of the individual choice representing the glyph to be displayed to the right of the item's label
  • alternatives
    The collection of items representing alternative choices
  • altLabelContent
    The property of the individual choice represent the the label to be displayed

Pulldown

var pulldown = new Backbone.UI.Pulldown({
  model: coffee,
  content: 'region',
  alternatives: regions,
  altLabelContent: 'name'
}).render();

Options

  • alignRight
    If true, the menu will be aligned to the right side
  • onMenuShow
    A callback to invoke when the pulldown menu is shown, passing the button click event.
  • onMenuHide
    A callback to invoke when the pulldown menu is hidden, if the menu was hidden as a result of a second click on the pulldown button, the button click event will be passed.
  • placeholder
    text to place in the pulldown button before a selection has been made
  • onChange
    A callback to invoke with a particular item when that item is selected from the pulldown menu.
  • emptyItem
    an additional item to render at the top of the menu to denote the lack of a selection

Radio Group

var group = new Backbone.UI.RadioGroup({
  model: coffee,
  content: 'region',
  alternatives: regions,
  altLabelContent: 'name'
}).render();

Options

  • onChange
    A callback to invoke with the selected item whenever the selection changes

Collection-Bound

These components are bound to a Backbone.Collection as opposed to a Model. The rendering of a particular item in the collection is defined by the given itemView implementation.

Options

  • onItemClick
    A callback to invoke when a row is clicked. The associated model will be passed as the first argument.
  • maxHeight
    The maximum height in pixels that this table show grow to. If the content exceeds this height, it will become scrollable.
  • model
    The Backbone.Collection instance the view is bound to
  • itemView
    The Backbone.View class responsible for rendering a single item in the collection
  • emptyContent
    A string, element, or function describing what should be displayed when the list is empty.

List View

var Item = Backbone.View.extend({
  render: function() {
    $(this.el).empty();
    $.el.div(this.model.get('name')).appendTo(this.el);
  }
});
var list = new Backbone.UI.List({
  model: regions,
  itemView: Item
}).render();
  • Americas
  • Africa

Options

  • itemView
    A Backbone.View implementation describing how to render a particular item in the collection. For simple use cases, you can pass a String instead which will be interpreted as the property of the model to display.

Table View

Table Views are similar to List Views, but allow you to pass a small amount of table meta-data as opposed to writing your own itemView implementation.
var table = new Backbone.UI.TableView({
  sortable: true,
  model: regions,
  onItemClick: function(model) {
    alert(model.get('name'));
  },
  columns: [{
    title: 'Name',
    content: 'name'
  }, {
    title: 'Notes',
    width: 100,
    content: 'notes'
  }]
}).render();
Name
Notes
Africa
Fruity
Americas
Bright

Options

  • onItemClick
    A callback to invoke when a row is clicked. If this callback is present, the rows will highlight on hover.
  • columns
    Each column should contain a label property to describe the column's heading, a content property to declare which property the cell is bound to, an optional two-argument comparator with which to sort each column if the table is sortable, and an optional width property to declare the width of the column in pixels.
  • sortable
    Clicking on the column headers will sort the table. See comparator property description on columns. The table is sorted by the first column by default.
  • onSort
    A callback to invoke when the table is to be sorted. The callback will be passed the column on which to sort.
  • emptyContent
    A string, element, or function describing what should be displayed when the table is empty.

Non-Bound

The following components are not meant to be bound to a model or collection, and exist as general-purpose UI elements.

Scroller

var lorem = "Lorem ipsum dolor sit..."
var scroller = new Backbone.UI.Scroller({
  content: $.el.p({
    style: 'height:150px'
  }, lorem)
}).render();
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eu metus turpis. Vestibulum quis mauris quis lectus tincidunt sollicitudin. Nunc a lobortis urna. Vivamus pharetra, odio ut sollicitudin mattis, metus nulla scelerisque sapien, sit amet pulvinar dui tellus a velit. Aliquam sapien tellus, auctor et pellentesque in, sodales et lectus. Praesent in massa nec dui hendrerit elementum. Vestibulum egestas, velit non pharetra porta, leo ligula tincidunt dui, sed egestas tortor ipsum in nisl. Vestibulum tincidunt tortor quis metus lacinia non pretium velit bibendum. Donec id erat at dui sodales adipiscing. Sed eleifend vulputate magna, luctus placerat nibh lobortis eu. Aenean vehicula molestie enim, ac suscipit nulla fermentum a. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla sodales, nisl id volutpat blandit, sem erat tincidunt massa, ac pharetra neque lacus ut justo. Vestibulum auctor hendrerit risus, vitae ultrices risus porttitor id.

Options

  • onScroll
    A callback to invoke when scrolling occurs
  • content
    The content to be scrolled. This element should be of a fixed height.
  • scrollAmount
    The amount to scroll on each wheel click

Tab Set

var set = new Backbone.UI.TabSet({
  tabs: [{
    label: 'Foo',
    content: "foo's content"
  }, {
    label: 'Bar',
    content: "bar's content"
  }, {
    label: 'Baz',
    content: "baz's content"
  }]
}).render();
foo's content

Options

  • tabs
    Tabs to initially add to this tab set. Each entry may contain a labelcontent, and onActivate option.

Glyphs

Many components may be rendered with an optional glyph on the left or right side. A glyph is a 16 x 16 pixel image stored in theBackbone.UI.GLYPH_DIR (which defaults to /images/glyphs). Here's some examples:
glyph glyph glyph glyph
And here's how you can put them to use:
var button = new Backbone.UI.Button({
  content: 'Edit',
  glyphRight: 'pencil'
}).render();
var link = new Backbone.UI.Link({
  content: 'Idea',
  glyph: 'lightbulb'
}).render();
var pulldown = new Backbone.UI.Pulldown({
  alternatives: [{
    name: 'save',
    glyph: 'disk'
  }, {
    name: 'trash',
    glyph: 'delete'
  }],
  altLabelContent: 'name',
  altGlyph: 'glyph'
}).render();

Browser Support

Backbone UI has been tested on most modern browsers, as well as IE8+. If you're using the HTML 5 Doctype, you may need to use the following meta tag to force IE into standards mode:
<meta http-equiv="X-UA-Compatible" value="IE=edge" />

Example Application

What would a framework be these days without an example task list application.
The entirety of this application is listed below:
// create a sorted backbone collection to store our tasks
var tasks = new Backbone.Collection([], {
  comparator: function(task) {
    return task.get('done') ? 1 : 0;
  }
});
// define how each individual task should render
var TaskView = Backbone.View.extend({
  render: function() {
    $(this.el).empty();

    // add a link to remove this task from the list
    this.el.appendChild(new Backbone.UI.Link({
      glyph: 'delete',
      onClick: _(tasks.remove).bind(tasks, this.model)
    }).render().el);

    // a checkbox to mark / unmark the done status of this task 
    this.el.appendChild(new Backbone.UI.Checkbox({
      model: this.model,
      labelContent: 'title',
      content: 'done'
    }).render().el);
  }
});
// create our list view to render our collection
var list = new Backbone.UI.List({
  itemView: TaskView,
  model: tasks}).render();
// create a text field to add new items 
var newItem = new Backbone.Model;
var field = new Backbone.UI.TextField({
  model: newItem,
  content: 'title',
  placeholder: 'add a new item',
  onKeyPress: function(e) {
    if (e.keyCode == 13) {
      list.options.model.add(newItem.clone());
      newItem.set({
        title: undefined
      });
    }
  }
}).render();
var appEl = $.el.div(field.el, list.el);

No comments:

Post a Comment