Todo exampleAmends made due to new lib api.# Please enter the commit message for your changes. Lines starting# with '#' will be ignored, and an empty message aborts the commit.# On branch master# Your branch is ahead of 'origin/master' by 1 commit.#   (use "git push" to publish your local commits)## Changes to be committed:#   (use "git reset HEAD <file>..." to unstage)##	modified:   Truss.js#	modified:   examples/todo/public/javascripts/Truss.js#	modified:   examples/todo/public/javascripts/bootstrap.js#	modified:   examples/todo/public/javascripts/views/Notes.View.Count.js#	modified:   examples/todo/public/javascripts/views/Notes.View.Edit_Note.js#	modified:   examples/todo/public/javascripts/views/Notes.View.Form.js#	modified:   examples/todo/public/javascripts/views/Notes.View.List.js#	modified:   examples/todo/public/javascripts/views/Notes.View.Note.js## Changes not staged for commit:#   (use "git add <file>..." to update what will be committed)#   (use "git checkout -- <file>..." to discard changes in working directory)##	modified:   Gruntfile.js#	modified:   Truss-min.js#	modified:   spec/View.spec.js#	modified:   src/View.js## Untracked files:#   (use "git add <file>..." to include in what will be committed)##	Truss.js,examples/diff --git Truss.js Truss.jsindex 54895fd..703ab81 100644--- Truss.js+++ Truss.js@@ -737,7 +737,7 @@ define ('Collection', ['Base', 'Model'], function ( Base, Model ) { });-define ('View',['Base'], function ( Base ) {    var TAGNAME = 'div';    function getRootNode () {        return document.getElementsByTagName("body")[0];    }    // Build the constructor    return Base.construct({        tagName: 'div',        start: function () {            this.tagName = this.options && this.options.tagName ? this.options.tagName : this.tagName;        },        setElement: function (element) {            this.element = element;        },        removeElement: function () {            if (arguments[0] && arguments[0].nodeType === 1) {                this.setElement(arguments[0]);            }            if (this.element.parentNode) {                this.element.parentNode.removeChild(this.element);            }            this.element = null;            delete this.element;        },        replaceElement: function (replacement) {            var replacee = this.element;            if (arguments[1] && arguments[1].nodeType === 1) {                replacee = arguments[1];            }            if (replacee && replacee.parentNode) {                this.oldElement = replacee.parentNode.replaceChild(replacement, replacee);            }        },        make: function () {            // All arguments are optional            var args = [].slice.call(arguments),                name = args[0] || this.tagName,                contents = args[1],                attrs = args[2],                i,                attr,                tag = document.createElement(name);            if (args.length === 2 && this.isObject(contents)) {                contents = undefined;                attrs = args[1];            }            // Add the contents            if (typeof contents !== "undefined") {                if (this.isNumber(contents) || this.isString(contents)) {                    // If the contents is a Number or a String,                    // parse it to a textnode                    contents = document.createTextNode(contents);                }                if (this.isArray(contents)) {                    // If our contents is an array,                    // append each one to the tag                    while ( i = contents.shift() ) {                        tag.appendChild(i);                    }                } else {                    tag.appendChild(contents);                }            }            // Add the attributes            if ( attrs ) {                for ( attr in attrs ) {                    if (attrs.hasOwnProperty( attr )) {                        // Add each attribute to the tag                        tag[ attr ] = attrs[ attr ];                        if ( !( attr in tag.attributes ) ) {                            // If the attribute wasnt't successfully added,                            // try again with setAttribute                            tag.setAttribute( attr, attrs[ attr ] );                        }                    }                }            }            // Finally return the new tag            return tag;        }    });});+define ('View',['Base'], function ( Base ) {    var TAGNAME = 'div';    // Build the constructor    return Base.construct({        tagName: 'div',        start: function () {            this.tagName = this.options && this.options.tagName ? this.options.tagName : this.tagName;        },        setElement: function (element) {            this.element = element;        },        removeElement: function () {            if (arguments[0] && arguments[0].nodeType === 1) {                this.setElement(arguments[0]);            }            if (this.element.parentNode) {                this.element.parentNode.removeChild(this.element);            }            this.stopListening();            this.element = null;            delete this.element;        },        destroy: function () {            if (this.model && this.collection) {                this.collection.removeById(this.model.get("id"));            }            this.removeElement();        },        replaceElement: function (replacement) {            var replacee = this.element;            if (arguments[1] && arguments[1].nodeType === 1) {                replacee = arguments[1];            }            if (replacee && replacee.parentNode) {                this.oldElement = replacee.parentNode.replaceChild(replacement, replacee);            }        },        addListener: function (eventName, handler) {            var el = arguments[2] && arguments[2].nodeType === 1 ? arguments[2] : this.element;            if (el.addEventListener) {                var evt = eventName.type || eventName;                el.addEventListener(evt, function (e) {                    if (eventName.key && (eventName.key == e.keyCode)) {                        handler(e);                    } else if (!eventName.key) {                        handler(e);                    }                });            }        },        stopListening: function () {            this.element.removeEventListener('*');        },        make: function () {            // All arguments are optional            var args = [].slice.call(arguments),                name = args[0] || this.tagName,                contents = args[1],                attrs = args[2],                i,                attr,                tag = document.createElement(name);            if (args.length === 2 && this.isObject(contents)) {                contents = undefined;                attrs = args[1];            }            // Add the contents            if (typeof contents !== "undefined") {                if (this.isNumber(contents) || this.isString(contents)) {                    // If the contents is a Number or a String,                    // parse it to a textnode                    contents = document.createTextNode(contents);                }                if (this.isArray(contents)) {                    // If our contents is an array,                    // append each one to the tag                    while ( i = contents.shift() ) {                        tag.appendChild(i);                    }                } else {                    tag.appendChild(contents);                }            }            // Add the attributes            if ( attrs ) {                for ( attr in attrs ) {                    if (attrs.hasOwnProperty( attr )) {                        // Add each attribute to the tag                        tag[ attr ] = attrs[ attr ];                        if ( !( attr in tag.attributes ) ) {                            // If the attribute wasnt't successfully added,                            // try again with setAttribute                            tag.setAttribute( attr, attrs[ attr ] );                        }                    }                }            }            // Finally return the new tag            return tag;        }    });}); define('main', [     'Base',     'events',diff --git examples/todo/public/javascripts/Truss.js examples/todo/public/javascripts/Truss.jsindex b910086..703ab81 100644--- examples/todo/public/javascripts/Truss.js+++ examples/todo/public/javascripts/Truss.js@@ -1 +1,773 @@-(function(global, define) {  var globalDefine = global.define;/** * almond 0.2.5 Copyright (c) 2011-2012, The Dojo Foundation All Rights Reserved. * Available via the MIT or new BSD license. * see: http://github.com/jrburke/almond for details *///Going sloppy to avoid 'use strict' string cost, but strict practices should//be followed./*jslint sloppy: true *//*global setTimeout: false */var requirejs, require, define;(function (undef) {    var main, req, makeMap, handlers,        defined = {},        waiting = {},        config = {},        defining = {},        hasOwn = Object.prototype.hasOwnProperty,        aps = [].slice;    function hasProp(obj, prop) {        return hasOwn.call(obj, prop);    }    /**     * Given a relative module name, like ./something, normalize it to     * a real name that can be mapped to a path.     * @param {String} name the relative name     * @param {String} baseName a real name that the name arg is relative     * to.     * @returns {String} normalized name     */    function normalize(name, baseName) {        var nameParts, nameSegment, mapValue, foundMap,            foundI, foundStarMap, starI, i, j, part,            baseParts = baseName && baseName.split("/"),            map = config.map,            starMap = (map && map['*']) || {};        //Adjust any relative paths.        if (name && name.charAt(0) === ".") {            //If have a base name, try to normalize against it,            //otherwise, assume it is a top-level require that will            //be relative to baseUrl in the end.            if (baseName) {                //Convert baseName to array, and lop off the last part,                //so that . matches that "directory" and not name of the baseName's                //module. For instance, baseName of "one/two/three", maps to                //"one/two/three.js", but we want the directory, "one/two" for                //this normalization.                baseParts = baseParts.slice(0, baseParts.length - 1);                name = baseParts.concat(name.split("/"));                //start trimDots                for (i = 0; i < name.length; i += 1) {                    part = name[i];                    if (part === ".") {                        name.splice(i, 1);                        i -= 1;                    } else if (part === "..") {                        if (i === 1 && (name[2] === '..' || name[0] === '..')) {                            //End of the line. Keep at least one non-dot                            //path segment at the front so it can be mapped                            //correctly to disk. Otherwise, there is likely                            //no path mapping for a path starting with '..'.                            //This can still fail, but catches the most reasonable                            //uses of ..                            break;                        } else if (i > 0) {                            name.splice(i - 1, 2);                            i -= 2;                        }                    }                }                //end trimDots                name = name.join("/");            } else if (name.indexOf('./') === 0) {                // No baseName, so this is ID is resolved relative                // to baseUrl, pull off the leading dot.                name = name.substring(2);            }        }        //Apply map config if available.        if ((baseParts || starMap) && map) {            nameParts = name.split('/');            for (i = nameParts.length; i > 0; i -= 1) {                nameSegment = nameParts.slice(0, i).join("/");                if (baseParts) {                    //Find the longest baseName segment match in the config.                    //So, do joins on the biggest to smallest lengths of baseParts.                    for (j = baseParts.length; j > 0; j -= 1) {                        mapValue = map[baseParts.slice(0, j).join('/')];                        //baseName segment has  config, find if it has one for                        //this name.                        if (mapValue) {                            mapValue = mapValue[nameSegment];                            if (mapValue) {                                //Match, update name to the new value.                                foundMap = mapValue;                                foundI = i;                                break;                            }                        }                    }                }                if (foundMap) {                    break;                }                //Check for a star map match, but just hold on to it,                //if there is a shorter segment match later in a matching                //config, then favor over this star map.                if (!foundStarMap && starMap && starMap[nameSegment]) {                    foundStarMap = starMap[nameSegment];                    starI = i;                }            }            if (!foundMap && foundStarMap) {                foundMap = foundStarMap;                foundI = starI;            }            if (foundMap) {                nameParts.splice(0, foundI, foundMap);                name = nameParts.join('/');            }        }        return name;    }    function makeRequire(relName, forceSync) {        return function () {            //A version of a require function that passes a moduleName            //value for items that may need to            //look up paths relative to the moduleName            return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync]));        };    }    function makeNormalize(relName) {        return function (name) {            return normalize(name, relName);        };    }    function makeLoad(depName) {        return function (value) {            defined[depName] = value;        };    }    function callDep(name) {        if (hasProp(waiting, name)) {            var args = waiting[name];            delete waiting[name];            defining[name] = true;            main.apply(undef, args);        }        if (!hasProp(defined, name) && !hasProp(defining, name)) {            throw new Error('No ' + name);        }        return defined[name];    }    //Turns a plugin!resource to [plugin, resource]    //with the plugin being undefined if the name    //did not have a plugin prefix.    function splitPrefix(name) {        var prefix,            index = name ? name.indexOf('!') : -1;        if (index > -1) {            prefix = name.substring(0, index);            name = name.substring(index + 1, name.length);        }        return [prefix, name];    }    /**     * Makes a name map, normalizing the name, and using a plugin     * for normalization if necessary. Grabs a ref to plugin     * too, as an optimization.     */    makeMap = function (name, relName) {        var plugin,            parts = splitPrefix(name),            prefix = parts[0];        name = parts[1];        if (prefix) {            prefix = normalize(prefix, relName);            plugin = callDep(prefix);        }        //Normalize according        if (prefix) {            if (plugin && plugin.normalize) {                name = plugin.normalize(name, makeNormalize(relName));            } else {                name = normalize(name, relName);            }        } else {            name = normalize(name, relName);            parts = splitPrefix(name);            prefix = parts[0];            name = parts[1];            if (prefix) {                plugin = callDep(prefix);            }        }        //Using ridiculous property names for space reasons        return {            f: prefix ? prefix + '!' + name : name, //fullName            n: name,            pr: prefix,            p: plugin        };    };    function makeConfig(name) {        return function () {            return (config && config.config && config.config[name]) || {};        };    }    handlers = {        require: function (name) {            return makeRequire(name);        },        exports: function (name) {            var e = defined[name];            if (typeof e !== 'undefined') {                return e;            } else {                return (defined[name] = {});            }        },        module: function (name) {            return {                id: name,                uri: '',                exports: defined[name],                config: makeConfig(name)            };        }    };    main = function (name, deps, callback, relName) {        var cjsModule, depName, ret, map, i,            args = [],            usingExports;        //Use name if no relName        relName = relName || name;        //Call the callback to define the module, if necessary.        if (typeof callback === 'function') {            //Pull out the defined dependencies and pass the ordered            //values to the callback.            //Default to [require, exports, module] if no deps            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;            for (i = 0; i < deps.length; i += 1) {                map = makeMap(deps[i], relName);                depName = map.f;                //Fast path CommonJS standard dependencies.                if (depName === "require") {                    args[i] = handlers.require(name);                } else if (depName === "exports") {                    //CommonJS module spec 1.1                    args[i] = handlers.exports(name);                    usingExports = true;                } else if (depName === "module") {                    //CommonJS module spec 1.1                    cjsModule = args[i] = handlers.module(name);                } else if (hasProp(defined, depName) ||                           hasProp(waiting, depName) ||                           hasProp(defining, depName)) {                    args[i] = callDep(depName);                } else if (map.p) {                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});                    args[i] = defined[depName];                } else {                    throw new Error(name + ' missing ' + depName);                }            }            ret = callback.apply(defined[name], args);            if (name) {                //If setting exports via "module" is in play,                //favor that over return value and exports. After that,                //favor a non-undefined return value over exports use.                if (cjsModule && cjsModule.exports !== undef &&                        cjsModule.exports !== defined[name]) {                    defined[name] = cjsModule.exports;                } else if (ret !== undef || !usingExports) {                    //Use the return value from the function.                    defined[name] = ret;                }            }        } else if (name) {            //May just be an object definition for the module. Only            //worry about defining if have a module name.            defined[name] = callback;        }    };    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {        if (typeof deps === "string") {            if (handlers[deps]) {                //callback in this case is really relName                return handlers[deps](callback);            }            //Just return the module wanted. In this scenario, the            //deps arg is the module name, and second arg (if passed)            //is just the relName.            //Normalize module name, if it contains . or ..            return callDep(makeMap(deps, callback).f);        } else if (!deps.splice) {            //deps is a config object, not an array.            config = deps;            if (callback.splice) {                //callback is an array, which means it is a dependency list.                //Adjust args if there are dependencies                deps = callback;                callback = relName;                relName = null;            } else {                deps = undef;            }        }        //Support require(['a'])        callback = callback || function () {};        //If relName is a function, it is an errback handler,        //so remove it.        if (typeof relName === 'function') {            relName = forceSync;            forceSync = alt;        }        //Simulate async callback;        if (forceSync) {            main(undef, deps, callback, relName);        } else {            //Using a non-zero value because of concern for what old browsers            //do, and latest browsers "upgrade" to 4 if lower value is used:            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:            //If want a value immediately, use require('id') instead -- something            //that works in almond on the global level, but not guaranteed and            //unlikely to work in other AMD implementations.            setTimeout(function () {                main(undef, deps, callback, relName);            }, 4);        }        return req;    };    /**     * Just drops the config on the floor, but returns req in case     * the config return value is used.     */    req.config = function (cfg) {        config = cfg;        if (config.deps) {            req(config.deps, config.callback);        }        return req;    };    define = function (name, deps, callback) {        //This module may not have dependencies        if (!deps.splice) {            //deps is not an array, so probably means            //an object literal or factory function for            //the value. Adjust args.            callback = deps;            deps = [];        }        if (!hasProp(defined, name) && !hasProp(waiting, name)) {            waiting[name] = [name, deps, callback];        }    };    define.amd = {        jQuery: true    };}());define("vendor/almond", function(){});define ('events',[], function ( ) {  return {    events: {},    on: function (event, callback) {      var context;      if ( "string" != typeof event ) {        throw new Error("on() needs an event name string");      }      if ( "function" != typeof callback ) {        throw new Error("on() needs a callback function");      }      context = [].slice.call( arguments, 2 )[0];      if ( !this.events[event] ) {        this.events[event] = [];      }      this.events[event].push({        callback: callback,        context: context      });    },    reset: function () {      this.events = {};    },    off: function (event) {      var ev, len, cb;      // Event must be a string      if ( "string" != typeof event ) {        throw new Error( "off() needs an event" );      }      cb = [].slice.call( arguments, 1 )[0];      // If the event has been registered      if ( this.events[event] ) {        ev = this.events[event];        len = ev.length;        // Loop over each event object that matches ours.        while ( len-- ) {          if ( "function" != typeof cb ) {            // If no callback was given, remove the event            // and all its callbacks            ev.splice(len, 1);          } else {            // If a callback was passed,            // remove the callback from the event            if ( ev[len].callback === cb ) {              ev[len].callback = null;              delete ev[len].callback;            }          }        }      }    },    fire: function ( event ) {      var ev, len, opt, data, ctx;      // event argument is mandatory      if ( "string" != typeof event ) {        throw new Error("fire() needs an event");      }      // Optional arguments      opt = [].slice.call( arguments, 1 );      data = opt[0];      ctx = opt[1];      // If this event has been registered      if ( this.events[event] ) {        len = this.events[event].length;        // Invoke the callback on each event object        while ( ev = this.events[event][--len] ) {          if ("function" == typeof ev.callback) {            // Invoke in either context with data if present            ev.callback.call( ( ctx || ev.context || this ), data );          }        }      }    }  };});define('utils',[], function ( ) {  return {    realTypeOf: function ( value ) {      // Borrow Object.toString to introspect the      // class definition of the value i.e. ([object Object])      // and return the latter portion which denotes      // the real type of value.      return ({}).toString.call(value).match( /\w+/g )[1].toLowerCase();    },    isObject: function ( value ) {      //delegate to realTypeOf      return this.realTypeOf(value) === 'object';    },    isArray: function ( value ) {      if (Array.isArray) {        return Array.isArray(value);      }      //delegate to realTypeOf if isArray is not supported      return this.realTypeOf(value) === 'array';    },    isString: function ( value ) {      //delegate to realTypeOf      return this.realTypeOf(value) === 'string';    },    isNumber: function ( value ) {      //delegate to realTypeOf      return this.realTypeOf(value) === 'number';    },    isFunction: function ( value ) {      //delegate to realTypeOf      return this.realTypeOf(value) === 'function';    }  };});define('Base', ['events', 'utils'], function ( events, utils ) {  /**   * @constructor   * @description   * -> Core of Base framework   * @param {Object} options   * @return {this}   */  var Base = function ( options ) {    if ( "undefined" != typeof options ) {        this.options = options;        Base.mixin(this, options);    }    // Call the start function to do any setup    if (this.isFunction(this.start)) {        this.start();    }  };  /**   * @static   * @description   * -> Takes object params and adds all object properties to the first (dest) param.   * @param {Object} dest   * @param {Object} src   * @return {Object} augmented dest   */  Base.mixin = function ( dest, src ) {    var prop, sources = [].slice.call(arguments, 1);    while(src = sources.shift()) {      // Iterate over all src properties      for (prop in src) {        if (src.hasOwnProperty(prop)) {          if ( utils.isObject(src[prop])  ) {            dest[prop] = dest[prop] || src[prop];            Base.mixin(dest[prop], src[prop]);          } else {            // Assign the value form the src to the destination            dest[prop] = src[prop];          }        }      }    }    return dest;  };  /**   * @static   * @description   * -> Construct is a static inheritance function   * @return {Function} constructor function   */  Base.construct = function (properties) {    var parent = this,        props = properties || {};    function F () {}    F.prototype = parent.prototype;    F.prototype.constructor = Base.mixin( F, parent );    function create (options) {        var proto = getPrototype();        Base.call(proto, options);        return proto;    }    function getPrototype() {      var proto = proto || Base.mixin( new F(), props );      return proto;    }    function proxy () {}    proxy.prototype = getPrototype();    proxy.construct = F.construct;    proxy.create = create;    return proxy;  };  // Augment the Base prototype with the  // properties of events;  Base.mixin(Base.prototype, events, utils);  // Return Base as the module definition  return Base;});define('mediator',[], function ( ) {    /**        * A little helper to remove duplication        * @param type {String} to|from        * @param obj {Object}        * @param eventName {String}        * @private        */    function add (type, obj, eventName) {        passes[ currentEvent ][ type ].push({            obj: obj,            eventName: eventName        });    }    function isEqual (a, b) {        if (a === b) {            return a !== 0 || 1 / a === 1 / b;        }        if (a === null || b === null) {            return a === b;        }        if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) {            return false;        }    }    // Polyfill for nativeForEach    function each (list, callback, context) {        var i;        // Native forEach        if (typeof Array.prototype.forEach == "function" && list.length) {            list.forEach( callback, context || this);        } else if ( list.length ) {            // Polyfill            Array.prototype.forEach = function( callback, context ) {                for (var i = 0, len = list.length; i < len; ++i) {                    callback.call(context, list[i], i, list);                }            };        } else {            // If the list is an [object Object] (i.e. Not an Array)            for ( i in list ) {                if ( list.hasOwnProperty( i ) ) {                    callback.call( context || this, list[i], i, list );                }            }        }    }    /**    * Bind one or more target events to one or more source events    * @private    */    function bind () {        each( passes[ currentEvent ], function (sources, type, passes) {            each( passes, function ( sources, type, pass ) {                each( pass.from, function ( from ) {                    // Remove any previous binding                    from.obj.off( from.eventName );                    // Bind the event to a callback                    from.obj.on( from.eventName, function( args ) {                        each( pass.to, function ( to ) {                            // The callback binds the |to| event                            to.obj.fire( to.eventName, args);                        }, this);                    }, this);                }, this);            }, this);        }, this);    }    var passes = {},        currentEvent = null;    // Return medaitor api as module definition    return {        /**        * Registers the source subject subscriber and its event(s)        * @param subscribee {Object}        * @param eventName {String}        * @return {this}        */        from: function (subscribee, eventName) {            if (!arguments.length) {                throw {                    name: "NoArgumentsException",                    message: "From cannot be called with no arguments"                };            }            currentEvent = eventName || 'all';            if ( !passes[ currentEvent ] ) {                passes[ currentEvent ] = {};            }            if ( !passes[ currentEvent ].from ) {                passes[ currentEvent ].from = [];            }            add( "from", subscribee, eventName );            if ( this.removing ) {                // Has to object been marked for removal??                each( passes, function ( pass, j ) {                    each( pass.to, function ( to, i) {                        if (pass.to[i].remove && pass.to[i].remove === true) {                            // Dedlete the target object and event,                            // null the currentEvent                            delete passes[j].to[i];                            currentEvent = null;                        }                    }, this);                }, this);                this.removing = false;            }            // Make it chainable            return this;        },        /**        * Adds a target subscriber by eventName to the mediator        * @param subscriber {Object}        * @param eventName {String}        * @return {this}        */        to: function ( subscriber, eventName ) {            if ( !currentEvent ) {                throw {                    name: "ToFunctionBadUsage",                    message: "Cannot call to before from."                };            }            if ( !passes[ currentEvent ].to ) {                passes[ currentEvent ].to = [];            }            add( "to", subscriber, eventName );            // No config object parameter            this.register();            // Make it chainable            return this;        },        /**        * Marks target and eventName for removal        * @param target {Object}        * @param eventName {String}        * @return {this}        */        remove: function (obj, eventName) {            if (!arguments.length) {                throw {                    name: "NoArgumentException",                    message: "Remove cannot be called without arguments"                };            }            this.removing = true;            each(passes, function ( pass ) {                each( pass.to, function ( to, i ) {                    if (typeof obj == "string") {                        eventName = obj;                        if ( to.eventName === eventName ) {                            [].splice.call(pass.to, i, 1);                        }                    } else {                        if ( ( isEqual(to.obj, obj) || obj == null ) && ( to.eventName === eventName || typeof eventName == "undefined" ) ) {                            to.remove = true;                        }                    }                });            });            return this;        },        /**        * Registers the source and target subscriber objects and their events for binding        * @param optional config Object        */        register: function () {            var config = arguments[0];            if ( config ) {                if ( config.source ) {                    each(config.source, function ( from ) {                        this.from( from.subscriber, from.event );                    }, this);                } else {                    throw {                        name: "ConfigSourceNotDefined",                        message: "Config object needs a source defined."                    };                }                if ( config.target ) {                    each( config.target, function (to) {                        this.to( to.subscriber, to.event );                    }, this);                } else {                    throw {                        name: "ConfigTargetNotDefined",                        message: "Config object needs a target defined."                    };                }            } else {                bind();            }        },        /**        * Notifies mediator that target and source subscriber and events should be removed.        * @param config {Object}        */        unregister: function ( config ) {            if ( !config ) {                throw {                    name: "NoArgumentException",                    message: "Unregister cannot be called without arguments"                };            }            if ( config ) {                this.removing = true;                if ( config.target ) {                    each( config.target, function ( to ) {                    this.remove( to.subscriber, to.event );                    }, this );                } else {                    throw {                        name: "ConfigTargetNotDefined",                        message: "Config object needs a target defined."                    };                }                if ( config.source ) {                    each(config.source, function (from) {                        this.from(from.subscriber, from.eventName);                    }, this );                } else {                    throw {                        name: "ConfigSourceNotDefined",                        message: "Config object needs a source defined."                    };                }            }        }    };});define('Model', ['Base'], function ( Base ) {    var constants = {            ID: 1,            ORIGID: 1,            IDPREFIX: "mid_"        };    function getNewId () {        return constants.IDPREFIX + constants.ID++;    }    function resetId () {        constants.ID = constants.ORIGID;    }    return Base.construct({        start: function (options) {            this.id = getNewId();            this.resetId = resetId;            this.properties = {};            if (options) {                this.set(options);            }            return this;        },        get: function ( name ) {            return this[ name ] || this.properties[ name ];        },        set: function ( name, value ) {            if ( this.isString(name) ) {                this.properties[ name ] = value;            } else {                for (var n in name) {                    if  (name.hasOwnProperty(n) ) {                        this.properties[ n ] = name[n];                    }                }            }        }    });});define ('Collection', ['Base', 'Model'], function ( Base, Model ) {    function getCount () {        return this.getModels().length;    }    function getBy (method, value) {        var models = this.getModels(),            len = models.length,            found = [],            i = 0;        while (0 < len--) {            if (typeof models[len][method] !== "undefined") {                if (models[len][method] === value) {                    found.push(models[len]);                }            } else {                if (models[len].get(method) === value) {                    found.push(models[len]);                }            }        }        return found = (found.length < 2) ? found[0] : found;    }    function removeBy (method, value) {        var found = [].concat(getBy.call(this, method, value)),            num = found.length,            models = this.getModels(),            len = models.length,            index = -1;        while (0 < len--) {            while (0 < num--) {                index = models.indexOf(found[num]);                if (index !== -1) {                    models.splice(index, 1);                    this.fire("removed", this.getModels());                }            }        }    }    var currentModel;    // Use Base.construct to build a constructor for the Collection    return Base.construct({        start: function ( options ) {            this.model = options && options.model ? options.model : Model;        },        models: [],        add: function (data) {            var items = [].concat(data),                len = items.length,                model,                item,                p,                currentModel;            while (len--) {                model = items[len];                if (this.isFunction(model.set)) {                    this.getModels().push( model );                } else {                    item = items[len];                    if ( this.isFunction(this.model) ) {                        model = this.model.create();                        this.getModels().push(model);                        for ( p in item ) {                            model.set( p, item[p] );                        }                    }                }                this.setCurrentModel(model);                this.fire("add", model);            }        },        reset: function () {            this.models = [];            this.fire("reset");        },        getById: function (id) {            return getBy.call(this, "id", id);        },        getByText: function (text) {            return getBy.call(this, "text", text);        },        removeByText: function (text) {            removeBy.call(this, "text", text);        },        removeById: function (id) {            removeBy.call(this, "id", id);        },        getModels: function () {            return this.models;        },        setCurrentModel: function (model) {            currentModel = model;        },        getCurrentModel: function () {            return currentModel;        }    });});define ('View',['Base'], function ( Base ) {    var TAGNAME = 'div';    // Build the constructor    return Base.construct({        tagName: TAGNAME,        start: function () {            this.tagName = this.options && this.options.tagName ? this.options.tagName : this.tagName;        },        addListener: function (type, element, handler) {            var el = (!this.isFunction(el)) ? element : this;            if (el.addEventListener) {                var evt = type.type || type;                el.addEventListener(evt, function (e) {                    if (type.key && type.key === e.keyCode) {                        handler(e);                    } else if (!type.key) {                        handler(e);                    }                });            }        },        addElement: function (element) {            this.element = element;        },        destroy: function () {            if (this.model && this.collection) {                this.collection.removeById(this.model.get("id"));            }            if (this.model) {                this.model.resetId();                this.model = null;                delete this.model;            }            this.remove();            this.element = null;            delete this.element;        },        remove: function () {            if (this.element && this.element.parentNode) {                this.element.parentNode.removeChild(this.element);            }        },        /**         * Make a Tag         */        make: function () {            // All arguments are optional            var args = [].slice.call(arguments),                name = args[0] || this.tagName,                contents = args[1],                attrs = args[2],                i,                attr,                tag = document.createElement(name);            if (args.length === 2 && this.isObject(contents)) {                contents = undefined;                attrs = args[1];            }            // Add the contents            if (typeof contents !== "undefined") {                if (this.isNumber(contents) || this.isString(contents)) {                    // If the contents is a Number or a String,                    // parse it to a textnode                    contents = document.createTextNode(contents);                }                if (this.isArray(contents)) {                    // If our contents is an array,                    // append each one to the tag                    while ( i = contents.shift() ) {                        tag.appendChild(i);                    }                } else {                    tag.appendChild(contents);                }            }            // Add the attributes            if ( attrs ) {                for ( attr in attrs ) {                    if (attrs.hasOwnProperty( attr )) {                        // Add each attribute to the tag                        tag[ attr ] = attrs[ attr ];                        if ( !( attr in tag.attributes ) ) {                            // If the attribute wasnt't successfully added,                            // try again with setAttribute                            tag.setAttribute( attr, attrs[ attr ] );                        }                    }                }            }            // Finally return the new tag            return tag;        }    });});define('main', [    'Base',    'events',    'mediator',    'utils',    'Collection',    'Model',    'View'    ],    function ( Base, events, mediator, utils, Collection, Model, View ) {        return {            events: events,            mediator: mediator,            utils: utils,            Collection: Collection,            Model: Model,            View: View        };    });  var library = require('main');  if(typeof module !== 'undefined' && module.exports) {    module.exports = library;  } else if(globalDefine) {    (function (define) {      define(function () { return library; });    }(globalDefine));  } else {    global['Truss'] = library;  }}(this));\ No newline at end of file+(function(global, define) {+  var globalDefine = global.define;++/**+ * almond 0.2.5 Copyright (c) 2011-2012, The Dojo Foundation All Rights Reserved.+ * Available via the MIT or new BSD license.+ * see: http://github.com/jrburke/almond for details+ */+//Going sloppy to avoid 'use strict' string cost, but strict practices should+//be followed.+/*jslint sloppy: true */+/*global setTimeout: false */++var requirejs, require, define;+(function (undef) {+    var main, req, makeMap, handlers,+        defined = {},+        waiting = {},+        config = {},+        defining = {},+        hasOwn = Object.prototype.hasOwnProperty,+        aps = [].slice;++    function hasProp(obj, prop) {+        return hasOwn.call(obj, prop);+    }++    /**+     * Given a relative module name, like ./something, normalize it to+     * a real name that can be mapped to a path.+     * @param {String} name the relative name+     * @param {String} baseName a real name that the name arg is relative+     * to.+     * @returns {String} normalized name+     */+    function normalize(name, baseName) {+        var nameParts, nameSegment, mapValue, foundMap,+            foundI, foundStarMap, starI, i, j, part,+            baseParts = baseName && baseName.split("/"),+            map = config.map,+            starMap = (map && map['*']) || {};++        //Adjust any relative paths.+        if (name && name.charAt(0) === ".") {+            //If have a base name, try to normalize against it,+            //otherwise, assume it is a top-level require that will+            //be relative to baseUrl in the end.+            if (baseName) {+                //Convert baseName to array, and lop off the last part,+                //so that . matches that "directory" and not name of the baseName's+                //module. For instance, baseName of "one/two/three", maps to+                //"one/two/three.js", but we want the directory, "one/two" for+                //this normalization.+                baseParts = baseParts.slice(0, baseParts.length - 1);++                name = baseParts.concat(name.split("/"));++                //start trimDots+                for (i = 0; i < name.length; i += 1) {+                    part = name[i];+                    if (part === ".") {+                        name.splice(i, 1);+                        i -= 1;+                    } else if (part === "..") {+                        if (i === 1 && (name[2] === '..' || name[0] === '..')) {+                            //End of the line. Keep at least one non-dot+                            //path segment at the front so it can be mapped+                            //correctly to disk. Otherwise, there is likely+                            //no path mapping for a path starting with '..'.+                            //This can still fail, but catches the most reasonable+                            //uses of ..+                            break;+                        } else if (i > 0) {+                            name.splice(i - 1, 2);+                            i -= 2;+                        }+                    }+                }+                //end trimDots++                name = name.join("/");+            } else if (name.indexOf('./') === 0) {+                // No baseName, so this is ID is resolved relative+                // to baseUrl, pull off the leading dot.+                name = name.substring(2);+            }+        }++        //Apply map config if available.+        if ((baseParts || starMap) && map) {+            nameParts = name.split('/');++            for (i = nameParts.length; i > 0; i -= 1) {+                nameSegment = nameParts.slice(0, i).join("/");++                if (baseParts) {+                    //Find the longest baseName segment match in the config.+                    //So, do joins on the biggest to smallest lengths of baseParts.+                    for (j = baseParts.length; j > 0; j -= 1) {+                        mapValue = map[baseParts.slice(0, j).join('/')];++                        //baseName segment has  config, find if it has one for+                        //this name.+                        if (mapValue) {+                            mapValue = mapValue[nameSegment];+                            if (mapValue) {+                                //Match, update name to the new value.+                                foundMap = mapValue;+                                foundI = i;+                                break;+                            }+                        }+                    }+                }++                if (foundMap) {+                    break;+                }++                //Check for a star map match, but just hold on to it,+                //if there is a shorter segment match later in a matching+                //config, then favor over this star map.+                if (!foundStarMap && starMap && starMap[nameSegment]) {+                    foundStarMap = starMap[nameSegment];+                    starI = i;+                }+            }++            if (!foundMap && foundStarMap) {+                foundMap = foundStarMap;+                foundI = starI;+            }++            if (foundMap) {+                nameParts.splice(0, foundI, foundMap);+                name = nameParts.join('/');+            }+        }++        return name;+    }++    function makeRequire(relName, forceSync) {+        return function () {+            //A version of a require function that passes a moduleName+            //value for items that may need to+            //look up paths relative to the moduleName+            return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync]));+        };+    }++    function makeNormalize(relName) {+        return function (name) {+            return normalize(name, relName);+        };+    }++    function makeLoad(depName) {+        return function (value) {+            defined[depName] = value;+        };+    }++    function callDep(name) {+        if (hasProp(waiting, name)) {+            var args = waiting[name];+            delete waiting[name];+            defining[name] = true;+            main.apply(undef, args);+        }++        if (!hasProp(defined, name) && !hasProp(defining, name)) {+            throw new Error('No ' + name);+        }+        return defined[name];+    }++    //Turns a plugin!resource to [plugin, resource]+    //with the plugin being undefined if the name+    //did not have a plugin prefix.+    function splitPrefix(name) {+        var prefix,+            index = name ? name.indexOf('!') : -1;+        if (index > -1) {+            prefix = name.substring(0, index);+            name = name.substring(index + 1, name.length);+        }+        return [prefix, name];+    }++    /**+     * Makes a name map, normalizing the name, and using a plugin+     * for normalization if necessary. Grabs a ref to plugin+     * too, as an optimization.+     */+    makeMap = function (name, relName) {+        var plugin,+            parts = splitPrefix(name),+            prefix = parts[0];++        name = parts[1];++        if (prefix) {+            prefix = normalize(prefix, relName);+            plugin = callDep(prefix);+        }++        //Normalize according+        if (prefix) {+            if (plugin && plugin.normalize) {+                name = plugin.normalize(name, makeNormalize(relName));+            } else {+                name = normalize(name, relName);+            }+        } else {+            name = normalize(name, relName);+            parts = splitPrefix(name);+            prefix = parts[0];+            name = parts[1];+            if (prefix) {+                plugin = callDep(prefix);+            }+        }++        //Using ridiculous property names for space reasons+        return {+            f: prefix ? prefix + '!' + name : name, //fullName+            n: name,+            pr: prefix,+            p: plugin+        };+    };++    function makeConfig(name) {+        return function () {+            return (config && config.config && config.config[name]) || {};+        };+    }++    handlers = {+        require: function (name) {+            return makeRequire(name);+        },+        exports: function (name) {+            var e = defined[name];+            if (typeof e !== 'undefined') {+                return e;+            } else {+                return (defined[name] = {});+            }+        },+        module: function (name) {+            return {+                id: name,+                uri: '',+                exports: defined[name],+                config: makeConfig(name)+            };+        }+    };++    main = function (name, deps, callback, relName) {+        var cjsModule, depName, ret, map, i,+            args = [],+            usingExports;++        //Use name if no relName+        relName = relName || name;++        //Call the callback to define the module, if necessary.+        if (typeof callback === 'function') {++            //Pull out the defined dependencies and pass the ordered+            //values to the callback.+            //Default to [require, exports, module] if no deps+            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;+            for (i = 0; i < deps.length; i += 1) {+                map = makeMap(deps[i], relName);+                depName = map.f;++                //Fast path CommonJS standard dependencies.+                if (depName === "require") {+                    args[i] = handlers.require(name);+                } else if (depName === "exports") {+                    //CommonJS module spec 1.1+                    args[i] = handlers.exports(name);+                    usingExports = true;+                } else if (depName === "module") {+                    //CommonJS module spec 1.1+                    cjsModule = args[i] = handlers.module(name);+                } else if (hasProp(defined, depName) ||+                           hasProp(waiting, depName) ||+                           hasProp(defining, depName)) {+                    args[i] = callDep(depName);+                } else if (map.p) {+                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});+                    args[i] = defined[depName];+                } else {+                    throw new Error(name + ' missing ' + depName);+                }+            }++            ret = callback.apply(defined[name], args);++            if (name) {+                //If setting exports via "module" is in play,+                //favor that over return value and exports. After that,+                //favor a non-undefined return value over exports use.+                if (cjsModule && cjsModule.exports !== undef &&+                        cjsModule.exports !== defined[name]) {+                    defined[name] = cjsModule.exports;+                } else if (ret !== undef || !usingExports) {+                    //Use the return value from the function.+                    defined[name] = ret;+                }+            }+        } else if (name) {+            //May just be an object definition for the module. Only+            //worry about defining if have a module name.+            defined[name] = callback;+        }+    };++    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {+        if (typeof deps === "string") {+            if (handlers[deps]) {+                //callback in this case is really relName+                return handlers[deps](callback);+            }+            //Just return the module wanted. In this scenario, the+            //deps arg is the module name, and second arg (if passed)+            //is just the relName.+            //Normalize module name, if it contains . or ..+            return callDep(makeMap(deps, callback).f);+        } else if (!deps.splice) {+            //deps is a config object, not an array.+            config = deps;+            if (callback.splice) {+                //callback is an array, which means it is a dependency list.+                //Adjust args if there are dependencies+                deps = callback;+                callback = relName;+                relName = null;+            } else {+                deps = undef;+            }+        }++        //Support require(['a'])+        callback = callback || function () {};++        //If relName is a function, it is an errback handler,+        //so remove it.+        if (typeof relName === 'function') {+            relName = forceSync;+            forceSync = alt;+        }++        //Simulate async callback;+        if (forceSync) {+            main(undef, deps, callback, relName);+        } else {+            //Using a non-zero value because of concern for what old browsers+            //do, and latest browsers "upgrade" to 4 if lower value is used:+            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:+            //If want a value immediately, use require('id') instead -- something+            //that works in almond on the global level, but not guaranteed and+            //unlikely to work in other AMD implementations.+            setTimeout(function () {+                main(undef, deps, callback, relName);+            }, 4);+        }++        return req;+    };++    /**+     * Just drops the config on the floor, but returns req in case+     * the config return value is used.+     */+    req.config = function (cfg) {+        config = cfg;+        if (config.deps) {+            req(config.deps, config.callback);+        }+        return req;+    };++    define = function (name, deps, callback) {++        //This module may not have dependencies+        if (!deps.splice) {+            //deps is not an array, so probably means+            //an object literal or factory function for+            //the value. Adjust args.+            callback = deps;+            deps = [];+        }++        if (!hasProp(defined, name) && !hasProp(waiting, name)) {+            waiting[name] = [name, deps, callback];+        }+    };++    define.amd = {+        jQuery: true+    };+}());+define("vendor/almond", function(){});++define ('events',[], function ( ) {  return {    events: {},    on: function (event, callback) {      var context;      if ( "string" != typeof event ) {        throw new Error("on() needs an event name string");      }      if ( "function" != typeof callback ) {        throw new Error("on() needs a callback function");      }      context = [].slice.call( arguments, 2 )[0];      if ( !this.events[event] ) {        this.events[event] = [];      }      this.events[event].push({        callback: callback,        context: context      });    },    reset: function () {      this.events = {};    },    off: function (event) {      var ev, len, cb;      // Event must be a string      if ( "string" != typeof event ) {        throw new Error( "off() needs an event" );      }      cb = [].slice.call( arguments, 1 )[0];      // If the event has been registered      if ( this.events[event] ) {        ev = this.events[event];        len = ev.length;        // Loop over each event object that matches ours.        while ( len-- ) {          if ( "function" != typeof cb ) {            // If no callback was given, remove the event            // and all its callbacks            ev.splice(len, 1);          } else {            // If a callback was passed,            // remove the callback from the event            if ( ev[len].callback === cb ) {              ev[len].callback = null;              delete ev[len].callback;            }          }        }      }    },    fire: function ( event ) {      var ev, len, opt, data, ctx;      // event argument is mandatory      if ( "string" != typeof event ) {        throw new Error("fire() needs an event");      }      // Optional arguments      opt = [].slice.call( arguments, 1 );      data = opt[0];      ctx = opt[1];      // If this event has been registered      if ( this.events[event] ) {        len = this.events[event].length;        // Invoke the callback on each event object        while ( ev = this.events[event][--len] ) {          if ("function" == typeof ev.callback) {            // Invoke in either context with data if present            ev.callback.call( ( ctx || ev.context || this ), data );          }        }      }    }  };});+define('utils',[], function ( ) {++  return {++    realTypeOf: function ( value ) {+      // Borrow Object.toString to introspect the+      // class definition of the value i.e. ([object Object])+      // and return the latter portion which denotes+      // the real type of value.+      return ({}).toString.call(value).match( /\w+/g )[1].toLowerCase();+    },++    isObject: function ( value ) {+      //delegate to realTypeOf+      return this.realTypeOf(value) === 'object';+    },++    isArray: function ( value ) {+      if (Array.isArray) {+        return Array.isArray(value);+      }+      //delegate to realTypeOf if isArray is not supported+      return this.realTypeOf(value) === 'array';+    },++    isString: function ( value ) {+      //delegate to realTypeOf+      return this.realTypeOf(value) === 'string';+    },++    isNumber: function ( value ) {+      //delegate to realTypeOf+      return this.realTypeOf(value) === 'number';+    },++    isFunction: function ( value ) {+      //delegate to realTypeOf+      return this.realTypeOf(value) === 'function';+    }++  };++});+define('Base', ['events', 'utils'], function ( events, utils ) {++  /**+   * @constructor+   * @description+   * -> Core of Base framework+   * @param {Object} options+   * @return {this}+   */+  var Base = function ( options ) {++    // Add any arguments to this.options+    if ( "undefined" != typeof options ) {+        this.options = options;+        Base.mixin(this, options);+    }++    // Call the start function to do any setup+    if ( this.isFunction(this.start) ) {+        this.start();+    }++  };++  /**+   * @static+   * @description+   * -> Takes object params and adds all object properties to the first (dest) param.+   * @param {Object} dest+   * @param {Object} src+   * @return {Object} augmented dest+   */+  Base.mixin = function ( dest, src ) {++    var prop, sources = [].slice.call(arguments, 1);++    while(src = sources.shift()) {+      // Iterate over all src properties+      for (prop in src) {+        if (src.hasOwnProperty(prop)) {+          if ( utils.isObject(src[prop])  ) {+            dest[prop] = dest[prop] || src[prop];+            Base.mixin(dest[prop], src[prop]);+          } else {+            // Assign the value form the src to the destination+            dest[prop] = src[prop];+          }+        }+      }++    }++    return dest;+  };++  /**+   * @static+   * @description+   * -> Construct is a static inheritance function+   * @return {Function} constructor function+   */+  Base.construct = function (properties) {++    var parent = this,+        props = properties || {};++    function F () {}+    F.prototype = parent.prototype;+    F.prototype.constructor = Base.mixin( F, parent );++    function create (options) {+        var proto = getPrototype();+        Base.call(proto, options);+        return proto;+    }++    function getPrototype() {+      var proto = proto || Base.mixin( new F(), props );+      return proto;+    }++    function proxy () {}+    proxy.prototype = getPrototype();+    proxy.construct = F.construct;+    proxy.create = create;++    return proxy;++  };++  // Augment the Base prototype with the+  // properties of events;+  Base.mixin(Base.prototype, events, utils);+++  // Return Base as the module definition+  return Base;++});+define('mediator',[], function ( ) {    /**        * A little helper to remove duplication        * @param type {String} to|from        * @param obj {Object}        * @param eventName {String}        * @private        */    function add (type, obj, eventName) {        passes[ currentEvent ][ type ].push({            obj: obj,            eventName: eventName        });    }    function isEqual (a, b) {        if (a === b) {            return a !== 0 || 1 / a === 1 / b;        }        if (a === null || b === null) {            return a === b;        }        if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) {            return false;        }    }    // Polyfill for nativeForEach    function each (list, callback, context) {        var i;        // Native forEach        if (typeof Array.prototype.forEach == "function" && list.length) {            list.forEach( callback, context || this);        } else if ( list.length ) {            // Polyfill            Array.prototype.forEach = function( callback, context ) {                for (var i = 0, len = list.length; i < len; ++i) {                    callback.call(context, list[i], i, list);                }            };        } else {            // If the list is an [object Object] (i.e. Not an Array)            for ( i in list ) {                if ( list.hasOwnProperty( i ) ) {                    callback.call( context || this, list[i], i, list );                }            }        }    }    /**    * Bind one or more target events to one or more source events    * @private    */    function bind () {        each( passes[ currentEvent ], function (sources, type, passes) {            each( passes, function ( sources, type, pass ) {                each( pass.from, function ( from ) {                    // Remove any previous binding                    from.obj.off( from.eventName );                    // Bind the event to a callback                    from.obj.on( from.eventName, function( args ) {                        each( pass.to, function ( to ) {                            // The callback binds the |to| event                            to.obj.fire( to.eventName, args);                        }, this);                    }, this);                }, this);            }, this);        }, this);    }    var passes = {},        currentEvent = null;    // Return medaitor api as module definition    return {        /**        * Registers the source subject subscriber and its event(s)        * @param subscribee {Object}        * @param eventName {String}        * @return {this}        */        from: function (subscribee, eventName) {            if (!arguments.length) {                throw {                    name: "NoArgumentsException",                    message: "From cannot be called with no arguments"                };            }            currentEvent = eventName || 'all';            if ( !passes[ currentEvent ] ) {                passes[ currentEvent ] = {};            }            if ( !passes[ currentEvent ].from ) {                passes[ currentEvent ].from = [];            }            add( "from", subscribee, eventName );            if ( this.removing ) {                // Has to object been marked for removal??                each( passes, function ( pass, j ) {                    each( pass.to, function ( to, i) {                        if (pass.to[i].remove && pass.to[i].remove === true) {                            // Dedlete the target object and event,                            // null the currentEvent                            delete passes[j].to[i];                            currentEvent = null;                        }                    }, this);                }, this);                this.removing = false;            }            // Make it chainable            return this;        },        /**        * Adds a target subscriber by eventName to the mediator        * @param subscriber {Object}        * @param eventName {String}        * @return {this}        */        to: function ( subscriber, eventName ) {            if ( !currentEvent ) {                throw {                    name: "ToFunctionBadUsage",                    message: "Cannot call to before from."                };            }            if ( !passes[ currentEvent ].to ) {                passes[ currentEvent ].to = [];            }            add( "to", subscriber, eventName );            // No config object parameter            this.register();            // Make it chainable            return this;        },        /**        * Marks target and eventName for removal        * @param target {Object}        * @param eventName {String}        * @return {this}        */        remove: function (obj, eventName) {            if (!arguments.length) {                throw {                    name: "NoArgumentException",                    message: "Remove cannot be called without arguments"                };            }            this.removing = true;            each(passes, function ( pass ) {                each( pass.to, function ( to, i ) {                    if (typeof obj == "string") {                        eventName = obj;                        if ( to.eventName === eventName ) {                            [].splice.call(pass.to, i, 1);                        }                    } else {                        if ( ( isEqual(to.obj, obj) || obj == null ) && ( to.eventName === eventName || typeof eventName == "undefined" ) ) {                            to.remove = true;                        }                    }                });            });            return this;        },        /**        * Registers the source and target subscriber objects and their events for binding        * @param optional config Object        */        register: function () {            var config = arguments[0];            if ( config ) {                if ( config.source ) {                    each(config.source, function ( from ) {                        this.from( from.subscriber, from.event );                    }, this);                } else {                    throw {                        name: "ConfigSourceNotDefined",                        message: "Config object needs a source defined."                    };                }                if ( config.target ) {                    each( config.target, function (to) {                        this.to( to.subscriber, to.event );                    }, this);                } else {                    throw {                        name: "ConfigTargetNotDefined",                        message: "Config object needs a target defined."                    };                }            } else {                bind();            }        },        /**        * Notifies mediator that target and source subscriber and events should be removed.        * @param config {Object}        */        unregister: function ( config ) {            if ( !config ) {                throw {                    name: "NoArgumentException",                    message: "Unregister cannot be called without arguments"                };            }            if ( config ) {                this.removing = true;                if ( config.target ) {                    each( config.target, function ( to ) {                    this.remove( to.subscriber, to.event );                    }, this );                } else {                    throw {                        name: "ConfigTargetNotDefined",                        message: "Config object needs a target defined."                    };                }                if ( config.source ) {                    each(config.source, function (from) {                        this.from(from.subscriber, from.eventName);                    }, this );                } else {                    throw {                        name: "ConfigSourceNotDefined",                        message: "Config object needs a source defined."                    };                }            }        }    };});+define('Model', ['Base'], function ( Base ) {++    var constants = {+            ID: 1,+            ORIGID: 1,+            IDPREFIX: "mid_"+        };++    function getNewId () {+        return constants.IDPREFIX + constants.ID++;+    }++    function resetId () {+        constants.ID = constants.ORIGID;+    }++    return Base.construct({++        start: function (options) {+            this.id = getNewId();+            this.resetId = resetId;+            this.properties = {};++            if (options) {+                this.set(options);+            }++            return this;+        },++        get: function ( name ) {+            return this[ name ] || this.properties[ name ];+        },++        set: function ( name, value ) {+            if ( this.isString(name) ) {+                this.properties[ name ] = value;+            } else {+                for (var n in name) {+                    if  (name.hasOwnProperty(n) ) {+                        this.properties[ n ] = name[n];+                    }+                }+            }++        }++    });++});++define ('Collection', ['Base', 'Model'], function ( Base, Model ) {++    function getCount () {+        return this.getModels().length;+    }++    function getBy (method, value) {+        var models = this.getModels(),+            len = models.length,+            found = [],+            i = 0;++        while (0 < len--) {+            if (typeof models[len][method] !== "undefined") {+                if (models[len][method] === value) {+                    found.push(models[len]);+                }+            } else {+                if (models[len].get(method) === value) {+                    found.push(models[len]);+                }+            }+        }+        return found = (found.length < 2) ? found[0] : found;+    }++    function removeBy (method, value) {+        var found = [].concat(getBy.call(this, method, value)),+            num = found.length,+            models = this.getModels(),+            len = models.length,+            index = -1;++        while (0 < len--) {+            while (0 < num--) {+                index = models.indexOf(found[num]);+                if (index !== -1) {+                    models.splice(index, 1);+                    this.fire("removed", this.getModels());+                }+            }+        }+    }++    var currentModel;++    // Use Base.construct to build a constructor for the Collection+    return Base.construct({++        start: function ( options ) {++            this.model = options && options.model ? options.model : Model;++        },++        models: [],++        add: function (data) {++            var items = [].concat(data),+                len = items.length,+                model,+                item,+                p,+                currentModel;++            while (len--) {++                model = items[len];++                if (this.isFunction(model.set)) {++                    this.getModels().push( model );++                } else {++                    item = items[len];++                    if ( this.isFunction(this.model) ) {++                        model = this.model.create();+                        this.getModels().push(model);++                        for ( p in item ) {+                            model.set( p, item[p] );+                        }++                    }+                }++                this.setCurrentModel(model);++                this.fire("add", model);+            }++        },++        reset: function () {+            this.models = [];+            this.fire("reset");+        },++        getById: function (id) {+            return getBy.call(this, "id", id);+        },++        getByText: function (text) {+            return getBy.call(this, "text", text);+        },++        removeByText: function (text) {+            removeBy.call(this, "text", text);+        },++        removeById: function (id) {+            removeBy.call(this, "id", id);+        },++        getModels: function () {+            return this.models;+        },++        setCurrentModel: function (model) {+            currentModel = model;+        },++        getCurrentModel: function () {+            return currentModel;+        }++    });++});++define ('View',['Base'], function ( Base ) {    var TAGNAME = 'div';    // Build the constructor    return Base.construct({        tagName: 'div',        start: function () {            this.tagName = this.options && this.options.tagName ? this.options.tagName : this.tagName;        },        setElement: function (element) {            this.element = element;        },        removeElement: function () {            if (arguments[0] && arguments[0].nodeType === 1) {                this.setElement(arguments[0]);            }            if (this.element.parentNode) {                this.element.parentNode.removeChild(this.element);            }            this.stopListening();            this.element = null;            delete this.element;        },        destroy: function () {            if (this.model && this.collection) {                this.collection.removeById(this.model.get("id"));            }            this.removeElement();        },        replaceElement: function (replacement) {            var replacee = this.element;            if (arguments[1] && arguments[1].nodeType === 1) {                replacee = arguments[1];            }            if (replacee && replacee.parentNode) {                this.oldElement = replacee.parentNode.replaceChild(replacement, replacee);            }        },        addListener: function (eventName, handler) {            var el = arguments[2] && arguments[2].nodeType === 1 ? arguments[2] : this.element;            if (el.addEventListener) {                var evt = eventName.type || eventName;                el.addEventListener(evt, function (e) {                    if (eventName.key && (eventName.key == e.keyCode)) {                        handler(e);                    } else if (!eventName.key) {                        handler(e);                    }                });            }        },        stopListening: function () {            this.element.removeEventListener('*');        },        make: function () {            // All arguments are optional            var args = [].slice.call(arguments),                name = args[0] || this.tagName,                contents = args[1],                attrs = args[2],                i,                attr,                tag = document.createElement(name);            if (args.length === 2 && this.isObject(contents)) {                contents = undefined;                attrs = args[1];            }            // Add the contents            if (typeof contents !== "undefined") {                if (this.isNumber(contents) || this.isString(contents)) {                    // If the contents is a Number or a String,                    // parse it to a textnode                    contents = document.createTextNode(contents);                }                if (this.isArray(contents)) {                    // If our contents is an array,                    // append each one to the tag                    while ( i = contents.shift() ) {                        tag.appendChild(i);                    }                } else {                    tag.appendChild(contents);                }            }            // Add the attributes            if ( attrs ) {                for ( attr in attrs ) {                    if (attrs.hasOwnProperty( attr )) {                        // Add each attribute to the tag                        tag[ attr ] = attrs[ attr ];                        if ( !( attr in tag.attributes ) ) {                            // If the attribute wasnt't successfully added,                            // try again with setAttribute                            tag.setAttribute( attr, attrs[ attr ] );                        }                    }                }            }            // Finally return the new tag            return tag;        }    });});+define('main', [+    'Base',+    'events',+    'mediator',+    'utils',+    'Collection',+    'Model',+    'View'+    ],++    function ( Base, events, mediator, utils, Collection, Model, View ) {++        return {+            events: events,+            mediator: mediator,+            utils: utils,+            Collection: Collection,+            Model: Model,+            View: View+        };++    }+);  var library = require('main');+  if(typeof module !== 'undefined' && module.exports) {+    module.exports = library;+  } else if(globalDefine) {+    (function (define) {+      define(function () { return library; });+    }(globalDefine));+  } else {+    global['Truss'] = library;+  }+}(this));diff --git examples/todo/public/javascripts/bootstrap.js examples/todo/public/javascripts/bootstrap.jsindex e01c2fa..a715db7 100644--- examples/todo/public/javascripts/bootstrap.js+++ examples/todo/public/javascripts/bootstrap.js@@ -1 +1 @@-var rootNode = document.getElementById("rootNode"),    options = {        rootNode: rootNode,        tagName: 'div',        collection: Truss.Collection.create()    };ViewTodoForm.create(options);ViewTodoCount.create(options);ViewTodoList.create(options);\ No newline at end of file+var rootNode = document.getElementById("rootNode"),    options = {        rootNode: rootNode,        collection: Truss.Collection.create()    };ViewTodoForm.create(options);ViewTodoCount.create(options);ViewTodoList.create(options);\ No newline at end of filediff --git examples/todo/public/javascripts/views/Notes.View.Count.js examples/todo/public/javascripts/views/Notes.View.Count.jsindex 75190f9..4ea2e39 100644--- examples/todo/public/javascripts/views/Notes.View.Count.js+++ examples/todo/public/javascripts/views/Notes.View.Count.js@@ -1,36 +1,34 @@     var ViewTodoCount = Truss.View.construct({+        tagName: 'output',+         start: function () {-            if (!this.options.collection) {+            if (!this.collection) {                 throw new Error("View requires a collection");             }-            this.tagName = "output";             this.counter = 0;-            this.rootNode = this.options.rootNode;-            this.collection = this.options.collection;--            this._render();-            this.collection.on("add", this._increment.bind(this));-            this.collection.on("removed", this._decrement.bind(this));+            this.render();+            this.collection.on("add", this.increment.bind(this));+            this.collection.on("removed", this.decrement.bind(this));         },-        _increment: function (model) {+        increment: function (model) {             this.output.innerHTML = this.collection.getModels().length;         },-        _decrement: function (models) {+        decrement: function (models) {             this.output.innerHTML = models.length;         },-        _render: function () {+        render: function () {             var element;             this.output = this.make(this.tagName, this.counter);-            element = this.make("p", this.output);-            this.rootNode.appendChild(element);+            this.setElement(this.make("p", this.output));+            this.rootNode.appendChild(this.element);         }     });\ No newline at end of filediff --git examples/todo/public/javascripts/views/Notes.View.Edit_Note.js examples/todo/public/javascripts/views/Notes.View.Edit_Note.jsindex b1e5742..1815363 100644--- examples/todo/public/javascripts/views/Notes.View.Edit_Note.js+++ examples/todo/public/javascripts/views/Notes.View.Edit_Note.js@@ -1 +1 @@-var ViewTodoEdit = Truss.View.construct({    start: function () {        this.model = this.options.model;        this.parentEl = this.options.parentEl;        this.render();        this.addListener({type: "keypress", key: 13}, this.element, this.update.bind(this));    },    render: function () {        this.element = this.make("input", {                autofocus: true,                id: this.model.get("id"),                value: this.model.get("text")            });        this.textEl = this.parentEl.firstChild;        this.parentEl.replaceChild(this.element, this.parentEl.firstChild);    },    update: function (e) {        this.model.set("text", e.target.value);        this.textEl.innerHTML = this.model.get("text");        this.parentEl.replaceChild(this.textEl, this.element);    }});\ No newline at end of file+var ViewTodoEdit = Truss.View.construct({    start: function () {        this.render();        this.addListener({type: "keyup", key: 13}, this.update.bind(this));    },    render: function () {        this.setElement(this.make("input", {                autofocus: true,                id: this.model.get("id"),                value: this.model.get("text")            }));        this.textEl = this.parentEl.firstChild;        this.replaceElement(this.element, this.textEl);    },    update: function (e) {        this.model.set("text", e.target.value);        this.textEl.innerHTML = this.model.get("text");        this.replaceElement(this.textEl);    }});\ No newline at end of filediff --git examples/todo/public/javascripts/views/Notes.View.Form.js examples/todo/public/javascripts/views/Notes.View.Form.jsindex 44cdc1e..9b429b3 100644--- examples/todo/public/javascripts/views/Notes.View.Form.js+++ examples/todo/public/javascripts/views/Notes.View.Form.js@@ -3,29 +3,27 @@ var ViewTodoForm = Truss.View.construct({     start: function () {-        if (!this.options.collection) {+        if (!this.collection) {             throw new Error("View requires a collection");         }-        this.rootNode = this.options.rootNode;-        this.collection = this.options.collection;-        this._makeElements();+        this.makeElements();     },-    _add: function (e) {+    add: function (e) {         e.preventDefault();         var value = this.input.value;-        if (this._isValid(value)) {+        if (this.isValid(value)) {             this.collection.add({'text': value});         }     },-    _isValid: function (value) {+    isValid: function (value) {         return (/\S/g).test(value);     },-    _makeElements: function () {+    makeElements: function () {         var fieldset;@@ -48,16 +46,16 @@ var ViewTodoForm = Truss.View.construct({                                         method: "get"                                     });-        this._render();+        this.render();     },-    _render: function () {+    render: function () {         this._submitListener();         this.rootNode.appendChild(this.element);     },     _submitListener: function () {-        this.submit.addEventListener("click", this._add.bind(this), false);+        this.addListener("click", this.add.bind(this), this.submit);     } });diff --git examples/todo/public/javascripts/views/Notes.View.List.js examples/todo/public/javascripts/views/Notes.View.List.jsindex 1821896..e6a406a 100644--- examples/todo/public/javascripts/views/Notes.View.List.js+++ examples/todo/public/javascripts/views/Notes.View.List.js@@ -1 +1 @@-var ViewTodoList = Truss.View.construct({    start:  function () {        if (!this.options.collection) {            throw new Error("View requires a collection");        }        this.tagName = "ul";        this.rootNode = this.options.rootNode;        this.collection = this.options.collection;        this.collection.on("add", this._renderNote.bind(this), this);        this.render();    },    render: function () {        this.element = document.createElement(this.tagName);        this.rootNode.appendChild(this.element);    },    _renderNote: function (model) {        ViewTodoItem.create({            parentEl: this._getElement(),            model: model,            collection: this._getCollection()        });    },    _getCollection: function () {        return this.collection;    },    _getElement: function () {        return this.element;    }});\ No newline at end of file+var ViewTodoList = Truss.View.construct({    tagName: 'ul',    start:  function () {        if (!this.collection) {            throw new Error("View requires a collection");        }        this.collection.on("add", this.renderNote.bind(this), this);        this.render();    },    render: function () {        this.setElement(this.make(this.tagName));        this.options.rootNode.appendChild(this.element);    },    renderNote: function (model) {        ViewTodoItem.create({            parentEl: this.element,            model: model,            collection: this.collection        });    },    _getCollection: function () {        return this.collection;    },    _getElement: function () {        return this.element;    }});\ No newline at end of filediff --git examples/todo/public/javascripts/views/Notes.View.Note.js examples/todo/public/javascripts/views/Notes.View.Note.jsindex 2173af7..4bb1b02 100644--- examples/todo/public/javascripts/views/Notes.View.Note.js+++ examples/todo/public/javascripts/views/Notes.View.Note.js@@ -1 +1 @@-    var ViewTodoItem = Truss.View.construct({        start: function () {            if (!this.options.collection) {                throw new Error("View requires a collection");            }            this.parentEl = this.options.parentEl;            this.model = this.options.model;            this.collection = this.options.collection;            this.render();            this.button.addEventListener("click", this.destroy.bind(this), false);            this.text.addEventListener("click", this.edit.bind(this), false);        },        edit: function () {            ViewTodoEdit.create({                parentEl: this.element,                model: this.model            });        },        render: function () {            var button = this.make("button"),                em = this.make("em", this.model.get("text") ),                element = this.make("li",                    [em, button], {                    id: this.model.get("id"),                    draggable: true                });            this.text = em;            this.button = button;            this.element = element;            this.parentEl.appendChild(element);        }    });\ No newline at end of file+var ViewTodoItem = Truss.View.construct({    start: function () {        if (!this.collection) {            throw new Error("View requires a collection");        }        this.render();        this.addListener("click", this.destroy.bind(this), this.button);        this.addListener("click", this.edit.bind(this), this.text);    },    edit: function () {        ViewTodoEdit.create({            parentEl: this.element,            model: this.model        });    },    render: function () {        var button = this.make("button"),            em = this.make("em", this.model.get("text") ),            element = this.make("li",                [em, button], {                id: this.model.get("id"),                draggable: true            });        this.text = em;        this.button = button;        this.setElement(element);        this.parentEl.appendChild(element);    }});\ No newline at end of file
Lib API changes esp. View.# Please enter the commit message for your changes. Lines starting# with '#' will be ignored, and an empty message aborts the commit.# On branch master# Your branch is ahead of 'origin/master' by 2 commits.#   (use "git push" to publish your local commits)## Changes to be committed:#   (use "git reset HEAD <file>..." to unstage)##	modified:   Gruntfile.js#	modified:   Truss-min.js#	modified:   spec/View.spec.js#	modified:   src/View.js## Untracked files:#   (use "git add <file>..." to include in what will be committed)##	Truss.js,examples/diff --git Gruntfile.js Gruntfile.jsindex c110aca..80ee9ba 100644--- Gruntfile.js+++ Gruntfile.js@@ -1 +1 @@-"use strict";module.exports = function( grunt ) {    // Project configuration.    grunt.initConfig({        pkg: grunt.file.readJSON('package.json'),        dirs: {            src: 'src',            spec: 'spec',            dest: 'dist/<%= pkg.name %>/<%= pkg.version %>'        },        meta : {            src   : '<%= dirs.src %>/*.js',            spec : '<%= dirs.spec %>/*.spec.js'        },        watch: {            test : {                files: ['<%= meta.src %>','<%= meta.spec %>'],                tasks: 'test'            }        },        jasmine : {            all: {                options : {                    specs : '<%= meta.spec %>',                    template: require('grunt-template-jasmine-requirejs'),                    templateOptions: {                        requireConfig: {                            baseUrl: './src'                        }                    }                }            }        },        requirejs: {            compile: {                options: {                    uglify: {                        toplevel: true,                        ascii_only: true,                        beautify: false,                        max_line_length: 100,                        no_mangle: false                    },                    baseUrl: "./src",                    name: 'vendor/almond',                    include: ['main'],                    wrap: {                        start: "(function(global, define) {\n"+                        // check for amd loader on global namespace                        "  var globalDefine = global.define;\n",                        end:   "  var library = require('main');\n"+                        "  if(typeof module !== 'undefined' && module.exports) {\n"+                        // export library for node                        "    module.exports = library;\n"+                        "  } else if(globalDefine) {\n"+                        // define library for global amd loader that is already present                        "    (function (define) {\n"+                        "      define(function () { return library; });\n"+                        "    }(globalDefine));\n"+                        "  } else {\n"+                        // define library on global namespace for inline script loading                        "    global['Truss'] = library;\n"+                        "  }\n"+                        "}(this));\n"                    },                    out: '<%= pkg.name %>-min.js'                }            },            unoptimized: {                options: {                    optimize: "none",                    baseUrl: "./src",                    name: 'vendor/almond',                    include: ['main'],                    wrap: {                        start: "(function(global, define) {\n"+                        // check for amd loader on global namespace                        "  var globalDefine = global.define;\n",                        end:   "  var library = require('main');\n"+                        "  if(typeof module !== 'undefined' && module.exports) {\n"+                        // export library for node                        "    module.exports = library;\n"+                        "  } else if(globalDefine) {\n"+                        // define library for global amd loader that is already present                        "    (function (define) {\n"+                        "      define(function () { return library; });\n"+                        "    }(globalDefine));\n"+                        "  } else {\n"+                        // define library on global namespace for inline script loading                        "    global['Truss'] = library;\n"+                        "  }\n"+                        "}(this));\n"                    },                    out: '<%= pkg.name %>.js'                }            }        },        jshint: {            all: [                'Gruntfile.js',                '<%= meta.src %>',                '<%= meta.spec %>'            ],            options: {                jshintrc: '.jshintrc'            }        }    });    grunt.loadNpmTasks('grunt-contrib-jasmine');    grunt.loadNpmTasks('grunt-contrib-jshint');    grunt.loadNpmTasks('grunt-contrib-watch');    grunt.loadNpmTasks('grunt-contrib-concat');    grunt.loadNpmTasks('grunt-contrib-requirejs');    // Custom tasks    grunt.registerTask('lint', ['jshint']);    grunt.registerTask('test', ['jasmine']);    grunt.registerTask('build', ['requirejs']);    grunt.registerTask('default', ['lint', 'test', 'build']);};\ No newline at end of file+"use strict";module.exports = function( grunt ) {    // Project configuration.    grunt.initConfig({        pkg: grunt.file.readJSON('package.json'),        dirs: {            src: 'src',            spec: 'spec',            dest: 'dist/<%= pkg.name %>/<%= pkg.version %>'        },        meta : {            src   : '<%= dirs.src %>/*.js',            spec : '<%= dirs.spec %>/*.spec.js'        },        watch: {            test : {                files: ['<%= meta.src %>','<%= meta.spec %>'],                tasks: 'test'            }        },        jasmine: {            all: {                options : {                    specs : '<%= meta.spec %>',                    template: require('grunt-template-jasmine-requirejs'),                    templateOptions: {                        requireConfig: {                            baseUrl: './src'                        }                    }                }            }        },        requirejs: {            compile: {                options: {                    uglify: {                        toplevel: true,                        ascii_only: true,                        beautify: false,                        max_line_length: 100,                        no_mangle: false                    },                    baseUrl: "./src",                    name: 'vendor/almond',                    include: ['main'],                    wrap: {                        start: "(function(global, define) {\n"+                        // check for amd loader on global namespace                        "  var globalDefine = global.define;\n",                        end:   "  var library = require('main');\n"+                        "  if(typeof module !== 'undefined' && module.exports) {\n"+                        // export library for node                        "    module.exports = library;\n"+                        "  } else if(globalDefine) {\n"+                        // define library for global amd loader that is already present                        "    (function (define) {\n"+                        "      define(function () { return library; });\n"+                        "    }(globalDefine));\n"+                        "  } else {\n"+                        // define library on global namespace for inline script loading                        "    global['Truss'] = library;\n"+                        "  }\n"+                        "}(this));\n"                    },                    out: '<%= pkg.name %>-min.js'                }            },            unoptimized: {                options: {                    optimize: "none",                    baseUrl: "./src",                    name: 'vendor/almond',                    include: ['main'],                    wrap: {                        start: "(function(global, define) {\n"+                        // check for amd loader on global namespace                        "  var globalDefine = global.define;\n",                        end:   "  var library = require('main');\n"+                        "  if(typeof module !== 'undefined' && module.exports) {\n"+                        // export library for node                        "    module.exports = library;\n"+                        "  } else if(globalDefine) {\n"+                        // define library for global amd loader that is already present                        "    (function (define) {\n"+                        "      define(function () { return library; });\n"+                        "    }(globalDefine));\n"+                        "  } else {\n"+                        // define library on global namespace for inline script loading                        "    global['Truss'] = library;\n"+                        "  }\n"+                        "}(this));\n"                    },                    out: '<%= pkg.name %>.js'                }            }        },        jshint: {            all: [                'Gruntfile.js',                '<%= meta.src %>',                '<%= meta.spec %>'            ],            options: {                jshintrc: '.jshintrc'            }        }    });    grunt.loadNpmTasks('grunt-contrib-jasmine');    grunt.loadNpmTasks('grunt-contrib-jshint');    grunt.loadNpmTasks('grunt-contrib-watch');    grunt.loadNpmTasks('grunt-contrib-concat');    grunt.loadNpmTasks('grunt-contrib-requirejs');    // Custom tasks    grunt.registerTask('lint', ['jshint']);    grunt.registerTask('test', ['jasmine']);    grunt.registerTask('build', ['requirejs']);    grunt.registerTask('default', ['lint', 'test', 'build']);};\ No newline at end of filediff --git Truss-min.js Truss-min.jsindex 8b972ce..f9d5705 100644--- Truss-min.js+++ Truss-min.js@@ -87,17 +87,21 @@ else{i=t[n];if(this.isFunction(this.model)){r=this.model.create(),this.getModels ("reset")},getById:function(e){return r.call(this,"id",e)},getByText:function(e){return r.call(this,"text" ,e)},removeByText:function(e){i.call(this,"text",e)},removeById:function(e){i.call(this,"id",e)},getModels :function(){return this.models},setCurrentModel:function(e){s=e},getCurrentModel:function(){return s}-})}),t("View",["Base"],function(e){function n(){return document.getElementsByTagName("body")[0]}var t="div"-;return e.construct({tagName:"div",start:function(){this.tagName=this.options&&this.options.tagName?this-.options.tagName:this.tagName},setElement:function(e){this.element=e},removeElement:function(){arguments-[0]&&arguments[0].nodeType===1&&this.setElement(arguments[0]),this.element.parentNode&&this.element.parentNode-.removeChild(this.element),this.element=null,delete this.element},replaceElement:function(e){var t=this-.element;arguments[1]&&arguments[1].nodeType===1&&(t=arguments[1]),t&&t.parentNode&&(this.oldElement=-t.parentNode.replaceChild(e,t))},make:function(){var e=[].slice.call(arguments),t=e[0]||this.tagName,-n=e[1],r=e[2],i,s,o=document.createElement(t);e.length===2&&this.isObject(n)&&(n=undefined,r=e[1]);if(typeof-n!="undefined"){if(this.isNumber(n)||this.isString(n))n=document.createTextNode(n);if(this.isArray(n)-)while(i=n.shift())o.appendChild(i);else o.appendChild(n)}if(r)for(s in r)r.hasOwnProperty(s)&&(o[s]=-r[s],s in o.attributes||o.setAttribute(s,r[s]));return o}})}),t("main",["Base","events","mediator","utils"-,"Collection","Model","View"],function(e,t,n,r,i,s,o){return{events:t,mediator:n,utils:r,Collection:i-,Model:s,View:o}});var s=i("main");typeof module!="undefined"&&module.exports?module.exports=s:n?function(-e){e(function(){return s})}(n):e.Truss=s})(this);\ No newline at end of file+})}),t("View",["Base"],function(e){var t="div";return e.construct({tagName:"div",start:function(){this+.tagName=this.options&&this.options.tagName?this.options.tagName:this.tagName},setElement:function(e)+{this.element=e},removeElement:function(){arguments[0]&&arguments[0].nodeType===1&&this.setElement(arguments+[0]),this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.stopListening(),+this.element=null,delete this.element},destroy:function(){this.model&&this.collection&&this.collection+.removeById(this.model.get("id")),this.removeElement()},replaceElement:function(e){var t=this.element+;arguments[1]&&arguments[1].nodeType===1&&(t=arguments[1]),t&&t.parentNode&&(this.oldElement=t.parentNode+.replaceChild(e,t))},addListener:function(e,t){var n=arguments[2]&&arguments[2].nodeType===1?arguments+[2]:this.element;if(n.addEventListener){var r=e.type||e;n.addEventListener(r,function(n){e.key&&e.key==+n.keyCode?t(n):e.key||t(n)})}},stopListening:function(){this.element.removeEventListener("*")},make:function(+){var e=[].slice.call(arguments),t=e[0]||this.tagName,n=e[1],r=e[2],i,s,o=document.createElement(t);e+.length===2&&this.isObject(n)&&(n=undefined,r=e[1]);if(typeof n!="undefined"){if(this.isNumber(n)||this+.isString(n))n=document.createTextNode(n);if(this.isArray(n))while(i=n.shift())o.appendChild(i);else o+.appendChild(n)}if(r)for(s in r)r.hasOwnProperty(s)&&(o[s]=r[s],s in o.attributes||o.setAttribute(s,r+[s]));return o}})}),t("main",["Base","events","mediator","utils","Collection","Model","View"],function(+e,t,n,r,i,s,o){return{events:t,mediator:n,utils:r,Collection:i,Model:s,View:o}});var s=i("main");typeof+module!="undefined"&&module.exports?module.exports=s:n?function(e){e(function(){return s})}(n):e.Truss=+s})(this);\ No newline at end of filediff --git spec/View.spec.js spec/View.spec.jsindex f62467f..418a692 100644--- spec/View.spec.js+++ spec/View.spec.js@@ -1,356 +1 @@-require( ['View'], function ( View ) {--	describe("View", function () {-		var view = null;--		describe("When a view is created without options", function () {-			it("Should not throw an error", function () {-				expect(function () {-					view = View.create();-				}).not.toThrow();-			});-		});-		describe("When a view is created without options", function () {-			beforeEach(function () {-				view = View.create();-			});-			afterEach(function () {-				view = null;-			});-			describe("When make is called with no arguments", function () {-				var html;-				beforeEach(function () {-					html = view.make();-				});-				it("Should make a div element", function () {-					expect(html.nodeName.toLowerCase()).toEqual("div");-				});-			});-			describe("When make is called with the tag name argument 'p'", function () {-				var html,-					name = "p";-				beforeEach(function () {-					html = view.make(name);-				});-				it("Should make a p element", function () {-					expect(html.nodeName.toLowerCase()).toEqual(name);-				});-			});-			describe("When make is called with the tag name argument 'p'", function () {-				describe("When make is called with the contents argument 'span' element", function () {-					var html,-						name = "p";-					beforeEach(function () {-						html = view.make(name, document.createElement("span"));-					});-					it("Should make a p element", function () {-						expect(html.nodeName.toLowerCase()).toEqual(name);-					});-					it("Should make a p element with a nested span element", function () {-						expect(html.firstChild.nodeName.toLowerCase()).toEqual("span");-					});-				});--			});-			describe("When make is called with the tag name argument 'p'", function () {-				describe("When make is called with the contents argument 'span' element", function () {-					describe("When make is called with an id 'el1' attr", function () {-						describe("When make is called with a class 'element attr' attr", function () {-							var html,-								name = "p",-								contents = "span",-								attrs = {-									id: "el1",-									"class": "element attr"-								};-							beforeEach(function () {-								html = view.make(name, document.createElement(contents), attrs);-							});-							it("Should make a p element", function () {-								expect(html.nodeName.toLowerCase()).toEqual(name);-							});-							it("Should make a p element with a nested span element", function () {-								expect(html.firstChild.nodeName.toLowerCase()).toEqual("span");-							});-							it("Should add id='el1'to the p element", function () {-								expect(html.id).toEqual("el1");-							});-							it("Should add class='element attr'to the p element", function () {-								expect(html.className).toEqual("element attr");-							});-						});-					});-				});-				describe("When the contents argument is another make call with no arguments", function () {-					describe("When make is called with an id 'el1' attr", function () {-						describe("When make is called with a class 'element attr' attr", function () {-							var html,-								name = "p",-								attrs = {-									id: "el1",-									"class" : "element attr"-								};-							beforeEach(function () {-								html = view.make(name, view.make(), attrs);-							});-							it("Should make a p element", function () {-								expect(html.nodeName.toLowerCase()).toEqual(name);-							});-							it("Should make a p element with a nested div element", function () {-								expect(html.firstChild.nodeName.toLowerCase()).toEqual("div");-							});-							it("Should add id='el1'to the p element", function () {-								expect(html.id).toEqual("el1");-							});-							it("Should add class='element attr'to the p element", function () {-								expect(html.className).toEqual("element attr");-							});-						});-					});-				});-				describe("When the contents argument is the string 'Hello World'", function () {-					describe("When make is called with an id 'el1' attr", function () {-						describe("When make is called with a class 'element attr' attr", function () {-							var html,-								name = "p",-								contents = "Hello World",-								attrs = {-									id: "el1",-									"class": "element attr"-								};-							beforeEach(function () {-								html = view.make(name, contents, attrs);-							});-							it("Should make a p element", function () {-								expect(html.nodeName.toLowerCase()).toEqual(name);-							});-							it("Should make a p element with the text 'Hello World'", function () {-								expect(html.innerText).toEqual("Hello World");-							});-							it("Should add id='el1'to the p element", function () {-								expect(html.id).toEqual("el1");-							});-							it("Should add class='element attr'to the p element", function () {-								expect(html.className).toEqual("element attr");-							});-						});-					});-				});-				describe("When the contents argument is the number 137", function () {-					describe("When make is called with an id 'el1' attr", function () {-						describe("When make is called with a class 'element attr' attr", function () {-							var html,-								name = "p",-								contents = 137,-								attrs = {-									id: "el1",-									"class": "element attr"-								};-							beforeEach(function () {-								html = view.make(name, contents, attrs);-							});-							it("Should make a p element", function () {-								expect(html.nodeName.toLowerCase()).toEqual(name);-							});-							it("Should make a p element with the text '137'", function () {-								expect(html.innerText).toEqual("137");-							});-							it("Should add id='el1'to the p element", function () {-								expect(html.id).toEqual("el1");-							});-							it("Should add class='element attr'to the p element", function () {-								expect(html.className).toEqual("element attr");-							});-						});-					});-				});-				describe("When the contents argument is the number 0", function () {-					describe("When make is called with an id 'el1' attr", function () {-						describe("When make is called with a class 'element attr' attr", function () {-							var html,-								name = "p",-								contents = 0,-								attrs = {-									id: "el1",-									"class": "element attr"-								};-							beforeEach(function () {-								html = view.make(name, contents, attrs);-							});-							it("Should make a p element", function () {-								expect(html.nodeName.toLowerCase()).toEqual(name);-							});-							it("Should make a p element with the text '0'", function () {-								expect(html.innerText).toEqual("0");-							});-							it("Should add id='el1'to the p element", function () {-								expect(html.id).toEqual("el1");-							});-							it("Should add class='element attr'to the p element", function () {-								expect(html.className).toEqual("element attr");-							});-						});-					});-				});-				describe("When the contents argument is an array of make calls, [make('em'), make('span')]", function () {-					describe("When make is called with an id 'el1' attr", function () {-						describe("When make is called with a class 'element attr' attr", function () {-							var html,-								name = "p",-								attrs = {-									id: "el1",-									"class": "element attr"-								};-							beforeEach(function () {-								html = view.make(name, [view.make("em"), view.make("span")], attrs);-							});-							it("Should make a p element", function () {-								expect(html.nodeName.toLowerCase()).toEqual(name);-							});-							it("Should make a p element with a first child em element", function () {-								expect(html.firstChild.nodeName.toLowerCase()).toEqual("em");-							});-							it("Should make a p element with a second child span element", function () {-								expect(html.children[1].nodeName.toLowerCase()).toEqual("span");-							});-							it("Should add id='el1'to the p element", function () {-								expect(html.id).toEqual("el1");-							});-							it("Should add class='element attr'to the p element", function () {-								expect(html.className).toEqual("element attr");-							});-						});-					});-				});-			});-			describe("When the NO contents argument is supplied", function () {-				describe("When make is called with an id 'el1' attr", function () {-					describe("When make is called with a class 'element attr' attr", function () {-						var html,-							name = "p",-							attrs = {-								id: "el1",-								"class": "element attr"-							};-						beforeEach(function () {-							html = view.make(name, attrs);-						});-						it("Should make a p element", function () {-							expect(html.nodeName.toLowerCase()).toEqual(name);-						});-						it("Should add id='el1'to the p element", function () {-							expect(html.id).toEqual("el1");-						});-						it("Should add class='element attr'to the p element", function () {-							expect(html.className).toEqual("element attr");-						});-					});-				});-			});--			describe("When make is called with attrs, unknown: 'test'", function () {-				var html,-					name = "p",-					contents = "span",-					attrs = {-						unknown: "test"-					};-				beforeEach(function () {-					html = view.make(name, view.make(), attrs);-				});-				it("Should add unknown='test' element", function () {-					expect(html.unknown).toEqual("test");-				});-			});--			describe('calling setElement with an element', function () {-				var element;-				beforeEach(function () {-					element = view.make('div');-					view.setElement(element);-				});-				it('adds the element to the view object', function () {-					expect(view.element).toEqual(element);-				});-			});--			describe('Calling removeElement', function () {--				describe('with no arguments', function () {-					var parent,-						element;-					beforeEach(function () {-						parent = view.make('div');-						element = view.make('p');-						parent.appendChild(element);-						view.setElement(element);-						view.removeElement();-					});--					it('removes the element from the view', function () {-						expect(view.element).toEqual(null);-					});-					it('removes the element from the parent', function () {-						expect(parent.hasChildNodes()).toEqual(false);-					});-				});--				describe('with an element', function () {-					var parent,-						element;-					beforeEach(function () {-						parent = view.make('div');-						element = view.make('p');-						parent.appendChild(element);-						view.removeElement(element);-					});-					it('removes the element from the parent', function () {-						expect(parent.hasChildNodes()).toEqual(false);-					});-				});-			});--			describe('Calling replaceElement', function () {--				describe('with a replacement element', function () {-					var parent,-						element,-						replacement;-					beforeEach(function () {-						parent = view.make('div');-						element = view.make('p');-						parent.appendChild(element);-						replacement = view.make('span');-						view.setElement(element);-						view.replaceElement(replacement);-					});-					it('replaces the view element with the replacement', function () {-						expect(parent.firstChild).toEqual(replacement);-					});-					it('sets old element', function () {-						expect(view.oldElement.nodeName).toEqual('P');-					});-				});--				describe('with a replacement element and replacee', function () {-					var parent,-						replacee,-						replacement;-					beforeEach(function () {-						parent = view.make('div');-						replacee = view.make('p');-						parent.appendChild(replacee);-						replacement = view.make('span');-						view.replaceElement(replacement, replacee);-					});-					it('replaces the view element with the replacement', function () {-						expect(parent.firstChild).toEqual(replacement);-					});-					it('sets old element', function () {-						expect(view.oldElement.nodeName).toEqual('P');-					});-				});-			});-		});-	});-});+require( ['View'], function ( View ) {    describe("View", function () {        var view = null;        describe("When a view is created without options", function () {            it("Should not throw an error", function () {                expect(function () {                    view = View.create();                }).not.toThrow();            });        });        describe("When a view is created without options", function () {            beforeEach(function () {                view = View.create();            });            afterEach(function () {                view = null;            });            describe("When make is called with no arguments", function () {                var html;                beforeEach(function () {                    html = view.make();                });                it("Should make a div element", function () {                    expect(html.nodeName.toLowerCase()).toEqual("div");                });            });            describe("When make is called with the tag name argument 'p'", function () {                var html,                    name = "p";                beforeEach(function () {                    html = view.make(name);                });                it("Should make a p element", function () {                    expect(html.nodeName.toLowerCase()).toEqual(name);                });            });            describe("When make is called with the tag name argument 'p'", function () {                describe("When make is called with the contents argument 'span' element", function () {                    var html,                        name = "p";                    beforeEach(function () {                        html = view.make(name, document.createElement("span"));                    });                    it("Should make a p element", function () {                        expect(html.nodeName.toLowerCase()).toEqual(name);                    });                    it("Should make a p element with a nested span element", function () {                        expect(html.firstChild.nodeName.toLowerCase()).toEqual("span");                    });                });            });            describe("When make is called with the tag name argument 'p'", function () {                describe("When make is called with the contents argument 'span' element", function () {                    describe("When make is called with an id 'el1' attr", function () {                        describe("When make is called with a class 'element attr' attr", function () {                            var html,                                name = "p",                                contents = "span",                                attrs = {                                    id: "el1",                                    "class": "element attr"                                };                            beforeEach(function () {                                html = view.make(name, document.createElement(contents), attrs);                            });                            it("Should make a p element", function () {                                expect(html.nodeName.toLowerCase()).toEqual(name);                            });                            it("Should make a p element with a nested span element", function () {                                expect(html.firstChild.nodeName.toLowerCase()).toEqual("span");                            });                            it("Should add id='el1'to the p element", function () {                                expect(html.id).toEqual("el1");                            });                            it("Should add class='element attr'to the p element", function () {                                expect(html.className).toEqual("element attr");                            });                        });                    });                });                describe("When the contents argument is another make call with no arguments", function () {                    describe("When make is called with an id 'el1' attr", function () {                        describe("When make is called with a class 'element attr' attr", function () {                            var html,                                name = "p",                                attrs = {                                    id: "el1",                                    "class" : "element attr"                                };                            beforeEach(function () {                                html = view.make(name, view.make(), attrs);                            });                            it("Should make a p element", function () {                                expect(html.nodeName.toLowerCase()).toEqual(name);                            });                            it("Should make a p element with a nested div element", function () {                                expect(html.firstChild.nodeName.toLowerCase()).toEqual("div");                            });                            it("Should add id='el1'to the p element", function () {                                expect(html.id).toEqual("el1");                            });                            it("Should add class='element attr'to the p element", function () {                                expect(html.className).toEqual("element attr");                            });                        });                    });                });                describe("When the contents argument is the string 'Hello World'", function () {                    describe("When make is called with an id 'el1' attr", function () {                        describe("When make is called with a class 'element attr' attr", function () {                            var html,                                name = "p",                                contents = "Hello World",                                attrs = {                                    id: "el1",                                    "class": "element attr"                                };                            beforeEach(function () {                                html = view.make(name, contents, attrs);                            });                            it("Should make a p element", function () {                                expect(html.nodeName.toLowerCase()).toEqual(name);                            });                            it("Should make a p element with the text 'Hello World'", function () {                                expect(html.innerText).toEqual("Hello World");                            });                            it("Should add id='el1'to the p element", function () {                                expect(html.id).toEqual("el1");                            });                            it("Should add class='element attr'to the p element", function () {                                expect(html.className).toEqual("element attr");                            });                        });                    });                });                describe("When the contents argument is the number 137", function () {                    describe("When make is called with an id 'el1' attr", function () {                        describe("When make is called with a class 'element attr' attr", function () {                            var html,                                name = "p",                                contents = 137,                                attrs = {                                    id: "el1",                                    "class": "element attr"                                };                            beforeEach(function () {                                html = view.make(name, contents, attrs);                            });                            it("Should make a p element", function () {                                expect(html.nodeName.toLowerCase()).toEqual(name);                            });                            it("Should make a p element with the text '137'", function () {                                expect(html.innerText).toEqual("137");                            });                            it("Should add id='el1'to the p element", function () {                                expect(html.id).toEqual("el1");                            });                            it("Should add class='element attr'to the p element", function () {                                expect(html.className).toEqual("element attr");                            });                        });                    });                });                describe("When the contents argument is the number 0", function () {                    describe("When make is called with an id 'el1' attr", function () {                        describe("When make is called with a class 'element attr' attr", function () {                            var html,                                name = "p",                                contents = 0,                                attrs = {                                    id: "el1",                                    "class": "element attr"                                };                            beforeEach(function () {                                html = view.make(name, contents, attrs);                            });                            it("Should make a p element", function () {                                expect(html.nodeName.toLowerCase()).toEqual(name);                            });                            it("Should make a p element with the text '0'", function () {                                expect(html.innerText).toEqual("0");                            });                            it("Should add id='el1'to the p element", function () {                                expect(html.id).toEqual("el1");                            });                            it("Should add class='element attr'to the p element", function () {                                expect(html.className).toEqual("element attr");                            });                        });                    });                });                describe("When the contents argument is an array of make calls, [make('em'), make('span')]", function () {                    describe("When make is called with an id 'el1' attr", function () {                        describe("When make is called with a class 'element attr' attr", function () {                            var html,                                name = "p",                                attrs = {                                    id: "el1",                                    "class": "element attr"                                };                            beforeEach(function () {                                html = view.make(name, [view.make("em"), view.make("span")], attrs);                            });                            it("Should make a p element", function () {                                expect(html.nodeName.toLowerCase()).toEqual(name);                            });                            it("Should make a p element with a first child em element", function () {                                expect(html.firstChild.nodeName.toLowerCase()).toEqual("em");                            });                            it("Should make a p element with a second child span element", function () {                                expect(html.children[1].nodeName.toLowerCase()).toEqual("span");                            });                            it("Should add id='el1'to the p element", function () {                                expect(html.id).toEqual("el1");                            });                            it("Should add class='element attr'to the p element", function () {                                expect(html.className).toEqual("element attr");                            });                        });                    });                });            });            describe("When the NO contents argument is supplied", function () {                describe("When make is called with an id 'el1' attr", function () {                    describe("When make is called with a class 'element attr' attr", function () {                        var html,                            name = "p",                            attrs = {                                id: "el1",                                "class": "element attr"                            };                        beforeEach(function () {                            html = view.make(name, attrs);                        });                        it("Should make a p element", function () {                            expect(html.nodeName.toLowerCase()).toEqual(name);                        });                        it("Should add id='el1'to the p element", function () {                            expect(html.id).toEqual("el1");                        });                        it("Should add class='element attr'to the p element", function () {                            expect(html.className).toEqual("element attr");                        });                    });                });            });            describe("When make is called with attrs, unknown: 'test'", function () {                var html,                    name = "p",                    contents = "span",                    attrs = {                        unknown: "test"                    };                beforeEach(function () {                    html = view.make(name, view.make(), attrs);                });                it("Should add unknown='test' element", function () {                    expect(html.unknown).toEqual("test");                });            });            describe('calling setElement with an element', function () {                var element;                beforeEach(function () {                    element = view.make('div');                    view.setElement(element);                });                it('adds the element to the view object', function () {                    expect(view.element).toEqual(element);                });            });            describe('Calling removeElement', function () {                var spyStopListen;                describe('with no arguments', function () {                    var parent,                        element;                    beforeEach(function () {                        spyStopListen = spyOn(view, 'stopListening');                        parent = view.make('div');                        element = view.make('p');                        parent.appendChild(element);                        view.setElement(element);                        view.removeElement();                    });                    it('removes the element from the view', function () {                        expect(view.element).toEqual(null);                    });                    it('removes the element from the parent', function () {                        expect(parent.hasChildNodes()).toEqual(false);                    });                    it('will call stopListening', function () {                        expect(spyStopListen).toHaveBeenCalled();                    });                });                describe('with an element', function () {                    var parent,                        element;                    beforeEach(function () {                        spyStopListen = spyOn(view, 'stopListening');                        parent = view.make('div');                        element = view.make('p');                        parent.appendChild(element);                        view.removeElement(element);                    });                    it('removes the element from the parent', function () {                        expect(parent.hasChildNodes()).toEqual(false);                    });                    it('will call stopListening', function () {                        expect(spyStopListen).toHaveBeenCalled();                    });                });            });            describe('Calling replaceElement', function () {                describe('with a replacement element', function () {                    var parent,                        element,                        replacement;                    beforeEach(function () {                        parent = view.make('div');                        element = view.make('p');                        parent.appendChild(element);                        replacement = view.make('span');                        view.setElement(element);                        view.replaceElement(replacement);                    });                    it('replaces the view element with the replacement', function () {                        expect(parent.firstChild).toEqual(replacement);                    });                    it('sets old element', function () {                        expect(view.oldElement.nodeName).toEqual('P');                    });                });                describe('with a replacement element and replacee', function () {                    var parent,                        replacee,                        replacement;                    beforeEach(function () {                        parent = view.make('div');                        replacee = view.make('p');                        parent.appendChild(replacee);                        replacement = view.make('span');                        view.replaceElement(replacement, replacee);                    });                    it('replaces the view element with the replacement', function () {                        expect(parent.firstChild).toEqual(replacement);                    });                    it('sets old element', function () {                        expect(view.oldElement.nodeName).toEqual('P');                    });                });            });            describe('calling destroy', function () {                var spyRemove,                    mockId = 'mockId',                    mockModel = {                        id: mockId,                        get: function (name) { return this[name]; }                    },                    mockCollection = {                        models: [mockModel],                        removeById: jasmine.createSpy('removeById')                    };                beforeEach(function () {                    spyRemove = spyOn(view, 'removeElement');                    view.model = mockModel;                    view.collection = mockCollection;                    view.destroy();                });                it('will call collection.removeById with the id of the model owned by the view', function () {                    expect(mockCollection.removeById).toHaveBeenCalledWith(mockId);                });                it('will call removeElement', function () {                    expect(spyRemove).toHaveBeenCalled();                });            });            describe('addListener', function () {                describe('with event name, handler and element', function () {                    var evtName = 'click',                        element,                        handler = jasmine.createSpy('handler'),                        evt;                    beforeEach(function () {                        element = view.make('p');                        evt = document.createEvent("Event");                        evt.initEvent(evtName);                        view.addListener(evtName, handler, element);                        element.dispatchEvent(evt);                    });                    it('binds handler to named event on element', function () {                        expect(handler).toHaveBeenCalledWith(evt);                    });                });                describe('without element', function () {                    var evtName = 'click',                        element,                        handler = jasmine.createSpy('handler'),                        evt;                    beforeEach(function () {                        element = view.make('p');                        view.setElement(element);                        evt = document.createEvent("Event");                        evt.initEvent(evtName);                        view.addListener(evtName, handler);                        element.dispatchEvent(evt);                    });                    it('binds handler to named event on element', function () {                        expect(handler).toHaveBeenCalledWith(evt);                    });                });                describe('event name is plain object with a key code', function () {                    var evtName = {type: 'keyup', key: 13},                        element,                        handler = jasmine.createSpy('handler'),                        evt;                    beforeEach(function () {                        element = view.make('p');                        view.setElement(element);                        evt = document.createEvent("Event");                        evt.keyCode = 13;                        evt.initEvent(evtName.type);                        view.addListener(evtName, handler);                        element.dispatchEvent(evt);                    });                    it('binds handler to named event on element', function () {                        expect(handler).toHaveBeenCalledWith(evt);                    });                });            });        });    });});\ No newline at end of filediff --git src/View.js src/View.jsindex d1837c3..017ee86 100644--- src/View.js+++ src/View.js@@ -1 +1 @@-define (['Base'], function ( Base ) {    var TAGNAME = 'div';    function getRootNode () {        return document.getElementsByTagName("body")[0];    }    // Build the constructor    return Base.construct({        tagName: 'div',        start: function () {            this.tagName = this.options && this.options.tagName ? this.options.tagName : this.tagName;        },        setElement: function (element) {            this.element = element;        },        removeElement: function () {            if (arguments[0] && arguments[0].nodeType === 1) {                this.setElement(arguments[0]);            }            if (this.element.parentNode) {                this.element.parentNode.removeChild(this.element);            }            this.element = null;            delete this.element;        },        replaceElement: function (replacement) {            var replacee = this.element;            if (arguments[1] && arguments[1].nodeType === 1) {                replacee = arguments[1];            }            if (replacee && replacee.parentNode) {                this.oldElement = replacee.parentNode.replaceChild(replacement, replacee);            }        },        make: function () {            // All arguments are optional            var args = [].slice.call(arguments),                name = args[0] || this.tagName,                contents = args[1],                attrs = args[2],                i,                attr,                tag = document.createElement(name);            if (args.length === 2 && this.isObject(contents)) {                contents = undefined;                attrs = args[1];            }            // Add the contents            if (typeof contents !== "undefined") {                if (this.isNumber(contents) || this.isString(contents)) {                    // If the contents is a Number or a String,                    // parse it to a textnode                    contents = document.createTextNode(contents);                }                if (this.isArray(contents)) {                    // If our contents is an array,                    // append each one to the tag                    while ( i = contents.shift() ) {                        tag.appendChild(i);                    }                } else {                    tag.appendChild(contents);                }            }            // Add the attributes            if ( attrs ) {                for ( attr in attrs ) {                    if (attrs.hasOwnProperty( attr )) {                        // Add each attribute to the tag                        tag[ attr ] = attrs[ attr ];                        if ( !( attr in tag.attributes ) ) {                            // If the attribute wasnt't successfully added,                            // try again with setAttribute                            tag.setAttribute( attr, attrs[ attr ] );                        }                    }                }            }            // Finally return the new tag            return tag;        }    });});\ No newline at end of file+define (['Base'], function ( Base ) {    var TAGNAME = 'div';    // Build the constructor    return Base.construct({        tagName: 'div',        start: function () {            this.tagName = this.options && this.options.tagName ? this.options.tagName : this.tagName;        },        setElement: function (element) {            this.element = element;        },        removeElement: function () {            if (arguments[0] && arguments[0].nodeType === 1) {                this.setElement(arguments[0]);            }            if (this.element.parentNode) {                this.element.parentNode.removeChild(this.element);            }            this.stopListening();            this.element = null;            delete this.element;        },        destroy: function () {            if (this.model && this.collection) {                this.collection.removeById(this.model.get("id"));            }            this.removeElement();        },        replaceElement: function (replacement) {            var replacee = this.element;            if (arguments[1] && arguments[1].nodeType === 1) {                replacee = arguments[1];            }            if (replacee && replacee.parentNode) {                this.oldElement = replacee.parentNode.replaceChild(replacement, replacee);            }        },        addListener: function (eventName, handler) {            var el = arguments[2] && arguments[2].nodeType === 1 ? arguments[2] : this.element;            if (el.addEventListener) {                var evt = eventName.type || eventName;                el.addEventListener(evt, function (e) {                    if (eventName.key && (eventName.key == e.keyCode)) {                        handler(e);                    } else if (!eventName.key) {                        handler(e);                    }                });            }        },        stopListening: function () {            this.element.removeEventListener('*');        },        make: function () {            // All arguments are optional            var args = [].slice.call(arguments),                name = args[0] || this.tagName,                contents = args[1],                attrs = args[2],                i,                attr,                tag = document.createElement(name);            if (args.length === 2 && this.isObject(contents)) {                contents = undefined;                attrs = args[1];            }            // Add the contents            if (typeof contents !== "undefined") {                if (this.isNumber(contents) || this.isString(contents)) {                    // If the contents is a Number or a String,                    // parse it to a textnode                    contents = document.createTextNode(contents);                }                if (this.isArray(contents)) {                    // If our contents is an array,                    // append each one to the tag                    while ( i = contents.shift() ) {                        tag.appendChild(i);                    }                } else {                    tag.appendChild(contents);                }            }            // Add the attributes            if ( attrs ) {                for ( attr in attrs ) {                    if (attrs.hasOwnProperty( attr )) {                        // Add each attribute to the tag                        tag[ attr ] = attrs[ attr ];                        if ( !( attr in tag.attributes ) ) {                            // If the attribute wasnt't successfully added,                            // try again with setAttribute                            tag.setAttribute( attr, attrs[ attr ] );                        }                    }                }            }            // Finally return the new tag            return tag;        }    });});\ No newline at end of file