diff --git a/www/documentation.html b/www/documentation.html
index a7db6b4..d73e93b 100644
--- a/www/documentation.html
+++ b/www/documentation.html
@@ -34,7 +34,7 @@
config
Backbone.Epoxy.binding.config( settings )
diff --git a/www/index.html b/www/index.html
index 46551f6..2b952a3 100644
--- a/www/index.html
+++ b/www/index.html
@@ -33,7 +33,7 @@
Epoxy .js Elegant Data Binding for Backbone
diff --git a/www/js/backbone.epoxy.js b/www/js/backbone.epoxy.js
new file mode 100644
index 0000000..cb237a1
--- /dev/null
+++ b/www/js/backbone.epoxy.js
@@ -0,0 +1,1324 @@
+// Backbone.Epoxy
+
+// (c) 2013 Greg MacWilliam
+// Freely distributed under the MIT license
+// For usage and documentation:
+// http://epoxyjs.org
+
+(function(root, factory) {
+
+
+ if (typeof exports !== 'undefined') {
+ // Define as CommonJS export:
+ module.exports = factory(require("underscore"), require("backbone"));
+ } else if (typeof define === 'function' && define.amd) {
+ // Define as AMD:
+ define(["underscore", "backbone"], factory);
+ } else {
+ // Just run it:
+ factory(root._, root.Backbone);
+ }
+
+}(this, function(_, Backbone) {
+
+ // Epoxy namespace:
+ var Epoxy = Backbone.Epoxy = {};
+
+ // Object-type utils:
+ var array = Array.prototype;
+ var isUndefined = _.isUndefined;
+ var isFunction = _.isFunction;
+ var isObject = _.isObject;
+ var isArray = _.isArray;
+ var isModel = function(obj) { return obj instanceof Backbone.Model; };
+ var isCollection = function(obj) { return obj instanceof Backbone.Collection; };
+ var blankMethod = function() {};
+
+ // Static mixins API:
+ // added as a static member to Epoxy class objects (Model & View);
+ // generates a set of class attributes for mixin with other objects.
+ var mixins = {
+ mixin: function(extend) {
+ extend = extend || {};
+
+ for (var i in this.prototype) {
+ if (this.prototype.hasOwnProperty(i) && i !== 'constructor') {
+ extend[i] = this.prototype[i];
+ }
+ }
+ return extend;
+ }
+ };
+
+ // Partial application for calling method implementations of a super-class object:
+ function superClass(sup) {
+ return function(instance, method, args) {
+ return sup.prototype[ method ].apply(instance, args);
+ };
+ }
+
+
+ // Epoxy.Model
+ // -----------
+ var modelMap;
+ var modelSuper = superClass(Backbone.Model);
+ var modelProps = ['computeds'];
+
+ Epoxy.Model = Backbone.Model.extend({
+
+ // Backbone.Model constructor override:
+ // configures computed model attributes around the underlying native Backbone model.
+ constructor: function(attributes, options) {
+ _.extend(this, _.pick(options||{}, modelProps));
+ modelSuper(this, 'constructor', arguments);
+ this.initComputeds(attributes, options);
+ },
+
+ // Gets a copy of a model attribute value:
+ // Array and Object values will return a shallow copy,
+ // primitive values will be returned directly.
+ getCopy: function(attribute) {
+ return _.clone(this.get(attribute));
+ },
+
+ // Backbone.Model.get() override:
+ // provides access to computed attributes,
+ // and maps computed dependency references while establishing bindings.
+ get: function(attribute) {
+
+ // Automatically register bindings while building out computed dependency graphs:
+ modelMap && modelMap.push(['change:'+attribute, this]);
+
+ // Return a computed property value, if available:
+ if (this.hasComputed(attribute)) {
+ return this.c()[ attribute ].get();
+ }
+
+ // Default to native Backbone.Model get operation:
+ return modelSuper(this, 'get', arguments);
+ },
+
+ // Backbone.Model.set() override:
+ // will process any computed attribute setters,
+ // and then pass along all results to the underlying model.
+ set: function(key, value, options) {
+ var params = key;
+
+ // Convert key/value arguments into {key:value} format:
+ if (params && !isObject(params)) {
+ params = {};
+ params[ key ] = value;
+ } else {
+ options = value;
+ }
+
+ // Default options definition:
+ options = options || {};
+
+ // Attempt to set computed attributes while not unsetting:
+ if (!options.unset) {
+ // All param properties are tested against computed setters,
+ // properties set to computeds will be removed from the params table.
+ // Optionally, an computed setter may return key/value pairs to be merged into the set.
+ params = deepModelSet(this, params, {}, []);
+ }
+
+ // Pass all resulting set params along to the underlying Backbone Model.
+ return modelSuper(this, 'set', [params, options]);
+ },
+
+ // Backbone.Model.toJSON() override:
+ // adds a 'computed' option, specifying to include computed attributes.
+ toJSON: function(options) {
+ var json = modelSuper(this, 'toJSON', arguments);
+
+ if (options && options.computed) {
+ _.each(this.c(), function(computed, attribute) {
+ json[ attribute ] = computed.value;
+ });
+ }
+
+ return json;
+ },
+
+ // Backbone.Model.destroy() override:
+ // clears all computed attributes before destroying.
+ destroy: function() {
+ this.clearComputeds();
+ return modelSuper(this, 'destroy', arguments);
+ },
+
+ // Computed namespace manager:
+ // Allows the model to operate as a mixin.
+ c: function() {
+ return this._c || (this._c = {});
+ },
+
+ // Initializes the Epoxy model:
+ // called automatically by the native constructor,
+ // or may be called manually when adding Epoxy as a mixin.
+ initComputeds: function(attributes, options) {
+ this.clearComputeds();
+
+ // Resolve computeds hash, and extend it with any preset attribute keys:
+ // TODO: write test.
+ var computeds = _.result(this, 'computeds')||{};
+ computeds = _.extend(computeds, _.pick(attributes||{}, _.keys(computeds)));
+
+ // Add all computed attributes:
+ _.each(computeds, function(params, attribute) {
+ params._init = 1;
+ this.addComputed(attribute, params);
+ }, this);
+
+ // Initialize all computed attributes:
+ // all presets have been constructed and may reference each other now.
+ _.invoke(this.c(), 'init');
+ },
+
+ // Adds a computed attribute to the model:
+ // computed attribute will assemble and return customized values.
+ // @param attribute (string)
+ // @param getter (function) OR params (object)
+ // @param [setter (function)]
+ // @param [dependencies ...]
+ addComputed: function(attribute, getter, setter) {
+ this.removeComputed(attribute);
+
+ var params = getter;
+ var delayInit = params._init;
+
+ // Test if getter and/or setter are provided:
+ if (isFunction(getter)) {
+ var depsIndex = 2;
+
+ // Add getter param:
+ params = {};
+ params._get = getter;
+
+ // Test for setter param:
+ if (isFunction(setter)) {
+ params._set = setter;
+ depsIndex++;
+ }
+
+ // Collect all additional arguments as dependency definitions:
+ params.deps = array.slice.call(arguments, depsIndex);
+ }
+
+ // Create a new computed attribute:
+ this.c()[ attribute ] = new EpoxyComputedModel(this, attribute, params, delayInit);
+ return this;
+ },
+
+ // Tests the model for a computed attribute definition:
+ hasComputed: function(attribute) {
+ return this.c().hasOwnProperty(attribute);
+ },
+
+ // Removes an computed attribute from the model:
+ removeComputed: function(attribute) {
+ if (this.hasComputed(attribute)) {
+ this.c()[ attribute ].dispose();
+ delete this.c()[ attribute ];
+ }
+ return this;
+ },
+
+ // Removes all computed attributes:
+ clearComputeds: function() {
+ for (var attribute in this.c()) {
+ this.removeComputed(attribute);
+ }
+ return this;
+ },
+
+ // Internal array value modifier:
+ // performs array ops on a stored array value, then fires change.
+ // No action is taken if the specified attribute value is not an array.
+ modifyArray: function(attribute, method, options) {
+ var obj = this.get(attribute);
+
+ if (isArray(obj) && isFunction(array[method])) {
+ var args = array.slice.call(arguments, 2);
+ var result = array[ method ].apply(obj, args);
+ options = options || {};
+
+ if (!options.silent) {
+ this.trigger('change:'+attribute+' change', this, array, options);
+ }
+ return result;
+ }
+ return null;
+ },
+
+ // Internal object value modifier:
+ // sets new property values on a stored object value, then fires change.
+ // No action is taken if the specified attribute value is not an object.
+ modifyObject: function(attribute, property, value, options) {
+ var obj = this.get(attribute);
+ var change = false;
+
+ // If property is Object:
+ if (isObject(obj)) {
+
+ options = options || {};
+
+ // Delete existing property in response to undefined values:
+ if (isUndefined(value) && obj.hasOwnProperty(property)) {
+ delete obj[property];
+ change = true;
+ }
+ // Set new and/or changed property values:
+ else if (obj[ property ] !== value) {
+ obj[ property ] = value;
+ change = true;
+ }
+
+ // Trigger model change:
+ if (change && !options.silent) {
+ this.trigger('change:'+attribute+' change', this, obj, options);
+ }
+
+ // Return the modified object:
+ return obj;
+ }
+ return null;
+ }
+ }, mixins);
+
+ // Epoxy.Model -> Private
+ // ----------------------
+
+ // Model deep-setter:
+ // Attempts to set a collection of key/value attribute pairs to computed attributes.
+ // Observable setters may digest values, and then return mutated key/value pairs for inclusion into the set operation.
+ // Values returned from computed setters will be recursively deep-set, allowing computeds to set other computeds.
+ // The final collection of resolved key/value pairs (after setting all computeds) will be returned to the native model.
+ // @param model: target Epoxy model on which to operate.
+ // @param toSet: an object of key/value pairs to attempt to set within the computed model.
+ // @param toReturn: resolved non-ovservable attribute values to be returned back to the native model.
+ // @param trace: property stack trace (prevents circular setter loops).
+ function deepModelSet(model, toSet, toReturn, stack) {
+
+ // Loop through all setter properties:
+ for (var attribute in toSet) {
+ if (toSet.hasOwnProperty(attribute)) {
+
+ // Pull each setter value:
+ var value = toSet[ attribute ];
+
+ if (model.hasComputed(attribute)) {
+
+ // Has a computed attribute:
+ // comfirm attribute does not already exist within the stack trace.
+ if (!stack.length || !_.contains(stack, attribute)) {
+
+ // Non-recursive:
+ // set and collect value from computed attribute.
+ value = model.c()[attribute].set(value);
+
+ // Recursively set new values for a returned params object:
+ // creates a new copy of the stack trace for each new search branch.
+ if (value && isObject(value)) {
+ toReturn = deepModelSet(model, value, toReturn, stack.concat(attribute));
+ }
+
+ } else {
+ // Recursive:
+ // Throw circular reference error.
+ throw('Recursive setter: '+stack.join(' > '));
+ }
+
+ } else {
+ // No computed attribute:
+ // set the value to the keeper values.
+ toReturn[ attribute ] = value;
+ }
+ }
+ }
+
+ return toReturn;
+ }
+
+
+ // Epoxy.Model -> Computed
+ // -----------------------
+ // Computed objects store model values independently from the model's attributes table.
+ // Computeds define custom getter/setter functions to manage their value.
+
+ function EpoxyComputedModel(model, name, params, delayInit) {
+ params = params || {};
+
+ // Rewrite getter param:
+ if (params.get && isFunction(params.get)) {
+ params._get = params.get;
+ }
+
+ // Rewrite setter param:
+ if (params.set && isFunction(params.set)) {
+ params._set = params.set;
+ }
+
+ // Prohibit override of 'get()' and 'set()', then extend:
+ delete params.get;
+ delete params.set;
+ _.extend(this, params);
+
+ // Set model, name, and default dependencies array:
+ this.model = model;
+ this.name = name;
+ this.deps = this.deps || [];
+
+ // Skip init while parent model is initializing:
+ // Model will initialize in two passes...
+ // the first pass sets up all computed attributes,
+ // then the second pass initializes all bindings.
+ if (!delayInit) this.init();
+ }
+
+ _.extend(EpoxyComputedModel.prototype, Backbone.Events, {
+
+ // Initializes the computed's value and bindings:
+ // this method is called independently from the object constructor,
+ // allowing computeds to build and initialize in two passes by the parent model.
+ init: function() {
+
+ // Configure dependency map, then update the computed's value:
+ // All Epoxy.Model attributes accessed while getting the initial value
+ // will automatically register themselves within the model bindings map.
+ var bindings = {};
+ var deps = modelMap = [];
+ this.get(true);
+ modelMap = null;
+
+ // If the computed has dependencies, then proceed to binding it:
+ if (deps.length) {
+
+ // Compile normalized bindings table:
+ // Ultimately, we want a table of event types, each with an array of their associated targets:
+ // {'change:name':[
], 'change:status':[,]}
+
+ // Compile normalized bindings map:
+ _.each(deps, function(value) {
+ var attribute = value[0];
+ var target = value[1];
+
+ // Populate event target arrays:
+ if (!bindings[attribute]) {
+ bindings[attribute] = [ target ];
+
+ } else if (!_.contains(bindings[attribute], target)) {
+ bindings[attribute].push(target);
+ }
+ });
+
+ // Bind all event declarations to their respective targets:
+ _.each(bindings, function(targets, binding) {
+ for (var i=0, len=targets.length; i < len; i++) {
+ this.listenTo(targets[i], binding, _.bind(this.get, this, true));
+ }
+ }, this);
+ }
+ },
+
+ // Gets an attribute value from the parent model.
+ val: function(attribute) {
+ return this.model.get(attribute);
+ },
+
+ // Gets the computed's current value:
+ // Computed values flagged as dirty will need to regenerate themselves.
+ // Note: 'update' is strongly checked as TRUE to prevent unintended arguments (handler events, etc) from qualifying.
+ get: function(update) {
+ if (update === true && this._get) {
+ var val = this._get.apply(this.model, _.map(this.deps, this.val, this));
+ this.change(val);
+ }
+ return this.value;
+ },
+
+ // Sets the computed's current value:
+ // computed values (have a custom getter method) require a custom setter.
+ // Custom setters should return an object of key/values pairs;
+ // key/value pairs returned to the parent model will be merged into its main .set() operation.
+ set: function(val) {
+ if (this._get) {
+ if (this._set) return this._set.apply(this.model, arguments);
+ else throw('Cannot set read-only computed attribute.');
+ }
+ this.change(val);
+ return null;
+ },
+
+ // Changes the computed's value:
+ // new values are cached, then fire an update event.
+ change: function(value) {
+ if (!_.isEqual(value, this.value)) {
+ this.value = value;
+ this.model.trigger('change:'+this.name+' change', this.model);
+ }
+ },
+
+ // Disposal:
+ // cleans up events and releases references.
+ dispose: function() {
+ this.stopListening();
+ this.off();
+ this.model = this.value = null;
+ }
+ });
+
+
+ // Epoxy.binding -> Binding API
+ // ----------------------------
+
+ var bindingSettings = {
+ optionText: 'label',
+ optionValue: 'value'
+ };
+
+
+ // Cache for storing binding parser functions:
+ // Cuts down on redundancy when building repetitive binding views.
+ var bindingCache = {};
+
+
+ // Reads value from an accessor:
+ // Accessors come in three potential forms:
+ // => A function to call for the requested value.
+ // => An object with a collection of attribute accessors.
+ // => A primitive (string, number, boolean, etc).
+ // This function unpacks an accessor and returns its underlying value(s).
+
+ function readAccessor(accessor) {
+
+ if (isFunction(accessor)) {
+ // Accessor is function: return invoked value.
+ return accessor();
+ }
+ else if (isObject(accessor)) {
+ // Accessor is object/array: return copy with all attributes read.
+ accessor = _.clone(accessor);
+
+ _.each(accessor, function(value, key) {
+ accessor[ key ] = readAccessor(value);
+ });
+ }
+ // return formatted value, or pass through primitives:
+ return accessor;
+ }
+
+
+ // Binding Handlers
+ // ----------------
+ // Handlers define set/get methods for exchanging data with the DOM.
+
+ // Formatting function for defining new handler objects:
+ function makeHandler(handler) {
+ return isFunction(handler) ? {set: handler} : handler;
+ }
+
+ var bindingHandlers = {
+ // Attribute: write-only. Sets element attributes.
+ attr: makeHandler(function($element, value) {
+ $element.attr(value);
+ }),
+
+ // Checked: read-write. Toggles the checked status of a form element.
+ checked: makeHandler({
+ get: function($element, currentValue) {
+ var checked = !!$element.prop('checked');
+ var value = $element.val();
+
+ if (this.isRadio($element)) {
+ // Radio button: return value directly.
+ return value;
+
+ } else if (isArray(currentValue)) {
+ // Checkbox array: add/remove value from list.
+ currentValue = currentValue.slice();
+ var index = _.indexOf(currentValue, value);
+
+ if (checked && index < 0) {
+ currentValue.push(value);
+ } else if (!checked && index > -1) {
+ currentValue.splice(index, 1);
+ }
+ return currentValue;
+ }
+ // Checkbox: return boolean toggle.
+ return checked;
+ },
+ set: function($element, value) {
+ // Default as loosely-typed boolean:
+ var checked = !!value;
+
+ if (this.isRadio($element)) {
+ // Radio button: match checked state to radio value.
+ checked = (value == $element.val());
+
+ } else if (isArray(value)) {
+ // Checkbox array: match checked state to checkbox value in array contents.
+ checked = _.contains(value, $element.val());
+ }
+
+ // Set checked property to element:
+ $element.prop('checked', checked);
+ },
+ // Is radio button: avoids '.is(":radio");' check for basic Zepto compatibility.
+ isRadio: function($element) {
+ return $element.attr('type').toLowerCase() === 'radio';
+ }
+ }),
+
+ // Class Name: write-only. Toggles a collection of class name definitions.
+ classes: makeHandler(function($element, value) {
+ _.each(value, function(enabled, className) {
+ $element.toggleClass(className, !!enabled);
+ });
+ }),
+
+ // Collection: write-only. Manages a list of views bound to a Backbone.Collection.
+ collection: makeHandler({
+ init: function($element, collection) {
+ if (!isCollection(collection) || !isFunction(collection.view)) {
+ throw('Binding "collection" requires a Collection with a "view" constructor.');
+ }
+ this.v = {};
+ },
+ set: function($element, collection, target) {
+
+ var view;
+ var views = this.v;
+ var models = collection.models;
+
+ // Cache and reset the current dependency graph state:
+ // sub-views may be created (each with their own dependency graph),
+ // therefore we need to suspend the working graph map here before making children...
+ var mapCache = viewMap;
+ viewMap = null;
+
+ // Default target to the bound collection object:
+ // during init (or failure), the binding will reset.
+ target = target || collection;
+
+ if (isModel(target)) {
+
+ // ADD/REMOVE Event (from a Model):
+ // test if view exists within the binding...
+ if (!views.hasOwnProperty(target.cid)) {
+
+ // Add new view:
+ views[ target.cid ] = view = new collection.view({model: target});
+ var index = _.indexOf(models, target);
+ var $children = $element.children();
+
+ // Attempt to add at proper index,
+ // otherwise just append into the element.
+ if (index < $children.length) {
+ $children.eq(index).before(view.$el);
+ } else {
+ $element.append(view.$el);
+ }
+
+ } else {
+
+ // Remove existing view:
+ views[ target.cid ].remove();
+ delete views[ target.cid ];
+ }
+
+ } else if (isCollection(target)) {
+
+ // SORT/RESET Event (from a Collection):
+ // First test if we're sorting...
+ // (number of models has not changed and all their views are present)
+ var sort = models.length === _.size(views) && collection.every(function(model) {
+ return views.hasOwnProperty(model.cid);
+ });
+
+ // Hide element before manipulating:
+ $element.children().detach();
+ var frag = document.createDocumentFragment();
+
+ if (sort) {
+ // Sort existing views:
+ collection.each(function(model) {
+ frag.appendChild(views[model.cid].el);
+ });
+
+ } else {
+ // Reset with new views:
+ this.clean();
+ collection.each(function(model) {
+ views[ model.cid ] = view = new collection.view({model: model});
+ frag.appendChild(view.el);
+ });
+ }
+
+ $element.append(frag);
+ }
+
+ // Restore cached dependency graph configuration:
+ viewMap = mapCache;
+ },
+ clean: function() {
+ for (var id in this.v) {
+ if (this.v.hasOwnProperty(id)) {
+ this.v[ id ].remove();
+ delete this.v[ id ];
+ }
+ }
+ }
+ }),
+
+ // CSS: write-only. Sets a collection of CSS styles to an element.
+ css: makeHandler(function($element, value) {
+ $element.css(value);
+ }),
+
+ // Disabled: write-only. Sets the 'disabled' status of a form element (true :: disabled).
+ disabled: makeHandler(function($element, value) {
+ $element.prop('disabled', !!value);
+ }),
+
+ // Enabled: write-only. Sets the 'disabled' status of a form element (true :: !disabled).
+ enabled: makeHandler(function($element, value) {
+ $element.prop('disabled', !value);
+ }),
+
+ // HTML: write-only. Sets the inner HTML value of an element.
+ html: makeHandler(function($element, value) {
+ $element.html(value);
+ }),
+
+ // Options: write-only. Sets option items to a element, then updates the value.
+ options: makeHandler({
+ init: function($element, value, context, bindings) {
+ this.e = bindings.optionsEmpty;
+ this.d = bindings.optionsDefault;
+ this.v = bindings.value;
+ },
+ set: function($element, value) {
+
+ // Pre-compile empty and default option values:
+ // both values MUST be accessed, for two reasons:
+ // 1) we need to need to guarentee that both values are reached for mapping purposes.
+ // 2) we'll need their values anyway to determine their defined/undefined status.
+ var self = this;
+ var optionsEmpty = readAccessor(self.e);
+ var optionsDefault = readAccessor(self.d);
+ var currentValue = readAccessor(self.v);
+ var options = isCollection(value) ? value.models : value;
+ var numOptions = options.length;
+ var enabled = true;
+ var html = '';
+
+ // No options or default, and has an empty options placeholder:
+ // display placeholder and disable select menu.
+ if (!numOptions && !optionsDefault && optionsEmpty) {
+
+ html += self.opt(optionsEmpty, numOptions);
+ enabled = false;
+
+ } else {
+ // Try to populate default option and options list:
+
+ // Configure list with a default first option, if defined:
+ if (optionsDefault) {
+ options = [ optionsDefault ].concat(options);
+ }
+
+ // Create all option items:
+ _.each(options, function(option, index) {
+ html += self.opt(option, numOptions);
+ });
+ }
+
+ // Set new HTML to the element and toggle disabled status:
+ $element.html(html).prop('disabled', !enabled).val(currentValue);
+
+ // Pull revised value with new options selection state:
+ var revisedValue = $element.val();
+
+ // Test if the current value was successfully applied:
+ // if not, set the new selection state into the model.
+ if (self.v && !_.isEqual(currentValue, revisedValue)) {
+ self.v(revisedValue);
+ }
+ },
+ opt: function(option, numOptions) {
+ // Set both label and value as the raw option object by default:
+ var label = option;
+ var value = option;
+ var textAttr = bindingSettings.optionText;
+ var valueAttr = bindingSettings.optionValue;
+
+ // Dig deeper into label/value settings for non-primitive values:
+ if (isObject(option)) {
+ // Extract a label and value from each object:
+ // a model's 'get' method is used to access potential computed values.
+ label = isModel(option) ? option.get(textAttr) : option[ textAttr ];
+ value = isModel(option) ? option.get(valueAttr) : option[ valueAttr ];
+ }
+
+ return ['', label, ' '].join('');
+ },
+ clean: function() {
+ this.d = this.e = this.v = 0;
+ }
+ }),
+
+ // Template: write-only. Renders the bound element with an Underscore template.
+ template: makeHandler({
+ init: function($element, value, context) {
+ var raw = $element.find('script,template');
+ this.t = _.template(raw.length ? raw.html() : $element.html());
+
+ // If an array of template attributes was provided,
+ // then replace array with a compiled hash of attribute accessors:
+ if (isArray(value)) {
+ return _.pick(context, value);
+ }
+ },
+ set: function($element, value) {
+ value = isModel(value) ? value.toJSON({computed:true}) : value;
+ $element.html(this.t(value));
+ },
+ clean: function() {
+ this.t = null;
+ }
+ }),
+
+ // Text: write-only. Sets the text value of an element.
+ text: makeHandler(function($element, value) {
+ $element.text(value);
+ }),
+
+ // Toggle: write-only. Toggles the visibility of an element.
+ toggle: makeHandler(function($element, value) {
+ $element.toggle(!!value);
+ }),
+
+ // Value: read-write. Gets and sets the value of a form element.
+ value: makeHandler({
+ get: function($element) {
+ return $element.val();
+ },
+ set: function($element, value) {
+ try {
+ if ($element.val() != value) $element.val(value);
+ } catch (error) {
+ // Error setting value: IGNORE.
+ // This occurs in IE6 while attempting to set an undefined multi-select option.
+ // unfortuantely, jQuery doesn't gracefully handle this error for us.
+ // remove this try/catch block when IE6 is officially deprecated.
+ }
+ }
+ })
+ };
+
+
+ // Binding Filters
+ // ---------------
+ // Filters are special binding handlers that may be invoked while binding;
+ // they will return a wrapper function used to modify how accessors are read.
+
+ // Partial application wrapper for creating binding filters:
+ function makeFilter(handler) {
+ return function() {
+ var params = arguments;
+ var read = isFunction(handler) ? handler : handler.get;
+ var write = handler.set;
+ return function(value) {
+ return isUndefined(value) ?
+ read.apply(this, _.map(params, readAccessor)) :
+ params[0]((write ? write : read).call(this, value));
+ };
+ };
+ }
+
+ var bindingFilters = {
+ // Positive collection assessment [read-only]:
+ // Tests if all of the provided accessors are truthy (and).
+ all: makeFilter(function() {
+ var params = arguments;
+ for (var i=0, len=params.length; i < len; i++) {
+ if (!params[i]) return false;
+ }
+ return true;
+ }),
+
+ // Partial collection assessment [read-only]:
+ // tests if any of the provided accessors are truthy (or).
+ any: makeFilter(function() {
+ var params = arguments;
+ for (var i=0, len=params.length; i < len; i++) {
+ if (params[i]) return true;
+ }
+ return false;
+ }),
+
+ // Collection length accessor [read-only]:
+ // assumes accessor value to be an Array or Collection; defaults to 0.
+ length: makeFilter(function(value) {
+ return value.length || 0;
+ }),
+
+ // Negative collection assessment [read-only]:
+ // tests if none of the provided accessors are truthy (and not).
+ none: makeFilter(function() {
+ var params = arguments;
+ for (var i=0, len=params.length; i < len; i++) {
+ if (params[i]) return false;
+ }
+ return true;
+ }),
+
+ // Negation [read-only]:
+ not: makeFilter(function(value) {
+ return !value;
+ }),
+
+ // Formats one or more accessors into a text string:
+ // ('$1 $2 did $3', firstName, lastName, action)
+ format: makeFilter(function(str) {
+ var params = arguments;
+
+ for (var i=1, len=params.length; i < len; i++) {
+ // TODO: need to make something like this work: (?View relationships will be baked at the time of applying bindings;
+ // changes in configuration to source attributes or view bindings will require a complete re-bind.
+ applyBindings: function() {
+ this.removeBindings();
+
+ var self = this;
+ var sources = _.clone(_.result(self, 'bindingSources'));
+ var declarations = self.bindings;
+ var options = self.setterOptions;
+ var handlers = _.clone(bindingHandlers);
+ var filters = _.clone(bindingFilters);
+ var context = self._c = {};
+
+ // Compile a complete set of binding handlers for the view:
+ // mixes all custom handlers into a copy of default handlers.
+ // Custom handlers defined as plain functions are registered as read-only setters.
+ _.each(_.result(self, 'bindingHandlers')||{}, function(handler, name) {
+ handlers[ name ] = makeHandler(handler);
+ });
+
+ // Compile a complete set of binding filters for the view:
+ // mixes all custom filters into a copy of default filters.
+ _.each(_.result(self, 'bindingFilters')||{}, function(filter, name) {
+ filters[ name ] = makeFilter(filter);
+ });
+
+ // Add native 'model' and 'collection' data sources:
+ self.model = addSourceToViewContext(self, context, options, 'model');
+ self.viewModel = addSourceToViewContext(self, context, options, 'viewModel');
+ self.collection = addSourceToViewContext(self, context, options, 'collection');
+
+ // Add all additional data sources:
+ if (sources) {
+ _.each(sources, function(source, sourceName) {
+ sources[ sourceName ] = addSourceToViewContext(sources, context, options, sourceName, sourceName);
+ });
+
+ // Reapply resulting sources to view instance.
+ self.bindingSources = sources;
+ }
+
+ // Add all computed view properties:
+ _.each(_.result(self, 'computeds')||{}, function(computed, name) {
+ var getter = isFunction(computed) ? computed : computed.get;
+ var setter = computed.set;
+ var deps = computed.deps;
+
+ context[ name ] = function(value) {
+ return (!isUndefined(value) && setter) ?
+ setter.call(self, value) :
+ getter.apply(self, getDepsFromViewContext(self._c, deps));
+ };
+ });
+
+ // Create all bindings:
+ // bindings are created from an object hash of query/binding declarations,
+ // OR based on queried DOM attributes.
+ if (isObject(declarations)) {
+
+ // Object declaration method:
+ // {'span.my-element': 'text:attribute'}
+
+ _.each(declarations, function(elementDecs, selector) {
+ // Get DOM jQuery reference:
+ var $element = queryViewForSelector(self, selector);
+
+ // Ignore empty DOM queries (without errors):
+ if ($element.length) {
+ bindElementToView(self, $element, elementDecs, context, handlers, filters);
+ }
+ });
+
+ } else {
+
+ // DOM attributes declaration method:
+ //
+
+ // Create bindings for each matched element:
+ queryViewForSelector(self, '['+declarations+']').each(function() {
+ var $element = Backbone.$(this);
+ bindElementToView(self, $element, $element.attr(declarations), context, handlers, filters);
+ });
+ }
+ },
+
+ // Gets a value from the binding context:
+ getBinding: function(attribute) {
+ return accessViewContext(this._c, attribute);
+ },
+
+ // Sets a value to the binding context:
+ setBinding: function(attribute, value) {
+ return accessViewContext(this._c, attribute, value);
+ },
+
+ // Disposes of all view bindings:
+ removeBindings: function() {
+ this._c = null;
+
+ if (this._b) {
+ while (this._b.length) {
+ this._b.pop().dispose();
+ }
+ }
+ },
+
+ // Backbone.View.remove() override:
+ // unbinds the view before performing native removal tasks.
+ remove: function() {
+ this.removeBindings();
+ viewSuper(this, 'remove', arguments);
+ }
+
+ }, mixins);
+
+ // Epoxy.View -> Private
+ // ---------------------
+
+ // Adds a data source to a view:
+ // Data sources are Backbone.Model and Backbone.Collection instances.
+ // @param source: a source instance, or a function that returns a source.
+ // @param context: the working binding context. All bindings in a view share a context.
+ function addSourceToViewContext(source, context, options, name, prefix) {
+
+ // Resolve source instance:
+ source = _.result(source, name);
+
+ // Ignore missing sources, and invoke non-instances:
+ if (!source) return;
+
+ // Add Backbone.Model source instance:
+ if (isModel(source)) {
+
+ // Establish source prefix:
+ prefix = prefix ? prefix+'_' : '';
+
+ // Create a read-only accessor for the model instance:
+ context['$'+name] = function() {
+ viewMap && viewMap.push([source, 'change']);
+ return source;
+ };
+
+ // Compile all model attributes as accessors within the context:
+ _.each(source.toJSON({computed:true}), function(value, attribute) {
+
+ // Create named accessor functions:
+ // -> Attributes from 'view.model' use their normal names.
+ // -> Attributes from additional sources are named as 'source_attribute'.
+ context[prefix+attribute] = function(value) {
+ return accessViewDataAttribute(source, attribute, value, options);
+ };
+ });
+ }
+ // Add Backbone.Collection source instance:
+ else if (isCollection(source)) {
+
+ // Create a read-only accessor for the collection instance:
+ context['$'+name] = function() {
+ viewMap && viewMap.push([source, 'reset add remove sort update']);
+ return source;
+ };
+ }
+
+ // Return original object, or newly constructed data source:
+ return source;
+ }
+
+ // Attribute data accessor:
+ // exchanges individual attribute values with model sources.
+ // This function is separated out from the accessor creation process for performance.
+ // @param source: the model data source to interact with.
+ // @param attribute: the model attribute to read/write.
+ // @param value: the value to set, or 'undefined' to get the current value.
+ function accessViewDataAttribute(source, attribute, value, options) {
+ // Register the attribute to the bindings map, if enabled:
+ viewMap && viewMap.push([source, 'change:'+attribute]);
+
+ // Set attribute value when accessor is invoked with an argument:
+ if (!isUndefined(value)) {
+
+ // Set Object (non-null, non-array) hashtable value:
+ if (!isObject(value) || isArray(value) || _.isDate(value)) {
+ var val = value;
+ value = {};
+ value[attribute] = val;
+ }
+
+ // Set value:
+ return options && options.save ? source.save(value, options) : source.set(value, options);
+ }
+
+ // Get the attribute value by default:
+ return source.get(attribute);
+ }
+
+ // Queries element selectors within a view:
+ // matches elements within the view, and the view's container element.
+ function queryViewForSelector(view, selector) {
+ if (selector === ':el') return view.$el;
+ var $elements = view.$(selector);
+
+ // Include top-level view in bindings search:
+ if (view.$el.is(selector)) {
+ $elements = $elements.add(view.$el);
+ }
+
+ return $elements;
+ }
+
+ // Binds an element into a view:
+ // The element's declarations are parsed, then a binding is created for each declared handler.
+ // @param view: the parent View to bind into.
+ // @param $element: the target element (as jQuery) to bind.
+ // @param declarations: the string of binding declarations provided for the element.
+ // @param context: a compiled binding context with all availabe view data.
+ // @param handlers: a compiled handlers table with all native/custom handlers.
+ function bindElementToView(view, $element, declarations, context, handlers, filters) {
+
+ // Parse localized binding context:
+ // parsing function is invoked with 'filters' and 'context' properties made available,
+ // yeilds a native context object with element-specific bindings defined.
+ try {
+ var parserFunct = bindingCache[declarations] || (bindingCache[declarations] = new Function('$f','$c','with($f){with($c){return{'+ declarations +'}}}'));
+ var bindings = parserFunct(filters, context);
+ } catch (error) {
+ throw('Error parsing bindings: "'+declarations +'"\n>> '+error);
+ }
+
+ // Format the 'events' option:
+ // include events from the binding declaration along with a default 'change' trigger,
+ // then format all event names with a '.epoxy' namespace.
+ var events = _.map(_.union(bindings.events || [], ['change']), function(name) {
+ return name+'.epoxy';
+ }).join(' ');
+
+ // Apply bindings from native context:
+ _.each(bindings, function(accessor, handlerName) {
+
+ // Validate that each defined handler method exists before binding:
+ if (handlers.hasOwnProperty(handlerName)) {
+ // Create and add binding to the view's list of handlers:
+ view.b().push(new EpoxyBinding($element, handlers[handlerName], accessor, events, context, bindings));
+ } else if (!allowedParams.hasOwnProperty(handlerName)) {
+ throw('binding handler "'+ handlerName +'" is not defined.');
+ }
+ });
+ }
+
+ // Gets and sets view context data attributes:
+ // used by the implementations of "getBinding" and "setBinding".
+ function accessViewContext(context, attribute, value) {
+ if (context && context.hasOwnProperty(attribute)) {
+ return isUndefined(value) ? readAccessor(context[attribute]) : context[attribute](value);
+ }
+ }
+
+ // Accesses an array of dependency properties from a view context:
+ // used for mapping view dependencies by manual declaration.
+ function getDepsFromViewContext(context, attributes) {
+ var values = [];
+ if (attributes && context) {
+ for (var i=0, len=attributes.length; i < len; i++) {
+ values.push(attributes[i] in context ? context[ attributes[i] ]() : null);
+ }
+ }
+ return values;
+ }
+
+
+ // Epoxy.View -> Binding
+ // ---------------------
+ // The binding object connects an element to a bound handler.
+ // @param $element: the target element (as jQuery) to bind.
+ // @param handler: the handler object to apply (include all handler methods).
+ // @param accessor: an accessor method from the binding context that exchanges data with the model.
+ // @param options: a compiled set of binding options that was pulled from the declaration.
+ function EpoxyBinding($element, handler, accessor, events, context, bindings) {
+
+ var self = this;
+ var tag = ($element[0].tagName).toLowerCase();
+ var changable = (tag == 'input' || tag == 'select' || tag == 'textarea' || $element.prop('contenteditable') == 'true');
+ var triggers = [];
+ var reset = function(target) {
+ self.set(self.$el, readAccessor(accessor), target);
+ };
+
+ self.$el = $element;
+ self.evt = events;
+ _.extend(self, handler);
+
+ // Initialize the binding:
+ // allow the initializer to redefine/modify the attribute accessor if needed.
+ accessor = self.init(self.$el, readAccessor(accessor), context, bindings) || accessor;
+
+ // Set default binding, then initialize & map bindings:
+ // each binding handler is invoked to populate its initial value.
+ // While running a handler, all accessed attributes will be added to the handler's dependency map.
+ viewMap = triggers;
+ reset();
+ viewMap = null;
+
+ // Configure READ/GET-able binding. Requires:
+ // => Form element.
+ // => Binding handler has a getter method.
+ // => Value accessor is a function.
+ if (changable && handler.get && isFunction(accessor)) {
+ self.$el.on(events, function(evt) {
+ accessor(self.get(self.$el, readAccessor(accessor), evt));
+ });
+ }
+
+ // Configure WRITE/SET-able binding. Requires:
+ // => One or more events triggers.
+ if (triggers.length) {
+ for (var i=0, len=triggers.length; i < len; i++) {
+ self.listenTo(triggers[i][0], triggers[i][1], reset);
+ }
+ }
+ }
+
+ _.extend(EpoxyBinding.prototype, Backbone.Events, {
+
+ // Pass-through binding methods:
+ // for override by actual implementations.
+ init: blankMethod,
+ get: blankMethod,
+ set: blankMethod,
+ clean: blankMethod,
+
+ // Destroys the binding:
+ // all events and managed sub-views are killed.
+ dispose: function() {
+ this.clean();
+ this.stopListening();
+ this.$el.off(this.evt);
+ this.$el = null;
+ }
+ });
+
+ return Epoxy;
+}));
diff --git a/www/js/backbone.epoxy.min.js b/www/js/backbone.epoxy.min.js
index f022a9a..19d1e74 100644
--- a/www/js/backbone.epoxy.min.js
+++ b/www/js/backbone.epoxy.min.js
@@ -1,6 +1,6 @@
-// Backbone.Epoxy 1.0.3
+// Backbone.Epoxy 1.0.5
// (c) 2013 Greg MacWilliam
// Freely distributed under the MIT license
// http://epoxyjs.org
-(function(t,e){"undefined"!=typeof exports?module.exports=e(require("underscore"),require("backbone")):"function"==typeof define&&define.amd?define(["underscore","backbone"],e):e(t._,t.Backbone)})(this,function(t,e){function n(t){return function(e,n,i){return t.prototype[n].apply(e,i)}}function i(e,n,r,o){for(var s in n)if(n.hasOwnProperty(s)){var u=n[s];if(e.hasComputed(s)){if(o.length&&!(0>t.indexOf(o,s)))throw"Recursive setter: "+o.join(" > ");u=e.c()[s].set(u),u&&w(u)&&(r=i(e,u,r,o.concat(s)))}else r[s]=u}return r}function r(e,n,i,r){i=i||{},i.get&&b(i.get)&&(i._get=i.get),i.set&&b(i.set)&&(i._set=i.set),delete i.get,delete i.set,t.extend(this,i),this.model=e,this.name=n,this.deps=this.deps||[],r||this.init()}function o(e){return b(e)?e():(w(e)&&(e=t.clone(e),t.each(e,function(t,n){e[n]=o(t)})),e)}function s(t){return b(t)?{set:t}:t}function u(e){return function(){var n=arguments,i=b(e)?e:e.get,r=e.set;return function(e){return y(e)?i.apply(this,t.map(n,o)):n[0]((r?r:i).call(this,e))}}}function c(e,n,i,r,o){return(e=t.result(e,r))?(x(e)?(o=o?o+"_":"",n["$"+r]=function(){return j&&j.push([e,"change"]),e},t.each(e.toJSON({computed:!0}),function(t,r){n[o+r]=function(t){return a(e,r,t,i)}})):C(e)&&(n["$"+r]=function(){return j&&j.push([e,"reset add remove sort update"]),e}),e):void 0}function a(e,n,i,r){if(j&&j.push([e,"change:"+n]),!y(i)){if(!w(i)||_(i)||t.isDate(i)){var o=i;i={},i[n]=o}return r&&r.save?e.save(i,r):e.set(i,r)}return e.get(n)}function h(t,e){if(":el"===e)return t.$el;var n=t.$(e);return t.$el.is(e)&&(n=n.add(t.$el)),n}function l(e,n,i,r,o,s){try{var u=F[i]||(F[i]=Function("$f","$c","with($f){with($c){return{"+i+"}}}")),c=u(s,r)}catch(a){throw'Error parsing bindings: "'+i+'"\n>> '+a}var h=t.map(t.union(c.events||[],["change"]),function(t){return t+".epoxy"}).join(" ");t.each(c,function(t,i){o.hasOwnProperty(i)&&e.b().push(new p(n,o[i],t,h,r,c))})}function f(t,e,n){return t&&t.hasOwnProperty(e)?y(n)?o(t[e]):t[e](n):void 0}function d(t,e){var n=[];if(e&&t)for(var i=0,r=e.length;r>i;i++)n.push(e[i]in t?t[e[i]]():null);return n}function p(e,n,i,r,s,u){var c=this,a=e[0].tagName.toLowerCase(),h="input"==a||"select"==a||"textarea"==a||"true"==e.prop("contenteditable"),l=[],f=function(t){c.set(c.$el,o(i),t)};if(c.$el=e,c.evt=r,t.extend(c,n),i=c.init(c.$el,o(i),s,u)||i,j=l,f(),j=null,h&&n.get&&b(i)&&c.$el.on(r,function(t){i(c.get(c.$el,o(i),t))}),l.length)for(var d=0,p=l.length;p>d;d++)c.listenTo(l[d][0],l[d][1],f)}var g,v=e.Epoxy={},m=Array.prototype,y=t.isUndefined,b=t.isFunction,w=t.isObject,_=t.isArray,x=function(t){return t instanceof e.Model},C=function(t){return t instanceof e.Collection},O=function(){},k={mixin:function(t){t=t||{};for(var e in this.prototype)this.prototype.hasOwnProperty(e)&&"constructor"!==e&&(t[e]=this.prototype[e]);return t}},B=n(e.Model),P=["computeds"];v.Model=e.Model.extend({constructor:function(e,n){t.extend(this,t.pick(n||{},P)),B(this,"constructor",arguments),this.initComputeds(e,n)},getCopy:function(e){return t.clone(this.get(e))},get:function(t){return g&&g.push(["change:"+t,this]),this.hasComputed(t)?this.c()[t].get():B(this,"get",arguments)},set:function(t,e,n){var r=t;return r&&!w(r)?(r={},r[t]=e):n=e,n=n||{},n.unset||(r=i(this,r,{},[])),B(this,"set",[r,n])},toJSON:function(e){var n=B(this,"toJSON",arguments);return e&&e.computed&&t.each(this.c(),function(t,e){n[e]=t.value}),n},destroy:function(){return this.clearComputeds(),B(this,"destroy",arguments)},c:function(){return this._c||(this._c={})},initComputeds:function(e){this.clearComputeds();var n=t.result(this,"computeds")||{};n=t.extend(n,t.pick(e||{},t.keys(n))),t.each(n,function(t,e){t._init=1,this.addComputed(e,t)},this),t.invoke(this.c(),"init")},addComputed:function(t,e,n){this.removeComputed(t);var i=e,o=i._init;if(b(e)){var s=2;i={},i._get=e,b(n)&&(i._set=n,s++),i.deps=m.slice.call(arguments,s)}return this.c()[t]=new r(this,t,i,o),this},hasComputed:function(t){return this.c().hasOwnProperty(t)},removeComputed:function(t){return this.hasComputed(t)&&(this.c()[t].dispose(),delete this.c()[t]),this},clearComputeds:function(){for(var t in this.c())this.removeComputed(t);return this},modifyArray:function(t,e){var n=this.get(t);if(_(n)&&b(m[e])){var i=m.slice.call(arguments,2),r=m[e].apply(n,i);return this.trigger("change change:"+t),r}return null},modifyObject:function(t,e,n){var i=this.get(t),r=!1;return w(i)?(y(n)&&i.hasOwnProperty(e)?(delete i[e],r=!0):i[e]!==n&&(i[e]=n,r=!0),r&&this.trigger("change change:"+t),i):null}},k),t.extend(r.prototype,e.Events,{init:function(){var e={},n=g=[];this.get(!0),g=null,n.length&&(t.each(n,function(n){var i=n[0],r=n[1];e[i]?t.contains(e[i],r)||e[i].push(r):e[i]=[r]}),t.each(e,function(e,n){for(var i=0,r=e.length;r>i;i++)this.listenTo(e[i],n,t.bind(this.get,this,!0))},this))},val:function(t){return this.model.get(t)},get:function(e){if(e===!0&&this._get){var n=this._get.apply(this.model,t.map(this.deps,this.val,this));this.change(n)}return this.value},set:function(t){if(this._get){if(this._set)return this._set.apply(this.model,arguments);throw"Cannot set read-only computed attribute."}return this.change(t),null},change:function(e){t.isEqual(e,this.value)||(this.value=e,this.model.trigger("change:"+this.name+" change",this.model))},dispose:function(){this.stopListening(),this.off(),this.model=this.value=null}});var E={optionText:"label",optionValue:"value"},F={},M={attr:s(function(t,e){t.attr(e)}),checked:s({get:function(e,n){var i=!!e.prop("checked"),r=e.val();if(this.isRadio(e))return r;if(_(n)){n=n.slice();var o=t.indexOf(n,r);return i&&0>o?n.push(r):!i&&o>-1&&n.splice(o,1),n}return i},set:function(e,n){var i=!!n;this.isRadio(e)?i=n==e.val():_(n)&&(i=t.contains(n,e.val())),e.prop("checked",i)},isRadio:function(t){return"radio"===t.attr("type").toLowerCase()}}),classes:s(function(e,n){t.each(n,function(t,n){e.toggleClass(n,!!t)})}),collection:s({init:function(t,e){if(!C(e)||!b(e.view))throw'Binding "collection" requires a Collection with a "view" constructor.';this.v={}},set:function(e,n,i){var r,o=this.v,s=n.models,u=j;if(j=null,i=i||n,x(i))if(o.hasOwnProperty(i.cid))o[i.cid].remove(),delete o[i.cid];else{o[i.cid]=r=new n.view({model:i});var c=t.indexOf(s,i),a=e.children();a.length>c?a.eq(c).before(r.$el):e.append(r.$el)}else if(C(i)){var h=s.length===t.size(o)&&n.every(function(t){return o.hasOwnProperty(t.cid)});e.children().detach();var l=document.createDocumentFragment();h?n.each(function(t){l.appendChild(o[t.cid].el)}):(this.clean(),n.each(function(t){o[t.cid]=r=new n.view({model:t}),l.appendChild(r.el)})),e.append(l)}j=u},clean:function(){for(var t in this.v)this.v.hasOwnProperty(t)&&(this.v[t].remove(),delete this.v[t])}}),css:s(function(t,e){t.css(e)}),disabled:s(function(t,e){t.prop("disabled",!!e)}),enabled:s(function(t,e){t.prop("disabled",!e)}),html:s(function(t,e){t.html(e)}),options:s({init:function(t,e,n,i){this.e=i.optionsEmpty,this.d=i.optionsDefault,this.v=i.value},set:function(e,n){var i=this,r=o(i.e),s=o(i.d),u=o(i.v),c=C(n)?n.models:n,a=c.length,h=!0,l="";a||s||!r?(s&&(c=[s].concat(c)),t.each(c,function(t){l+=i.opt(t,a)})):(l+=i.opt(r,a),h=!1),e.html(l).prop("disabled",!h).val(u);var f=e.val();i.v&&!t.isEqual(u,f)&&i.v(f)},opt:function(t){var e=t,n=t,i=E.optionText,r=E.optionValue;return w(t)&&(e=x(t)?t.get(i):t[i],n=x(t)?t.get(r):t[r]),['',e," "].join("")},clean:function(){this.d=this.e=this.v=0}}),template:s({init:function(e,n,i){var r=e.find("script,template");return this.t=t.template(r.length?r.html():e.html()),_(n)?t.pick(i,n):void 0},set:function(t,e){e=x(e)?e.toJSON({computed:!0}):e,t.html(this.t(e))},clean:function(){this.t=null}}),text:s(function(t,e){t.text(e)}),toggle:s(function(t,e){t.toggle(!!e)}),value:s({get:function(t){return t.val()},set:function(t,e){try{t.val()!=e&&t.val(e)}catch(n){}}})},S={all:u(function(){for(var t=arguments,e=0,n=t.length;n>e;e++)if(!t[e])return!1;return!0}),any:u(function(){for(var t=arguments,e=0,n=t.length;n>e;e++)if(t[e])return!0;return!1}),length:u(function(t){return t.length||0}),none:u(function(){for(var t=arguments,e=0,n=t.length;n>e;e++)if(t[e])return!1;return!0}),not:u(function(t){return!t}),format:u(function(t){for(var e=arguments,n=1,i=e.length;i>n;n++)t=t.replace(RegExp("\\$"+n,"g"),e[n]);return t}),select:u(function(t,e,n){return t?e:n}),csv:u({get:function(t){return t+="",t?t.split(","):[]},set:function(t){return _(t)?t.join(","):t}}),integer:u(function(t){return t?parseInt(t,10):0}),decimal:u(function(t){return t?parseFloat(t):0})};v.binding={addHandler:function(t,e){M[t]=s(e)},addFilter:function(t,e){S[t]=u(e)},config:function(e){t.extend(E,e)},emptyCache:function(){F={}}};var j,q=n(e.View),N=["viewModel","bindings","bindingFilters","bindingHandlers","bindingSources","computeds"];return v.View=e.View.extend({constructor:function(e){t.extend(this,t.pick(e||{},N)),q(this,"constructor",arguments),this.applyBindings()},b:function(){return this._b||(this._b=[])},bindings:"data-bind",setterOptions:null,applyBindings:function(){this.removeBindings();var e=this,n=t.clone(t.result(e,"bindingSources")),i=e.bindings,r=e.setterOptions,o=t.clone(M),a=t.clone(S),f=e._c={};t.each(t.result(e,"bindingHandlers")||{},function(t,e){o[e]=s(t)}),t.each(t.result(e,"bindingFilters")||{},function(t,e){a[e]=u(t)}),e.model=c(e,f,r,"model"),e.viewModel=c(e,f,r,"viewModel"),e.collection=c(e,f,r,"collection"),n&&(t.each(n,function(t,e){n[e]=c(n,f,r,e,e)}),e.bindingSources=n),t.each(t.result(e,"computeds")||{},function(t,n){var i=b(t)?t:t.get,r=t.set,o=t.deps;f[n]=function(t){return!y(t)&&r?r.call(e,t):i.apply(e,d(e._c,o))}}),w(i)?t.each(i,function(t,n){var i=h(e,n);i.length&&l(e,i,t,f,o,a)}):h(e,"["+i+"]").each(function(){var t=$(this);l(e,t,t.attr(i),f,o,a)})},getBinding:function(t){return f(this._c,t)},setBinding:function(t,e){return f(this._c,t,e)},removeBindings:function(){if(this._c=null,this._b)for(;this._b.length;)this._b.pop().dispose()},remove:function(){this.removeBindings(),q(this,"remove",arguments)}},k),t.extend(p.prototype,e.Events,{init:O,get:O,set:O,clean:O,dispose:function(){this.clean(),this.stopListening(),this.$el.off(this.evt),this.$el=null}}),v});
+(function(t,n){"undefined"!=typeof exports?module.exports=n(require("underscore"),require("backbone")):"function"==typeof define&&define.amd?define(["underscore","backbone"],n):n(t._,t.Backbone)})(this,function(t,n){function e(t){return function(n,e,i){return t.prototype[e].apply(n,i)}}function i(n,e,o,r){for(var s in e)if(e.hasOwnProperty(s)){var u=e[s];if(n.hasComputed(s)){if(r.length&&t.contains(r,s))throw"Recursive setter: "+r.join(" > ");u=n.c()[s].set(u),u&&w(u)&&(o=i(n,u,o,r.concat(s)))}else o[s]=u}return o}function o(n,e,i,o){i=i||{},i.get&&b(i.get)&&(i._get=i.get),i.set&&b(i.set)&&(i._set=i.set),delete i.get,delete i.set,t.extend(this,i),this.model=n,this.name=e,this.deps=this.deps||[],o||this.init()}function r(n){return b(n)?n():(w(n)&&(n=t.clone(n),t.each(n,function(t,e){n[e]=r(t)})),n)}function s(t){return b(t)?{set:t}:t}function u(n){return function(){var e=arguments,i=b(n)?n:n.get,o=n.set;return function(n){return y(n)?i.apply(this,t.map(e,r)):e[0]((o?o:i).call(this,n))}}}function c(n,e,i,o,r){return(n=t.result(n,o))?(C(n)?(r=r?r+"_":"",e["$"+o]=function(){return j&&j.push([n,"change"]),n},t.each(n.toJSON({computed:!0}),function(t,o){e[r+o]=function(t){return a(n,o,t,i)}})):x(n)&&(e["$"+o]=function(){return j&&j.push([n,"reset add remove sort update"]),n}),n):void 0}function a(n,e,i,o){if(j&&j.push([n,"change:"+e]),!y(i)){if(!w(i)||_(i)||t.isDate(i)){var r=i;i={},i[e]=r}return o&&o.save?n.save(i,o):n.set(i,o)}return n.get(e)}function h(t,n){if(":el"===n)return t.$el;var e=t.$(n);return t.$el.is(n)&&(e=e.add(t.$el)),e}function l(n,e,i,o,r,s){try{var u=E[i]||(E[i]=Function("$f","$c","with($f){with($c){return{"+i+"}}}")),c=u(s,o)}catch(a){throw'Error parsing bindings: "'+i+'"\n>> '+a}var h=t.map(t.union(c.events||[],["change"]),function(t){return t+".epoxy"}).join(" ");t.each(c,function(t,i){if(r.hasOwnProperty(i))n.b().push(new p(e,r[i],t,h,o,c));else if(!S.hasOwnProperty(i))throw'binding handler "'+i+'" is not defined.'})}function f(t,n,e){return t&&t.hasOwnProperty(n)?y(e)?r(t[n]):t[n](e):void 0}function d(t,n){var e=[];if(n&&t)for(var i=0,o=n.length;o>i;i++)e.push(n[i]in t?t[n[i]]():null);return e}function p(n,e,i,o,s,u){var c=this,a=n[0].tagName.toLowerCase(),h="input"==a||"select"==a||"textarea"==a||"true"==n.prop("contenteditable"),l=[],f=function(t){c.set(c.$el,r(i),t)};if(c.$el=n,c.evt=o,t.extend(c,e),i=c.init(c.$el,r(i),s,u)||i,j=l,f(),j=null,h&&e.get&&b(i)&&c.$el.on(o,function(t){i(c.get(c.$el,r(i),t))}),l.length)for(var d=0,p=l.length;p>d;d++)c.listenTo(l[d][0],l[d][1],f)}var g,v=n.Epoxy={},m=Array.prototype,y=t.isUndefined,b=t.isFunction,w=t.isObject,_=t.isArray,C=function(t){return t instanceof n.Model},x=function(t){return t instanceof n.Collection},$=function(){},O={mixin:function(t){t=t||{};for(var n in this.prototype)this.prototype.hasOwnProperty(n)&&"constructor"!==n&&(t[n]=this.prototype[n]);return t}},k=e(n.Model),P=["computeds"];v.Model=n.Model.extend({constructor:function(n,e){t.extend(this,t.pick(e||{},P)),k(this,"constructor",arguments),this.initComputeds(n,e)},getCopy:function(n){return t.clone(this.get(n))},get:function(t){return g&&g.push(["change:"+t,this]),this.hasComputed(t)?this.c()[t].get():k(this,"get",arguments)},set:function(t,n,e){var o=t;return o&&!w(o)?(o={},o[t]=n):e=n,e=e||{},e.unset||(o=i(this,o,{},[])),k(this,"set",[o,e])},toJSON:function(n){var e=k(this,"toJSON",arguments);return n&&n.computed&&t.each(this.c(),function(t,n){e[n]=t.value}),e},destroy:function(){return this.clearComputeds(),k(this,"destroy",arguments)},c:function(){return this._c||(this._c={})},initComputeds:function(n){this.clearComputeds();var e=t.result(this,"computeds")||{};e=t.extend(e,t.pick(n||{},t.keys(e))),t.each(e,function(t,n){t._init=1,this.addComputed(n,t)},this),t.invoke(this.c(),"init")},addComputed:function(t,n,e){this.removeComputed(t);var i=n,r=i._init;if(b(n)){var s=2;i={},i._get=n,b(e)&&(i._set=e,s++),i.deps=m.slice.call(arguments,s)}return this.c()[t]=new o(this,t,i,r),this},hasComputed:function(t){return this.c().hasOwnProperty(t)},removeComputed:function(t){return this.hasComputed(t)&&(this.c()[t].dispose(),delete this.c()[t]),this},clearComputeds:function(){for(var t in this.c())this.removeComputed(t);return this},modifyArray:function(t,n,e){var i=this.get(t);if(_(i)&&b(m[n])){var o=m.slice.call(arguments,2),r=m[n].apply(i,o);return e=e||{},e.silent||this.trigger("change:"+t+" change",this,m,e),r}return null},modifyObject:function(t,n,e,i){var o=this.get(t),r=!1;return w(o)?(i=i||{},y(e)&&o.hasOwnProperty(n)?(delete o[n],r=!0):o[n]!==e&&(o[n]=e,r=!0),r&&!i.silent&&this.trigger("change:"+t+" change",this,o,i),o):null}},O),t.extend(o.prototype,n.Events,{init:function(){var n={},e=g=[];this.get(!0),g=null,e.length&&(t.each(e,function(e){var i=e[0],o=e[1];n[i]?t.contains(n[i],o)||n[i].push(o):n[i]=[o]}),t.each(n,function(n,e){for(var i=0,o=n.length;o>i;i++)this.listenTo(n[i],e,t.bind(this.get,this,!0))},this))},val:function(t){return this.model.get(t)},get:function(n){if(n===!0&&this._get){var e=this._get.apply(this.model,t.map(this.deps,this.val,this));this.change(e)}return this.value},set:function(t){if(this._get){if(this._set)return this._set.apply(this.model,arguments);throw"Cannot set read-only computed attribute."}return this.change(t),null},change:function(n){t.isEqual(n,this.value)||(this.value=n,this.model.trigger("change:"+this.name+" change",this.model))},dispose:function(){this.stopListening(),this.off(),this.model=this.value=null}});var B={optionText:"label",optionValue:"value"},E={},F={attr:s(function(t,n){t.attr(n)}),checked:s({get:function(n,e){var i=!!n.prop("checked"),o=n.val();if(this.isRadio(n))return o;if(_(e)){e=e.slice();var r=t.indexOf(e,o);return i&&0>r?e.push(o):!i&&r>-1&&e.splice(r,1),e}return i},set:function(n,e){var i=!!e;this.isRadio(n)?i=e==n.val():_(e)&&(i=t.contains(e,n.val())),n.prop("checked",i)},isRadio:function(t){return"radio"===t.attr("type").toLowerCase()}}),classes:s(function(n,e){t.each(e,function(t,e){n.toggleClass(e,!!t)})}),collection:s({init:function(t,n){if(!x(n)||!b(n.view))throw'Binding "collection" requires a Collection with a "view" constructor.';this.v={}},set:function(n,e,i){var o,r=this.v,s=e.models,u=j;if(j=null,i=i||e,C(i))if(r.hasOwnProperty(i.cid))r[i.cid].remove(),delete r[i.cid];else{r[i.cid]=o=new e.view({model:i});var c=t.indexOf(s,i),a=n.children();a.length>c?a.eq(c).before(o.$el):n.append(o.$el)}else if(x(i)){var h=s.length===t.size(r)&&e.every(function(t){return r.hasOwnProperty(t.cid)});n.children().detach();var l=document.createDocumentFragment();h?e.each(function(t){l.appendChild(r[t.cid].el)}):(this.clean(),e.each(function(t){r[t.cid]=o=new e.view({model:t}),l.appendChild(o.el)})),n.append(l)}j=u},clean:function(){for(var t in this.v)this.v.hasOwnProperty(t)&&(this.v[t].remove(),delete this.v[t])}}),css:s(function(t,n){t.css(n)}),disabled:s(function(t,n){t.prop("disabled",!!n)}),enabled:s(function(t,n){t.prop("disabled",!n)}),html:s(function(t,n){t.html(n)}),options:s({init:function(t,n,e,i){this.e=i.optionsEmpty,this.d=i.optionsDefault,this.v=i.value},set:function(n,e){var i=this,o=r(i.e),s=r(i.d),u=r(i.v),c=x(e)?e.models:e,a=c.length,h=!0,l="";a||s||!o?(s&&(c=[s].concat(c)),t.each(c,function(t){l+=i.opt(t,a)})):(l+=i.opt(o,a),h=!1),n.html(l).prop("disabled",!h).val(u);var f=n.val();i.v&&!t.isEqual(u,f)&&i.v(f)},opt:function(t){var n=t,e=t,i=B.optionText,o=B.optionValue;return w(t)&&(n=C(t)?t.get(i):t[i],e=C(t)?t.get(o):t[o]),['',n," "].join("")},clean:function(){this.d=this.e=this.v=0}}),template:s({init:function(n,e,i){var o=n.find("script,template");return this.t=t.template(o.length?o.html():n.html()),_(e)?t.pick(i,e):void 0},set:function(t,n){n=C(n)?n.toJSON({computed:!0}):n,t.html(this.t(n))},clean:function(){this.t=null}}),text:s(function(t,n){t.text(n)}),toggle:s(function(t,n){t.toggle(!!n)}),value:s({get:function(t){return t.val()},set:function(t,n){try{t.val()!=n&&t.val(n)}catch(e){}}})},M={all:u(function(){for(var t=arguments,n=0,e=t.length;e>n;n++)if(!t[n])return!1;return!0}),any:u(function(){for(var t=arguments,n=0,e=t.length;e>n;n++)if(t[n])return!0;return!1}),length:u(function(t){return t.length||0}),none:u(function(){for(var t=arguments,n=0,e=t.length;e>n;n++)if(t[n])return!1;return!0}),not:u(function(t){return!t}),format:u(function(t){for(var n=arguments,e=1,i=n.length;i>e;e++)t=t.replace(RegExp("\\$"+e,"g"),n[e]);return t}),select:u(function(t,n,e){return t?n:e}),csv:u({get:function(t){return t+="",t?t.split(","):[]},set:function(t){return _(t)?t.join(","):t}}),integer:u(function(t){return t?parseInt(t,10):0}),decimal:u(function(t){return t?parseFloat(t):0})},S={events:1,optionsDefault:1,optionsEmpty:1};v.binding={allowedParams:S,addHandler:function(t,n){F[t]=s(n)},addFilter:function(t,n){M[t]=u(n)},config:function(n){t.extend(B,n)},emptyCache:function(){E={}}};var j,q=e(n.View),N=["viewModel","bindings","bindingFilters","bindingHandlers","bindingSources","computeds"];return v.View=n.View.extend({constructor:function(n){t.extend(this,t.pick(n||{},N)),q(this,"constructor",arguments),this.applyBindings()},b:function(){return this._b||(this._b=[])},bindings:"data-bind",setterOptions:null,applyBindings:function(){this.removeBindings();var e=this,i=t.clone(t.result(e,"bindingSources")),o=e.bindings,r=e.setterOptions,a=t.clone(F),f=t.clone(M),p=e._c={};t.each(t.result(e,"bindingHandlers")||{},function(t,n){a[n]=s(t)}),t.each(t.result(e,"bindingFilters")||{},function(t,n){f[n]=u(t)}),e.model=c(e,p,r,"model"),e.viewModel=c(e,p,r,"viewModel"),e.collection=c(e,p,r,"collection"),i&&(t.each(i,function(t,n){i[n]=c(i,p,r,n,n)}),e.bindingSources=i),t.each(t.result(e,"computeds")||{},function(t,n){var i=b(t)?t:t.get,o=t.set,r=t.deps;p[n]=function(t){return!y(t)&&o?o.call(e,t):i.apply(e,d(e._c,r))}}),w(o)?t.each(o,function(t,n){var i=h(e,n);i.length&&l(e,i,t,p,a,f)}):h(e,"["+o+"]").each(function(){var t=n.$(this);l(e,t,t.attr(o),p,a,f)})},getBinding:function(t){return f(this._c,t)},setBinding:function(t,n){return f(this._c,t,n)},removeBindings:function(){if(this._c=null,this._b)for(;this._b.length;)this._b.pop().dispose()},remove:function(){this.removeBindings(),q(this,"remove",arguments)}},O),t.extend(p.prototype,n.Events,{init:$,get:$,set:$,clean:$,dispose:function(){this.clean(),this.stopListening(),this.$el.off(this.evt),this.$el=null}}),v});
//@ sourceMappingURL=backbone.epoxy.min.map
\ No newline at end of file
diff --git a/www/js/backbone.epoxy.min.map b/www/js/backbone.epoxy.min.map
index c5cae99..e36bc94 100644
--- a/www/js/backbone.epoxy.min.map
+++ b/www/js/backbone.epoxy.min.map
@@ -1 +1 @@
-{"version":3,"file":"backbone.epoxy.min.js","sources":["backbone.epoxy.js"],"names":["root","factory","exports","module","require","define","amd","_","Backbone","this","superClass","sup","instance","method","args","prototype","apply","deepModelSet","model","toSet","toReturn","stack","attribute","hasOwnProperty","value","hasComputed","length","indexOf","join","c","set","isObject","concat","EpoxyComputedModel","name","params","delayInit","get","isFunction","_get","_set","extend","deps","init","readAccessor","accessor","clone","each","key","makeHandler","handler","makeFilter","arguments","read","write","isUndefined","map","call","addSourceToViewContext","source","context","options","prefix","result","isModel","viewMap","push","toJSON","computed","accessViewDataAttribute","isCollection","isArray","isDate","val","save","queryViewForSelector","view","selector","$el","$elements","$","is","add","bindElementToView","$element","declarations","handlers","filters","parserFunct","bindingCache","Function","bindings","error","events","union","handlerName","b","EpoxyBinding","accessViewContext","getDepsFromViewContext","attributes","values","i","len","self","tag","toLowerCase","changable","prop","triggers","reset","target","evt","on","listenTo","modelMap","Epoxy","array","Array","obj","Model","Collection","blankMethod","mixins","mixin","modelSuper","modelProps","constructor","pick","initComputeds","getCopy","unset","json","destroy","clearComputeds","_c","computeds","keys","_init","addComputed","invoke","getter","setter","removeComputed","depsIndex","slice","dispose","modifyArray","trigger","modifyObject","property","change","Events","contains","targets","binding","bind","update","isEqual","stopListening","off","bindingSettings","optionText","optionValue","bindingHandlers","attr","checked","currentValue","isRadio","index","splice","classes","enabled","className","toggleClass","collection","v","views","models","mapCache","cid","remove","$children","children","eq","before","append","sort","size","every","detach","frag","document","createDocumentFragment","appendChild","el","clean","id","css","disabled","html","e","optionsEmpty","d","optionsDefault","numOptions","option","opt","revisedValue","label","textAttr","valueAttr","template","raw","find","t","text","toggle","bindingFilters","all","any","none","not","format","str","replace","RegExp","select","condition","truthy","falsey","csv","String","split","integer","parseInt","decimal","parseFloat","addHandler","addFilter","config","settings","emptyCache","viewSuper","View","viewProps","applyBindings","_b","setterOptions","removeBindings","sources","filter","viewModel","sourceName","bindingSources","elementDecs","getBinding","setBinding","pop"],"mappings":"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","sourceRoot":"./"}
\ No newline at end of file
+{"version":3,"file":"backbone.epoxy.min.js","sources":["backbone.epoxy.js"],"names":["root","factory","exports","module","require","define","amd","_","Backbone","this","superClass","sup","instance","method","args","prototype","apply","deepModelSet","model","toSet","toReturn","stack","attribute","hasOwnProperty","value","hasComputed","length","contains","join","c","set","isObject","concat","EpoxyComputedModel","name","params","delayInit","get","isFunction","_get","_set","extend","deps","init","readAccessor","accessor","clone","each","key","makeHandler","handler","makeFilter","arguments","read","write","isUndefined","map","call","addSourceToViewContext","source","context","options","prefix","result","isModel","viewMap","push","toJSON","computed","accessViewDataAttribute","isCollection","isArray","isDate","val","save","queryViewForSelector","view","selector","$el","$elements","$","is","add","bindElementToView","$element","declarations","handlers","filters","parserFunct","bindingCache","Function","bindings","error","events","union","handlerName","b","EpoxyBinding","allowedParams","accessViewContext","getDepsFromViewContext","attributes","values","i","len","self","tag","toLowerCase","changable","prop","triggers","reset","target","evt","on","listenTo","modelMap","Epoxy","array","Array","obj","Model","Collection","blankMethod","mixins","mixin","modelSuper","modelProps","constructor","pick","initComputeds","getCopy","unset","json","destroy","clearComputeds","_c","computeds","keys","_init","addComputed","invoke","getter","setter","removeComputed","depsIndex","slice","dispose","modifyArray","silent","trigger","modifyObject","property","change","Events","targets","binding","bind","update","isEqual","stopListening","off","bindingSettings","optionText","optionValue","bindingHandlers","attr","checked","currentValue","isRadio","index","indexOf","splice","classes","enabled","className","toggleClass","collection","v","views","models","mapCache","cid","remove","$children","children","eq","before","append","sort","size","every","detach","frag","document","createDocumentFragment","appendChild","el","clean","id","css","disabled","html","e","optionsEmpty","d","optionsDefault","numOptions","option","opt","revisedValue","label","textAttr","valueAttr","template","raw","find","t","text","toggle","bindingFilters","all","any","none","not","format","str","replace","RegExp","select","condition","truthy","falsey","csv","String","split","integer","parseInt","decimal","parseFloat","addHandler","addFilter","config","settings","emptyCache","viewSuper","View","viewProps","applyBindings","_b","setterOptions","removeBindings","sources","filter","viewModel","sourceName","bindingSources","elementDecs","getBinding","setBinding","pop"],"mappings":"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","sourceRoot":"./"}
\ No newline at end of file
diff --git a/www/tutorials.html b/www/tutorials.html
index 5bb4f9c..783fdd9 100644
--- a/www/tutorials.html
+++ b/www/tutorials.html
@@ -33,7 +33,7 @@
Epoxy .js Elegant Data Binding for Backbone