(function () { /** * @license almond 0.2.9 Copyright (c) 2011-2014, 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, jsSuffixRegExp = /\.js$/; 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, lastIndex, 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 = name.split('/'); lastIndex = name.length - 1; // Node .js allowance: if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); } name = baseParts.concat(name); //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 = [], callbackType = typeof callback, usingExports; //Use name if no relName relName = relName || name; //Call the callback to define the module, if necessary. if (callbackType === 'undefined' || callbackType === '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 ? callback.apply(defined[name], args) : undefined; 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 (config.deps) { req(config.deps, config.callback); } if (!callback) { return; } 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) { return req(cfg); }; /** * Expose module registry for debugging and tooling */ requirejs._defined = defined; 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("bower_components/almond/almond", function(){}); define( 'Seed/helpers',[],function( ) { // dirty, todo Function.prototype.bind || ( Function.prototype.bind = function( scope ) { var self = this return ( function() { return ( self.apply( scope, arguments ) ) } ) } ) return { capitalize: function( s ) { return ( s.charAt( 0 ).toUpperCase( ) + s.slice( 1 ) ) }, remove: function( a, v ) { for ( var i = a.length; i--; ) { if ( a[ i ] === v ) a.splice( i, 1 ) } return a }, clone: function( o ) { // clones an object (only lvl 1, see hardClone) var res = {}; for ( var i in o ) if ( o.hasOwnProperty( i ) ) res[ i ] = o[ i ] return res }, extend: function( o ) { for ( var i = 1, n = arguments.length; i < n; i++ ) { var e = typeof( arguments[ i ] ) === 'object' || typeof( arguments[ i ] ) === 'function' ? arguments[ i ] : {} for ( var j in e ) if ( e.hasOwnProperty( j ) ) { o[ j ] = e[ j ] } } return o }, find: function( a, f ) { for ( var i = 0, n = a.length; i < n; i++ ) { if ( f( a[ i ], i ) ) return a[ i ] } return false } } } ); define( 'Seed/extendHooker',[ './helpers' ], function( _ ) { var ExtendHooker = function( ) { } ExtendHooker.prototype = { getHooks: function( ) { }, hookify: function( Extendable ) { var hooks = Extendable.__hooks = [ ] Extendable.registerHook = function( hook ) { Extendable.__hooks.push( hook ) } Extendable.hasHook = function( hook ) { if ( typeof hook === 's' ) { return !!_.find( hooks, function( h ) { return h.id === hook } ) } return !!_.find( hooks, function( h ) { return h === hook } ) } Extendable.unregisterHook = function( hook ) { return _.remove( hooks, hook ) } } } return new ExtendHooker } ); define( 'Seed/extendHooks/plusMinusExtendHook',[ '../helpers' ], function( _ ) { /** * Mix two params, to get the better mix * * @private * @param {String|Array|Object|Number} before * @param {String|Array|Object|Number} after * @returns an extended object if before and after are objects */ var extendReturn = function( before, after ) { if ( typeof( after ) === "undefined" ) { return before; } if ( typeof( after ) === "object" && typeof( before ) === "object" ) { return _.extend( {}, before, after ); } return after; }; /** * Two Fns executed in once * * @private * @param {Object|Function} before a function or object that is executed before * @param {Object|Function} after a function or object that is executed before * @returns {Object|Function} a function that calls before and then after */ var mergeFns = function( before, after ) { if ( typeof( before ) === "function" || typeof( after ) === "function" ) { return function( ) { var beforeR = ( typeof( before ) === "function" ? before.apply( this, arguments ) : before ), afterR = ( typeof( after ) === "function" ? after.apply( this, arguments ) : after ); return extendReturn( beforeR, afterR ); }; } else { return extendReturn( before, after ); } }; /** * extend an object with +/- convention * * @private * @param {Object} oldObj an object to extend from * @param {Object} a key-value object to add to oldObject, with +key and -key * @returns {Object} an extended object */ return { name: 'plusMinus', handle: function( oldObj, extendObj ) { // var resObj = {}, var resObj = oldObj, nullFn = function( ) {}; for ( var i in extendObj ) if ( extendObj.hasOwnProperty( i ) ) { var reg = /(^\+|^-)(.*)/g; if ( reg.test( i ) ) { // merge fns var key = i.replace( reg, "$2" ), old = oldObj[ key ] || nullFn, extFn = extendObj[ i ]; switch ( i.charAt( 0 ) ) { case "+": resObj[ key ] = mergeFns( old, extFn ); break; case "-": resObj[ key ] = mergeFns( extFn, old ); break; } delete oldObj[ i ] } else { // merge object resObj[ i ] = extendObj[ i ]; } } return resObj; } } } ); define('Seed/extendHooks/accessors/TypeChecker',[],function( ) { Array.isArray = Array.isArray || function( o ) { return Object.prototype.toString.call( o ) == "[object Array]" } Function.prototype.bind || ( Function.prototype.bind = function( scope ) { var self = this; return ( function( ) { return ( self.apply( scope, arguments ) ); } ); } ) var TypeChecker = function( ) { this.is = this.is.bind( this ) } TypeChecker.prototype = { is: function( type, arg ) { if ( arg !== null && typeof arg !== 'undefined' && typeof arg.isTypeOf === 'function' ) return arg.isTypeOf( type ) if ( this[ type ] ) // check if this type is defined here return this[ type ]( arg ) || false; return typeof arg === type.toLowerCase( ) }, Truthy: function( arg ) { return !! arg }, Falsy: function( arg ) { return !! arg }, Array: function( a ){ return Array.isArray( a ) }, Point: function( f ) { return f && f.isPoint }, Valid: function( t ) { return typeof t !== 'undefined' }, defined: function( o ){ return typeof o !== 'undefined' }, //From jQuery PlainObject: function( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well var hasOwnProperty = Object.prototype.hasOwnProperty, toString = Object.prototype.toString; if ( !obj || toString.call( obj ) !== '[object Object]' || obj.nodeType || obj.setInterval ) { return false; } // Not own constructor property must be Object if ( obj.constructor && !hasOwnProperty.call( obj, 'constructor' ) && !hasOwnProperty.call( obj.constructor.prototype, 'isPrototypeOf' ) ) { return false; } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || hasOwnProperty.call( obj, key ); }, isStructure: function( structure, obj ){ var error if ( ! this.is( 'PlainObject', obj ) ){ error = 'TypeChecker: Object ' + obj + ' is not a plain Object' return false } for ( var key in structure ) if ( structure.hasOwnProperty( key ) ){ var type = structure[ key ] if ( ! key in obj ) error = 'TypeChecker: Key ' + key + ' is not in ' + object if ( this.is( 'PlainObject', structure[ key ] )) // if value is a plain objet, reccursive check return this.isStructure( structure[ key ], obj[ key ]) if ( ! this.is( type, obj[ key ] ) ) error = 'TypeChecker: Key ' + key + ' is not in ' + object } if ( error ){ throw new Error( error ) return false } return true }, Profile: function( p ){ return this.isStructure({ label: 'String', id: 'String' }, p ) }, BenchmarkRawData: function( d ){ return this.isStructure({ settings: 'PlainObject', data: { W: 'PlainObject', M: 'PlainObject' } }, d ) } }; return TypeChecker } ); define( 'Seed/extendHooks/accessors/defaultTypeChecker',[ './TypeChecker' ], function( TypeChecker ){ var typeChecker = ( new TypeChecker ) return typeChecker }); define( 'Seed/extendHooks/accessorsExtendHook',[ './accessors/defaultTypeChecker', '../helpers' ], function( defaultTypeChecker, _, Seed ) { var AccessorHandler = function( oldPrototype, accessorString, extendObj, typeChecker ){ this.id = 'accessors' this.accessorString = accessorString this.extendObj = extendObj this.typeChecker = typeChecker this.typeChecker.is = this.typeChecker.is.bind( this.typeChecker ) this.oldPrototype = oldPrototype this.create( ) } AccessorHandler.prototype = { create: function( ){ var firstChar = this.accessorString.charAt( 0 ), isPrivate = ( firstChar === '-' ), isPublic = ! isPrivate, accessorString = ( firstChar === '-' || firstChar === '+' ) ? this.accessorString.slice( 1 ) : this.accessorString, // remove + and - accessorStringSplit = accessorString.split( '|' ), type = accessorStringSplit[ 1 ], name = accessorStringSplit[ 0 ], capitalizedName = _.capitalize( name ), prefix = ( isPrivate ? '_' : '' ), getterName = prefix + 'get' + capitalizedName, setterName = prefix + 'set' + capitalizedName, accessorName = prefix + name, typeChecker = this.typeChecker, self = this, error // console.log( this.getExtendHookConfiguration( ).allAccessors ) // console.log( name, this.accessorString) if ( !_.find( this.getExtendHookConfiguration( ).allAccessors, function( x ){ return x } ) ) // console.log( 'accessorsExtendHook - erasing parent accessors ' + name ) // else this.getExtendHookConfiguration( ).allAccessors.push( name ) this.addMethod( getterName, function( ) { return this[ accessorName ] } ) if ( type ) this.addMethod( setterName, function( v ) { if ( self.typeChecker.is( type, v ) ){ this[ accessorName ] = v return v } else { try { error = JSON.stringify( v ) + ' is not a ' + type } catch(e ){ } debugger // dev mode, TODO throw new Error( error ) } } ) else this.addMethod( setterName, function( v ) { this[ accessorName ] = v return v }) }, getOldObj: function( ) { return this.oldPrototype }, getExtendObj: function( ) { return this.extendObj }, getExtendHookConfiguration: function( ) { return this.getOldObj( ).__extendHooks[ this.id ] }, addMethod: function( methodName, f ){ if ( ! this.extendObj[ methodName ] ) this.oldPrototype[ methodName ] = f // else // console.log( 'accessorsExtendHook - ' + methodName + ' is define in extendObj' ) } } var AccessorExtendHook = function( ){ this.id = 'accessors' this.handle = this.handle.bind( this ) this.typeChecker = defaultTypeChecker } AccessorExtendHook.prototype = { configure: function( confObj ){ if ( confObj.typeChecker ) this.typeChecker = confObj.typeChecker }, initializeHook: function( oldObj, extendObj ){ var accessors = [] // add extendObj.__extendHooks = oldObj.__extendHooks || { } extendObj.__extendHooks[ this.id ] = { id: this.id, allAccessors: accessors } }, hasHook: function( oldObj ){ return oldObj && oldObj.__extendHooks && oldObj.__extendHooks[ this.id ] }, handle: function( oldObj, extendObj ){ var accessors = extendObj.accessors if ( ! this.hasHook( oldObj ) ) this.initializeHook( oldObj, extendObj ) if ( !accessors ) return oldObj for ( var i = 0; i < accessors.length; i++ ){ new AccessorHandler( oldObj, accessors[ i ], extendObj, this.typeChecker ) } return oldObj } } return new AccessorExtendHook } ); define( 'Seed/extendHooks/typeExtendHook',[ '../helpers' ], function( _ ) { var TypeExtendHook = function( ) { this.id = 'type' this.handle = this.handle.bind( this ) } var TypeHookHandler = function( o ) { this.id = 'type' this.oldObj = o.oldObj this.extendObj = o.extendObj // console.log( 'type', this.getExtendObj( ).type, this.getOldObj( ).types ) if ( ! this.hasHook( ) ){ this.initializeHook( ) } this.handleExtendObjType( ) } TypeHookHandler.prototype = { handleExtendObjType: function( ){ var oldTypes = this.getOldObj( ).getTypes( ).slice( ), // copy array of previoustypes newType = this.getExtendObj( ).type this.getOldObj( ).types = oldTypes if ( typeof newType !== 'string' ) // no type or invalid type type ( ha ha ) return if ( oldTypes.indexOf( newType ) !== -1 ) return this.getOldObj( ).types.push( newType ) }, hasHook: function( ){ return this.getOldObj( ).__extendHooks && this.oldObj.__extendHooks[ this.id ] }, getHookConfigurationObject: function( ){ return this.getOldObj( ).__extendHooks[ this.id ] }, getTypes: function( ){ return this.getOldObj( ).types }, initializeHook: function( ){ if ( ! this.getOldObj( ).__extendHooks ) this.getOldObj( ).__extendHooks = { } this.getOldObj( ).__extendHooks[ this.id ] = { id: this.id } this.getOldObj( ).isTypeOf = function( type ){ return this.types.indexOf( type ) !== -1 } this.getOldObj( ).types = [ ] this.getOldObj( ).getTypes = function( ){ return this.types } }, getOldObj: function( ){ return this.oldObj }, getExtendObj: function( ){ return this.extendObj } } TypeExtendHook.prototype = { configure: function( ){ }, handle: function( oldObj, extendObj ){ new TypeHookHandler({ oldObj: oldObj, extendObj: extendObj }) return oldObj } } return new TypeExtendHook } ); define( 'Seed/extendHookRegistrations',[ './extendHooks/plusMinusExtendHook', './extendHooks/accessorsExtendHook', './extendHooks/typeExtendHook', ], function( plusMinusExtendHook, accessorsExtendHook, typeExtendHook ) { return [ accessorsExtendHook, typeExtendHook, plusMinusExtendHook ] } ); define( 'Seed/Extendable',[ './helpers', './extendHooker', './extendHookRegistrations' ], function( _ , extendHooker, hookList ) { /** * This is the basic extendable element, it is used by fjs.View, fjs.Controller and others ... * It allows user to specifies '+_String:methodName_' to augment set the + method of the prototype of the new element with the defined method * if A is extended and A has a method named 'some_random_method', * if you do B = A.extend({ * '+some_random_method' : add * }) * B.some_random_method <=> function() { * A.prototype.some_random_method(); * add(); * } * @export Seed/Extendable */ var Extendable = function( ) {}; /** * Initialize an object * * @this {Extendable} * @param {Object} configuration Object */ Extendable.prototype.constructor = function( ) {}; // here we hookify Extendable extendHooker.hookify( Extendable ) for ( var i = 0; i < hookList.length; i++ ){ Extendable.registerHook( hookList[i] ) } /** * Call init function from the cstructor signleton scope, useful to add custom afterNew/beforeNew callbacks * * @param {object} inst The instance scope * @param {array} args arguments */ Extendable[ 'new' ] = function( inst, args ) { }; /** * Singleton extend with +/- convention * * @private * @param {Object} basicObj configuration key-value object with +/-key * @returns {Object} extObj * */ var extendCstr = function( basicObj, extObj ) { var Res; Res = function( o ) { Res[ 'new' ].call( Res, this, arguments ); }; var attrs = _.extend( {}, basicObj, pm( basicObj, extObj ) ); for ( var i in attrs ) if ( attrs.hasOwnProperty( i ) ) { Res[ i ] = attrs[ i ]; } return Res; }; /** * Extend a Constructor with +/- convention * * @public * @param {Object} obj configuration key-value object with '+key' or '-key' * */ Extendable.extend = function( obj ) { var C = function( o ) { // C[ 'new' ].call( C, this, arguments ); // ( typeof( args[ 0 ] ) !== 'boolean' || args[ 0 ] !== false ) && this.constructor.apply( this, arguments ); ( typeof( arguments[ 0 ] ) !== 'boolean' || arguments[ 0 ] !== false ) && ( C.prototype.constructor).apply( this, arguments ); }; //copy constructor ownProperty (i.e. extend and new) var attrs = _.clone( this ); for ( var i in attrs ) if ( attrs.hasOwnProperty( i ) ) { C[ i ] = attrs[ i ]; } var hooks = Extendable.__hooks, hooked = _.extend( new this( false ), obj ) for ( var i = 0; i < hooks.length; i++ ) { hooked = hooks[ i ].handle( hooked, obj ) } C.prototype = hooked // C.prototype = extend(new this(false), pm(this.prototype, obj)); return C; }; return Extendable; } ); define( 'Seed/Eventable',[ './Extendable', './helpers' ], function( Extendable, _ ) { /** * For publishing events * @export Seed/Eventable */ return Extendable.extend( { constructor: function( ) { this._events = {}; this._attached = [ ]; }, /** * Publisher method, Fire an event * * @public * @param {string} eventName * @param {..} [arguments] the arguments to pass through the event pipe * */ emit: function( eventName ) { var evs = this._events[ eventName ]; if ( evs ) { var args = Array.prototype.slice.call( arguments, 1 ); // last subscribe is the first to be called for ( var i = evs.length; i--; ) { //TODO profiling to this line evs[ i ].fn.apply( evs[ i ].subscriber, args ); //evs[i](args[0], args[1], args[2], args[3]); } } }, // fire alias, temporary fire: function( ) { this.emit.apply( this, arguments ) }, /** * Publisher method, Subscribe to an event * * Note : it's important to provide an subscriber object to detach the event when the subscriber is destroyed, else you may have issues to destroy events * * @public * @param {String} eventName '*' means 'all', subsribe multi events with 'evt1 evt2 ...' * @param {Object|Function} subscriber if Object, the subscriber instance else the function to attach * @param {String|Function|Object} [functionPointer='subscriber.'on'+eventName'] if the subscriber is an object, a string pointes to subscriber method, a function would be executed in the subscriber scope * @returns {Object} subscription * * @example // call subscriber.onStart when publisher fire 'start' var sub = publisher.on('start', subscriber); sub.un(); // stops the subscription // call subscriber.onStart when publisher fire 'start' and subscriber.onEnd when publisher fire 'end' publisher.on('start end', subscriber); // call subscriber.onPublisherStart when publisher fire 'start' publisher.on('start', subscriber, 'onPublisherStart'); // call fn in the subscriber scope publisher.on('start', subscriber, fn); // call fn in the subscriber scope (equivalent to previous), use for more compatibility with classic use publisher.on('start', fn, subscriber); // call fn when publisher fire start, use with caution when you'll never want to detach event at any destroy publisher.on('start', fn); */ on: function( eventName, subscriber, fn ) { var evts = eventName.split( ' ' ); // multimorph API handling if ( typeof( subscriber ) === 'function' ) { var oldFn = fn; fn = subscriber; subscriber = oldFn; } // multi events handling if ( evts.length === 1 ) { return this._on( evts[ 0 ], subscriber, fn ); } else { var ons = [ ]; for ( var i = 0; i < evts.length; i++ ) { ons[ i ].push( this._on( evtName, subscriber, fn ) ); } return { un: function( ) { for ( var i = 0; i < ons.length; i++ ) { ons[ i ].un( ); } } }; } }, /** * @private */ _on: function( eventName, subscriber, f ) { // subscriber format validation if ( subscriber && typeof( subscriber.attach ) !== 'function' ) { throw new Error( 'The subscriber should have a attach(event) method' ); return; } // fn multimorphism handling if ( typeof( f ) === 'string' ) { f = subscriber[ f ]; } else if ( typeof( f ) === 'undefined' ) { f = subscriber[ 'on' + _.capitalize( eventName ) ]; } if ( typeof( f ) !== 'function' ) { throw new Error( 'Cannot find the function to subscribe to ' + eventName ); return; } var _this = this, subObj = { fn: f, subscriber: subscriber }, ret = { un: function( ) { _this._rmSubscription( eventName, subObj ); } }; // subscriber.attach( ret ); ( this._events[ eventName ] || ( this._events[ eventName ] = [ ] ) ).push( subObj ); return ret; }, /** * Publisher method, Remove a Subscription, private, use subscription.un() * * @private * @param {string} eventName * @param {object} subscription object * */ _rmSubscription: function( eventName, subObj ) { _.remove( this._events[ eventName ], subObj ); if ( this._events[ eventName ].length == 0 ) { delete this._events[ eventName ]; } }, /** * Subscriber method * Attach a subscription to this * @param {object} subscription */ attach: function( subscription ) { this._attached.push( subscription ); }, /** * Subscriber method * Detach all subscription */ detachAll: function( ) { for ( var i = 0; i < this._attached.length; i++ ) { this._attached[ i ].un( ); } this._attached = [ ]; } } ); } ); /** * SeedHq version: "0.0.16" Copyright (c) 2011-2012, Cyril Agosta ( cyril.agosta.dev@gmail.com) All Rights Reserved. * Available via the MIT license. * see: http://github.com/cagosta/SeedHq for details */ define( 'Seed/SeedHq',[ './Eventable', './helpers' // remove me ], function( Eventable, helpers ) { /** * @class Seed * @param {object} o configuration object * @example * */ return Eventable.extend( { /** * init instance attributes * * @param {object} o configuration object */ constructor: function( o ) { ( o = o ||  {} ); //publisher init this._events = []; //subscriber init this._attached = []; this._subs = []; this._o = o; if ( o._a ) { this._a = o._a; } this.setOptions(); }, /** * no options by default */ options: {}, /** * keys declared in options are set as attribute in the instance */ bindMethod: function( methodName ) { this[ methodName ] = this[ methodName ].bind( this ) }, setOptions: function() { var setter if ( this.options ) { for ( var i in this.options ) if ( this.options.hasOwnProperty( i ) ) { if ( typeof( this._o[ i ] ) === 'undefined' ) this[ i ] = this.options[ i ]; else { setter = 'set' + helpers.capitalize( i ) if ( typeof this[ setter ] === 'function' ) { // accessors extend hook todo this[ setter ]( this._o[ i ] ) } else { this[ i ] = this._o[ i ]; } } } } }, /** * Build a sub instance, that will be destroyed with this * @params {function} C Constructor of the sub instance * @params {object} o configuration options of the sub instance * @returns {object} c instance built */ sub: function( C, o ) { if ( typeof( C ) !== 'function' ) { throw new Error( 'C is not a valid constructor' ); } var c = new C( this.subParams( o ) ); this._subs.push( c ); return c; }, /** * Add custom keys in the sub configuratin object from this * * @params {object} o start sub configuration object * @returns {object} o extended sub configuration object */ subParams: function( o ) { ( o || ( o = {} ) ); o._parent = this; if ( this._a ) { o._a = this._a; } return o; }, /** * Destroy the objects, his events and his sub objects */ destroy: function() { this.detachAll(); for ( var i = 0; i < this._subs.length; i++ ) { this._subs[ i ].destroy() } } } ); } ); define('Seed/Seed',[ './SeedHq' ], function( SeedHq ){ return SeedHq }); define( 'mangrove-utils/dom/addEventListener',[],function() { return ( function() { if ( window.addEventListener ) return function( el, ev, fn, c ) { return el.addEventListener( ev, fn, !! c ) } return function( el, ev, fn ) { return el.attachEvent( 'on' + ev, function( e ) { var e = e || window.event e.target = e.target || e.srcElement e.relatedTarget = e.relatedTarget || e.fromElement || e.toElement e.isImmediatePropagationStopped = e.isImmediatePropagationStopped || false e.preventDefault = e.preventDefault || function() { e.returnValue = false } e.stopPropagation = e.stopPropagation || function() { e.cancelBubble = true } e.stopImmediatePropagation = e.stopImmediatePropagation || function() { e.stopPropagation() e.isImmediatePropagationStopped = true } if ( !e.isImmediatePropagationStopped ) fn( e ) } ) } }() ) } ); define('mangrove-utils/dom/keyCodes',[],function(){ return { backspace: 8, tab: 9, enter: 13, shift: 16, ctrl: 17, alt: 18, pauseBbreak: 19, capsLock: 20, escape: 27, pageUp: 33, pageDown: 34, end: 35, home: 36, leftArrow: 37, upArrow: 38, rightArrow: 39, downArrow: 40, insert: 45, delete: 46, 0: 48, 1: 49, 2: 50, 3: 51, 4: 52, 5: 53, 6: 54, 7: 55, 8: 56, 9: 57, a: 65, b: 66, c: 67, d: 68, e: 69, f: 70, g: 71, h: 72, i: 73, j: 74, k: 75, l: 76, m: 77, n: 78, o: 79, p: 80, q: 81, r: 82, s: 83, t: 84, u: 85, v: 86, w: 87, x: 88, y: 89, z: 90, leftWindowKey: 91, rightWindowKey: 92, selectKey: 93, numpad0: 96, numpad1: 97, numpad2: 98, numpad3: 99, numpad4: 100, numpad5: 101, numpad6: 102, numpad7: 103, numpad8: 104, numpad9: 105, multiply: 106, add: 107, subtract: 109, decimalPoint: 110, divide: 111, f1: 112, f2: 113, f3: 114, f4: 115, f5: 116, f6: 117, f7: 118, f8: 119, f9: 120, f10: 121, f11: 122, f12: 123, numLock: 144, scrollLock: 145, semiColon: 186, equalSign: 187, comma: 188, dash: 189, period: 190, forwardSlash: 191, graveAccent: 192, openBracket: 219, backSlash: 220, closeBraket: 221, singleQuote: 222 }; }); /** * @license RequireJS domReady 2.0.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. * Available via the MIT or new BSD license. * see: http://github.com/requirejs/domReady for details */ /*jslint */ /*global require: false, define: false, requirejs: false, window: false, clearInterval: false, document: false, self: false, setInterval: false */ define('mangrove-utils/dom/ready',[],function () { var isTop, testDiv, scrollIntervalId, isBrowser = typeof window !== "undefined" && window.document, isPageLoaded = !isBrowser, doc = isBrowser ? document : null, readyCalls = []; function runCallbacks(callbacks) { var i; for (i = 0; i < callbacks.length; i += 1) { callbacks[i](doc); } } function callReady() { var callbacks = readyCalls; if (isPageLoaded) { //Call the DOM ready callbacks if (callbacks.length) { readyCalls = []; runCallbacks(callbacks); } } } /** * Sets the page as loaded. */ function pageLoaded() { if (!isPageLoaded) { isPageLoaded = true; if (scrollIntervalId) { clearInterval(scrollIntervalId); } callReady(); } } if (isBrowser) { if (document.addEventListener) { //Standards. Hooray! Assumption here that if standards based, //it knows about DOMContentLoaded. document.addEventListener("DOMContentLoaded", pageLoaded, false); window.addEventListener("load", pageLoaded, false); } else if (window.attachEvent) { window.attachEvent("onload", pageLoaded); testDiv = document.createElement('div'); try { isTop = window.frameElement === null; } catch (e) {} //DOMContentLoaded approximation that uses a doScroll, as found by //Diego Perini: http://javascript.nwbox.com/IEContentLoaded/, //but modified by other contributors, including jdalton if (testDiv.doScroll && isTop && window.external) { scrollIntervalId = setInterval(function () { try { testDiv.doScroll(); pageLoaded(); } catch (e) {} }, 30); } } //Check if document already complete, and if so, just trigger page load //listeners. Latest webkit browsers also use "interactive", and //will fire the onDOMContentLoaded before "interactive" but not after //entering "interactive" or "complete". More details: //http://dev.w3.org/html5/spec/the-end.html#the-end //http://stackoverflow.com/questions/3665561/document-readystate-of-interactive-vs-ondomcontentloaded //Hmm, this is more complicated on further use, see "firing too early" //bug: https://github.com/requirejs/domReady/issues/1 //so removing the || document.readyState === "interactive" test. //There is still a window.onload binding that should get fired if //DOMContentLoaded is missed. if (document.readyState === "complete") { pageLoaded(); } } /** START OF PUBLIC API **/ /** * Registers a callback for DOM ready. If DOM is already ready, the * callback is called immediately. * @param {Function} callback */ function domReady(callback) { if (isPageLoaded) { callback(doc); } else { readyCalls.push(callback); } return domReady; } domReady.version = '2.0.1'; /** * Loader Plugin API method */ domReady.load = function (name, req, onLoad, config) { if (config.isBuild) { onLoad(null); } else { domReady(onLoad); } }; /** END OF PUBLIC API **/ return domReady; }); define( 'mangrove-utils/dom/removeEventListener',[],function() { return ( function() { if ( window.removeEventListener ) return function( el, ev, fn, c ) { return el.removeEventListener( ev, fn, !! c ) } return function( el, ev, fn ) { el.detachEvent( ev, fn ) } }() ) } ); define( 'mangrove-utils/dom/all',[ './addEventListener', './keyCodes', './ready', './removeEventListener' ], function( addEventListener, keyCodes, ready, removeEventListener ) { return { addEventListener: addEventListener, keyCodes: keyCodes, ready: ready, removeEventListener: removeEventListener } } ); define( 'Array.nocomplex/isArray',[],function() { Array.isArray = Array.isArray || function( o ) { return Object.prototype.toString.call( o ) == "[object Array]" } return Array.isArray } ); // Underscore.string // (c) 2010 Esa-Matti Suuronen // Underscore.string is freely distributable under the terms of the MIT license. // Documentation: https://github.com/epeli/underscore.string // Some code is borrowed from MooTools and Alexandru Marasteanu. // Version '2.3.2' !function(root, String){ // Defining helper functions. var nativeTrim = String.prototype.trim; var nativeTrimRight = String.prototype.trimRight; var nativeTrimLeft = String.prototype.trimLeft; var parseNumber = function(source) { return source * 1 || 0; }; var strRepeat = function(str, qty){ if (qty < 1) return ''; var result = ''; while (qty > 0) { if (qty & 1) result += str; qty >>= 1, str += str; } return result; }; var slice = [].slice; var defaultToWhiteSpace = function(characters) { if (characters == null) return '\\s'; else if (characters.source) return characters.source; else return '[' + _s.escapeRegExp(characters) + ']'; }; // Helper for toBoolean function boolMatch(s, matchers) { var i, matcher, down = s.toLowerCase(); matchers = [].concat(matchers); for (i = 0; i < matchers.length; i += 1) { matcher = matchers[i]; if (!matcher) continue; if (matcher.test && matcher.test(s)) return true; if (matcher.toLowerCase() === down) return true; } } var escapeChars = { lt: '<', gt: '>', quot: '"', amp: '&', apos: "'" }; var reversedEscapeChars = {}; for(var key in escapeChars) reversedEscapeChars[escapeChars[key]] = key; reversedEscapeChars["'"] = '#39'; // sprintf() for JavaScript 0.7-beta1 // http://www.diveintojavascript.com/projects/javascript-sprintf // // Copyright (c) Alexandru Marasteanu // All rights reserved. var sprintf = (function() { function get_type(variable) { return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); } var str_repeat = strRepeat; var str_format = function() { if (!str_format.cache.hasOwnProperty(arguments[0])) { str_format.cache[arguments[0]] = str_format.parse(arguments[0]); } return str_format.format.call(null, str_format.cache[arguments[0]], arguments); }; str_format.format = function(parse_tree, argv) { var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; for (i = 0; i < tree_length; i++) { node_type = get_type(parse_tree[i]); if (node_type === 'string') { output.push(parse_tree[i]); } else if (node_type === 'array') { match = parse_tree[i]; // convenience purposes only if (match[2]) { // keyword argument arg = argv[cursor]; for (k = 0; k < match[2].length; k++) { if (!arg.hasOwnProperty(match[2][k])) { throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k])); } arg = arg[match[2][k]]; } } else if (match[1]) { // positional argument (explicit) arg = argv[match[1]]; } else { // positional argument (implicit) arg = argv[cursor++]; } if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg))); } switch (match[8]) { case 'b': arg = arg.toString(2); break; case 'c': arg = String.fromCharCode(arg); break; case 'd': arg = parseInt(arg, 10); break; case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; case 'o': arg = arg.toString(8); break; case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; case 'u': arg = Math.abs(arg); break; case 'x': arg = arg.toString(16); break; case 'X': arg = arg.toString(16).toUpperCase(); break; } arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; pad_length = match[6] - String(arg).length; pad = match[6] ? str_repeat(pad_character, pad_length) : ''; output.push(match[5] ? arg + pad : pad + arg); } } return output.join(''); }; str_format.cache = {}; str_format.parse = function(fmt) { var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; while (_fmt) { if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { parse_tree.push(match[0]); } else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { parse_tree.push('%'); } else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { if (match[2]) { arg_names |= 1; var field_list = [], replacement_field = match[2], field_match = []; if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { field_list.push(field_match[1]); while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { field_list.push(field_match[1]); } else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { field_list.push(field_match[1]); } else { throw new Error('[_.sprintf] huh?'); } } } else { throw new Error('[_.sprintf] huh?'); } match[2] = field_list; } else { arg_names |= 2; } if (arg_names === 3) { throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported'); } parse_tree.push(match); } else { throw new Error('[_.sprintf] huh?'); } _fmt = _fmt.substring(match[0].length); } return parse_tree; }; return str_format; })(); // Defining underscore.string var _s = { VERSION: '2.3.0', isBlank: function(str){ if (str == null) str = ''; return (/^\s*$/).test(str); }, stripTags: function(str){ if (str == null) return ''; return String(str).replace(/<\/?[^>]+>/g, ''); }, capitalize : function(str){ str = str == null ? '' : String(str); return str.charAt(0).toUpperCase() + str.slice(1); }, chop: function(str, step){ if (str == null) return []; str = String(str); step = ~~step; return step > 0 ? str.match(new RegExp('.{1,' + step + '}', 'g')) : [str]; }, clean: function(str){ return _s.strip(str).replace(/\s+/g, ' '); }, count: function(str, substr){ if (str == null || substr == null) return 0; str = String(str); substr = String(substr); var count = 0, pos = 0, length = substr.length; while (true) { pos = str.indexOf(substr, pos); if (pos === -1) break; count++; pos += length; } return count; }, chars: function(str) { if (str == null) return []; return String(str).split(''); }, swapCase: function(str) { if (str == null) return ''; return String(str).replace(/\S/g, function(c){ return c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase(); }); }, escapeHTML: function(str) { if (str == null) return ''; return String(str).replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; }); }, unescapeHTML: function(str) { if (str == null) return ''; return String(str).replace(/\&([^;]+);/g, function(entity, entityCode){ var match; if (entityCode in escapeChars) { return escapeChars[entityCode]; } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) { return String.fromCharCode(parseInt(match[1], 16)); } else if (match = entityCode.match(/^#(\d+)$/)) { return String.fromCharCode(~~match[1]); } else { return entity; } }); }, escapeRegExp: function(str){ if (str == null) return ''; return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); }, splice: function(str, i, howmany, substr){ var arr = _s.chars(str); arr.splice(~~i, ~~howmany, substr); return arr.join(''); }, insert: function(str, i, substr){ return _s.splice(str, i, 0, substr); }, include: function(str, needle){ if (needle === '') return true; if (str == null) return false; return String(str).indexOf(needle) !== -1; }, join: function() { var args = slice.call(arguments), separator = args.shift(); if (separator == null) separator = ''; return args.join(separator); }, lines: function(str) { if (str == null) return []; return String(str).split("\n"); }, reverse: function(str){ return _s.chars(str).reverse().join(''); }, startsWith: function(str, starts){ if (starts === '') return true; if (str == null || starts == null) return false; str = String(str); starts = String(starts); return str.length >= starts.length && str.slice(0, starts.length) === starts; }, endsWith: function(str, ends){ if (ends === '') return true; if (str == null || ends == null) return false; str = String(str); ends = String(ends); return str.length >= ends.length && str.slice(str.length - ends.length) === ends; }, succ: function(str){ if (str == null) return ''; str = String(str); return str.slice(0, -1) + String.fromCharCode(str.charCodeAt(str.length-1) + 1); }, titleize: function(str){ if (str == null) return ''; str = String(str).toLowerCase(); return str.replace(/(?:^|\s|-)\S/g, function(c){ return c.toUpperCase(); }); }, camelize: function(str){ return _s.trim(str).replace(/[-_\s]+(.)?/g, function(match, c){ return c ? c.toUpperCase() : ""; }); }, underscored: function(str){ return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase(); }, dasherize: function(str){ return _s.trim(str).replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase(); }, classify: function(str){ return _s.titleize(String(str).replace(/[\W_]/g, ' ')).replace(/\s/g, ''); }, humanize: function(str){ return _s.capitalize(_s.underscored(str).replace(/_id$/,'').replace(/_/g, ' ')); }, trim: function(str, characters){ if (str == null) return ''; if (!characters && nativeTrim) return nativeTrim.call(str); characters = defaultToWhiteSpace(characters); return String(str).replace(new RegExp('\^' + characters + '+|' + characters + '+$', 'g'), ''); }, ltrim: function(str, characters){ if (str == null) return ''; if (!characters && nativeTrimLeft) return nativeTrimLeft.call(str); characters = defaultToWhiteSpace(characters); return String(str).replace(new RegExp('^' + characters + '+'), ''); }, rtrim: function(str, characters){ if (str == null) return ''; if (!characters && nativeTrimRight) return nativeTrimRight.call(str); characters = defaultToWhiteSpace(characters); return String(str).replace(new RegExp(characters + '+$'), ''); }, truncate: function(str, length, truncateStr){ if (str == null) return ''; str = String(str); truncateStr = truncateStr || '...'; length = ~~length; return str.length > length ? str.slice(0, length) + truncateStr : str; }, /** * _s.prune: a more elegant version of truncate * prune extra chars, never leaving a half-chopped word. * @author github.com/rwz */ prune: function(str, length, pruneStr){ if (str == null) return ''; str = String(str); length = ~~length; pruneStr = pruneStr != null ? String(pruneStr) : '...'; if (str.length <= length) return str; var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; }, template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA' if (template.slice(template.length-2).match(/\w\w/)) template = template.replace(/\s*\S+$/, ''); else template = _s.rtrim(template.slice(0, template.length-1)); return (template+pruneStr).length > str.length ? str : str.slice(0, template.length)+pruneStr; }, words: function(str, delimiter) { if (_s.isBlank(str)) return []; return _s.trim(str, delimiter).split(delimiter || /\s+/); }, pad: function(str, length, padStr, type) { str = str == null ? '' : String(str); length = ~~length; var padlen = 0; if (!padStr) padStr = ' '; else if (padStr.length > 1) padStr = padStr.charAt(0); switch(type) { case 'right': padlen = length - str.length; return str + strRepeat(padStr, padlen); case 'both': padlen = length - str.length; return strRepeat(padStr, Math.ceil(padlen/2)) + str + strRepeat(padStr, Math.floor(padlen/2)); default: // 'left' padlen = length - str.length; return strRepeat(padStr, padlen) + str; } }, lpad: function(str, length, padStr) { return _s.pad(str, length, padStr); }, rpad: function(str, length, padStr) { return _s.pad(str, length, padStr, 'right'); }, lrpad: function(str, length, padStr) { return _s.pad(str, length, padStr, 'both'); }, sprintf: sprintf, vsprintf: function(fmt, argv){ argv.unshift(fmt); return sprintf.apply(null, argv); }, toNumber: function(str, decimals) { if (!str) return 0; str = _s.trim(str); if (!str.match(/^-?\d+(?:\.\d+)?$/)) return NaN; return parseNumber(parseNumber(str).toFixed(~~decimals)); }, numberFormat : function(number, dec, dsep, tsep) { if (isNaN(number) || number == null) return ''; number = number.toFixed(~~dec); tsep = typeof tsep == 'string' ? tsep : ','; var parts = number.split('.'), fnums = parts[0], decimals = parts[1] ? (dsep || '.') + parts[1] : ''; return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals; }, strRight: function(str, sep){ if (str == null) return ''; str = String(str); sep = sep != null ? String(sep) : sep; var pos = !sep ? -1 : str.indexOf(sep); return ~pos ? str.slice(pos+sep.length, str.length) : str; }, strRightBack: function(str, sep){ if (str == null) return ''; str = String(str); sep = sep != null ? String(sep) : sep; var pos = !sep ? -1 : str.lastIndexOf(sep); return ~pos ? str.slice(pos+sep.length, str.length) : str; }, strLeft: function(str, sep){ if (str == null) return ''; str = String(str); sep = sep != null ? String(sep) : sep; var pos = !sep ? -1 : str.indexOf(sep); return ~pos ? str.slice(0, pos) : str; }, strLeftBack: function(str, sep){ if (str == null) return ''; str += ''; sep = sep != null ? ''+sep : sep; var pos = str.lastIndexOf(sep); return ~pos ? str.slice(0, pos) : str; }, toSentence: function(array, separator, lastSeparator, serial) { separator = separator || ', '; lastSeparator = lastSeparator || ' and '; var a = array.slice(), lastMember = a.pop(); if (array.length > 2 && serial) lastSeparator = _s.rtrim(separator) + lastSeparator; return a.length ? a.join(separator) + lastSeparator + lastMember : lastMember; }, toSentenceSerial: function() { var args = slice.call(arguments); args[3] = true; return _s.toSentence.apply(_s, args); }, slugify: function(str) { if (str == null) return ''; var from = "ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź", to = "aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz", regex = new RegExp(defaultToWhiteSpace(from), 'g'); str = String(str).toLowerCase().replace(regex, function(c){ var index = from.indexOf(c); return to.charAt(index) || '-'; }); return _s.dasherize(str.replace(/[^\w\s-]/g, '')); }, surround: function(str, wrapper) { return [wrapper, str, wrapper].join(''); }, quote: function(str, quoteChar) { return _s.surround(str, quoteChar || '"'); }, unquote: function(str, quoteChar) { quoteChar = quoteChar || '"'; if (str[0] === quoteChar && str[str.length-1] === quoteChar) return str.slice(1,str.length-1); else return str; }, exports: function() { var result = {}; for (var prop in this) { if (!this.hasOwnProperty(prop) || prop.match(/^(?:include|contains|reverse)$/)) continue; result[prop] = this[prop]; } return result; }, repeat: function(str, qty, separator){ if (str == null) return ''; qty = ~~qty; // using faster implementation if separator is not needed; if (separator == null) return strRepeat(String(str), qty); // this one is about 300x slower in Google Chrome for (var repeat = []; qty > 0; repeat[--qty] = str) {} return repeat.join(separator); }, naturalCmp: function(str1, str2){ if (str1 == str2) return 0; if (!str1) return -1; if (!str2) return 1; var cmpRegex = /(\.\d+)|(\d+)|(\D+)/g, tokens1 = String(str1).toLowerCase().match(cmpRegex), tokens2 = String(str2).toLowerCase().match(cmpRegex), count = Math.min(tokens1.length, tokens2.length); for(var i = 0; i < count; i++) { var a = tokens1[i], b = tokens2[i]; if (a !== b){ var num1 = parseInt(a, 10); if (!isNaN(num1)){ var num2 = parseInt(b, 10); if (!isNaN(num2) && num1 - num2) return num1 - num2; } return a < b ? -1 : 1; } } if (tokens1.length === tokens2.length) return tokens1.length - tokens2.length; return str1 < str2 ? -1 : 1; }, levenshtein: function(str1, str2) { if (str1 == null && str2 == null) return 0; if (str1 == null) return String(str2).length; if (str2 == null) return String(str1).length; str1 = String(str1); str2 = String(str2); var current = [], prev, value; for (var i = 0; i <= str2.length; i++) for (var j = 0; j <= str1.length; j++) { if (i && j) if (str1.charAt(j - 1) === str2.charAt(i - 1)) value = prev; else value = Math.min(current[j], current[j - 1], prev) + 1; else value = i + j; prev = current[j]; current[j] = value; } return current.pop(); }, toBoolean: function(str, trueValues, falseValues) { if (typeof str === "number") str = "" + str; if (typeof str !== "string") return !!str; str = _s.trim(str); if (boolMatch(str, trueValues || ["true", "1"])) return true; if (boolMatch(str, falseValues || ["false", "0"])) return false; } }; // Aliases _s.strip = _s.trim; _s.lstrip = _s.ltrim; _s.rstrip = _s.rtrim; _s.center = _s.lrpad; _s.rjust = _s.lpad; _s.ljust = _s.rpad; _s.contains = _s.include; _s.q = _s.quote; _s.toBool = _s.toBoolean; // Exporting // CommonJS module is defined if (typeof exports !== 'undefined') { if (typeof module !== 'undefined' && module.exports) module.exports = _s; exports._s = _s; } // Register as a named module with AMD. if (typeof define === 'function' && define.amd) define('underscore.string', [], function(){ return _s; }); // Integrate with Underscore.js if defined // or create our own underscore object. root._ = root._ || {}; root._.string = root._.str = _s; }(this, String); define( 'String.nocomplex/uncapitalize',[],function() { String.prototype.uncapitalize = function() { return ( this[ 0 ].toLowerCase() + this.substr( 1, this.length - 1 ) ); }; } ); /** * String.nocomplex version: "0.0.9" Copyright (c) 2011-2012, Cyril Agosta ( cyril.agosta.dev@gmail.com) All Rights Reserved. * Available via the MIT license. * see: http://github.com/cagosta/String.nocomplex for details */ define( 'String.nocomplex/String.nocomplex',[ 'underscore.string', './uncapitalize' ], function( helpers, uncapitalize ) { var slice = Array.prototype.slice, addMethod = function( method ) { String.prototype[ method ] = function() { var args = slice.call( arguments ) args.unshift( this ) return helpers[ method ].apply( this, args ) } } for ( var method in helpers ) if ( helpers.hasOwnProperty( method ) ) { addMethod( method ) } return String.prototype } ); define( 'Array.nocomplex/collect',[],function() { Array.prototype.collect = function( f ) { var res = []; if ( typeof( f ) === "string" ) { for ( var i = -1, n = this.length; ++i < n; ) { res.push( this[ i ][ f ] ); } } else { for ( var i = -1, n = this.length; ++i < n; ) { res.push( f( this[ i ] ) ); } } return res; }; } ); define( 'Array.nocomplex/each',[],function() { Array.prototype.each = function( f ) { for ( var i = 0, n = this.length; i < n; i++ ) { f( this[ i ], i ); } return this; }; } ); define( 'Array.nocomplex/first',[],function() { Array.prototype.first = function( f ) { for ( var i = 0, n = this.length; i < n; i++ ) { if ( f( this[ i ] ) ) return this[ i ]; } return null; }; } ); define( 'Array.nocomplex/has',[],function() { Array.prototype.has = function( value ) { for ( var i = this.length; i--; ) { if ( this[ i ] === value ) { return true; } } return false; }; } ); define( 'Array.nocomplex/last',[],function() { Array.prototype.last = function() { return this[ this.length - 1 ]; }; } ); define( 'Array.nocomplex/map',[],function() { Array.prototype.map = Array.prototype.map || function( fn, scope ) { if ( scope ) fn = fn.bind( scope ); var r = this.slice(); if ( typeof( fn ) === 'function' ) { for ( var i = 0, n = r.length; i < n; i++ ) r[ i ] = fn( r[ i ], i ); } else { fn = fn.substr( 2, fn.length ); for ( var i = 0, n = r.length; i < n; i++ ) r[ i ] = r[ i ][ fn ](); } return r; }; } ); define( 'Array.nocomplex/onEls',[],function() { Array.prototype.onEls = function( f ) { for ( var i = this.length; i--; ) this[ i ] = f( this[ i ], i ); return this; }; } ); define( 'Array.nocomplex/remove',[],function() { Array.prototype.remove = function( v ) { for ( var i = this.length; i--; ) { if ( this[ i ] === v ) this.splice( i, 1 ); } return this; }; } ); define( 'Array.nocomplex/removeOneValue',[],function() { Array.prototype.removeOneValue = function( v ) { for ( var i = this.length; i--; ) { if ( this[ i ] === v ) { return ( this.splice( i, 1 ) ); } } }; } ); define( 'Array.nocomplex/except',[],function() { Array.prototype.except = function( v ) { var res = []; for ( var i = 0, n = this.length; i < n; i++ ) if ( this[ i ] !== v ) res.push( this[ i ] ) return res; } } ); define( 'Array.nocomplex/exceptFn',[],function() { Array.prototype.exceptFn = function( f ) { var r = this.slice(); for ( var i = r.length; i--; ) if ( f( r[ i ] ) ) r.splice( i, 1 ); return r; } } ); define( 'Array.nocomplex/indexOf',[],function() { Array.prototype.indexOf = Array.prototype.indexOf || function( s ) { var i, l for ( i = 0, l = this.length; i < l; i++ ) if ( this[ i ] === s ) return i return -1 }; } ); define( 'Array.nocomplex/isIn',[ './has' ], function() { Array.prototype.isIn = function( array ) { for ( var i = this.length; i--; ) { if ( !array.has( this[ i ] ) ) return false; } return true; } } ); define( 'Array.nocomplex/send',[],function() { Array.prototype.send = function( method ) { var args = Array.prototype.slice.call( arguments ); args.splice( 0, 1 ); if ( typeof( method ) === 'string' ) { for ( var i = -1, n = this.length; ++i < n; ) { if ( this[ i ] ) this[ i ][ method ].apply( this[ i ], args ); } } else for ( var i = -1, n = this.length; ++i < n; ) method.apply( {}, [ this[ i ] ].concat( args ) ); return this; }; } ); define( 'Array.nocomplex/uniq',[ './has' ], function() { Array.prototype.uniq = function( f ) { if ( !f ) { var res = [] for ( var i = this.length; i--; ) { !res.has( this[ i ] ) && res.push( this[ i ] ); } return res; } else { var res = [], _r = []; for ( var i = 0, n = this.length; i < n; i++ ) { var v = f( this[ i ] ); if ( !_r.has( v ) ) { res.push( this[ i ] ) _r.push( v ); } } return res; } } } ); define( 'Array.nocomplex/equals',[ './isIn' ], function() { Array.prototype.equals = function( array ) { if ( this.isIn( array ) && array.isIn( this ) ) { return true; } return false; }; } ); define( 'Array.nocomplex/find',[],function() { Array.prototype.find = function( f ) { for ( var i = 0, n = this.length; i < n; i++ ) { if ( f( this[ i ], i ) ) return this[ i ]; } return false; }; Array.prototype.findReverse = function( f ) { for ( var i = this.length; i--; ) { if ( f( this[ i ], i ) ) return this[ i ]; } return false; }; } ); define( 'Array.nocomplex/where',[],function() { Array.prototype.where = function( f ) { var res = []; for ( var i = 0, n = this.length; i < n; i++ ) { if ( f( this[ i ] ) ) res.push( this[ i ] ); } return res; } } ); define( 'Array.nocomplex/findIndexOf',[],function() { Array.prototype.findIndexOf = function( f ) { for ( var i = 0, n = this.length; i < n; i++ ) { if ( f( this[ i ], i ) ) return i; } return false; }; } ); define( 'Array.nocomplex/findByKey',[],function() { Array.prototype.findByKey = function( key, value ) { for ( var i = 0, n = this.length; i < n; i++ ) { if ( this[ i ][ key ] === value ) return this[ i ]; } return false; }; } ); define( 'Array.nocomplex/basics',[ './collect', './each', './first', './has', './last', './map', './onEls', './remove', './removeOneValue', './remove', './except', './exceptFn', './indexOf', './isIn', './send', './uniq', './equals', './find', './where', './findIndexOf', './findByKey' ], function(){ return Array.prototype }); define( 'Array.nocomplex/math/all',[],function() { var methods = { equals: function( a ) { for ( var i = this.length; i--; ) if ( a[ i ] !== this[ i ] ) return false; return true; }, multiply: function( a ) { var ret = []; if ( typeof( a ) === 'number' ) { for ( var i = this.length; i--; ) { ret[ i ] = this[ i ] * a; } } else { for ( var i = this.length; i--; ) { ret[ i ] = this[ i ] * a[ i ]; } } return ( ret ); }, divide: function( a ) { var ret = []; if ( typeof( a ) === 'number' ) { for ( var i = this.length; i--; ) { ret[ i ] = this[ i ] / a; } } else { for ( var i = this.length; i--; ) { ret[ i ] = this[ i ] / a[ i ]; } } return ( ret ); }, min: function( f ) { var r = f ? this.map( f ) : this return Math.min.apply( null, r ) }, minMax: function( f ) { return [ this.min( f ), this.max( f ) ] }, max: function( f ) { var r = f ? this.map( f ) : this return Math.max.apply( null, r ) }, average: function() { var ave = 0; for ( var i = this.length; i--; ) { ave += this[ i ] } return ave / this.length }, minus: function( a ) { var ret = []; if ( typeof( a ) === 'number' ) { for ( var i = this.length; i--; ) { ret[ i ] = this[ i ] - a; } } else { for ( var i = this.length; i--; ) { ret[ i ] = this[ i ] - a[ i ]; } } return ( ret ); }, domain: function( bounds, range ) { var min = range && typeof range[ 0 ] === "number" ? range[ 0 ] : this.min(), max = range && typeof range[ 1 ] === "number" ? range[ 1 ] : this.max(), a, b; if ( min === max ) { // if all data are equal, return range[ 0 ] return this.map( function() {  return bounds[ 0 ] } ) } a = ( bounds[ 1 ] - bounds[ 0 ] ) / ( max - min ); b = ( bounds[ 0 ] * max - bounds[ 1 ] * min ) / ( max - min ) return this.multiply( a ).add( b ) }, add: function( a ) { var ret = []; if ( typeof( a ) === 'number' ) { for ( var i = this.length; i--; ) { ret[ i ] = this[ i ] + a; } } else { for ( var i = this.length; i--; ) { ret[ i ] = this[ i ] + a[ i ]; } } return ( ret ); }, round: function() { for ( var i = this.length; i--; ) { this[ i ] = Math.round( this[ i ] ); } return ( this ); }, sum: function( f ) { var r = 0 for ( var i = this.length; i--; ) { r += f( i ) } return r }, orth: function() { if ( this.length != 2 ) { throw Error; } return [ -this[ 1 ], this[ 0 ] ]; }, norm: function() { return Math.sqrt( this.sum( function( i ) { return i * i } ) ); } }; for ( var method in methods ) if ( methods.hasOwnProperty( method ) ) Array.prototype[  method ] = methods[ method ] return Array.prototype } ); define('Array.nocomplex/all',[ './basics', './math/all' ], function(){ return Array.prototype }); define( 'SeedView/Parser',[ 'Seed/Seed' ], function( Seed ) { return Seed.extend( { parse: function() { console.log( 'overide me' ) } } ) } ); define('SeedView/parsers/HTMLParser',[ '../Parser' ], function( Parser ){ return Parser.extend({ '+options': { name: 'html' }, '+constructor': function( ){ }, parse: function( view ) { // dirty var fragment = document.createElement(), container = document.createElement( 'container' ), flaggedElements container.innerHTML = view.template fragment.appendChild( container.childNodes[ 0 ] ) view._fragment = fragment view._elements = { root: view._fragment } flaggedElements = view.getElementsByAttribute( 'flag' ) for ( var i = 0; i < flaggedElements.length; i++ ) { view.addElement( flaggedElements[ i  ].getAttribute( 'flag' ), flaggedElements[ i ] ) } } }) }); /** * toDOM version: "0.0.7" Copyright (c) 2011-2012, Cyril Agosta ( cyril.agosta.dev@gmail.com) All Rights Reserved. * Available via the MIT license. * see: http://github.com/cagosta/toDOM for details */ define( 'toDOM/toDOM',[],function () { return function toDOM( tree, scope ) { var obj = tree, k, l, el, attr, childEl, p, q, evt, style, children if ( !obj.tag ) obj.tag = 'div' el = document.createElement( obj.tag ) if ( obj.attr ) for ( attr in obj.attr ) if ( obj.attr.hasOwnProperty( attr ) ) el.setAttribute( attr, obj.attr[ attr ] ) if ( obj.label ) scope[ obj.label ] = el if ( obj.className ) el.className = obj.className if ( typeof( obj.innerHTML ) !== 'undefined' ) if ( typeof( obj.innerHTML ) === 'function' ) el.innerHTML = obj.innerHTML.call( scope ) || '' else el.innerHTML = obj.innerHTML if ( obj.events ) for ( evt in obj.events ) if ( obj.events.hasOwnProperty( evt ) ) el[ 'on' + evt ] = obj.events[ evt ] if ( obj.style ) for ( style in obj.style ) if ( obj.style.hasOwnProperty( style ) ) el.style[ style ] = obj.style[ style ] if ( obj.children ) { children = obj.children for ( k = 0, l = children.length; k < l; k++ ) { childEl = toDOM( children[ k ], scope ) el.appendChild( childEl ) } } return el } } ); define('SeedView/parsers/ToDOMParser',[ '../Parser', 'toDOM/toDOM' ], function( Parser, toDOM ){ return Parser.extend({ '+options': { name: 'toDOM' }, '+constructor': function( ){ }, parse: function( view ){ // dirty var elements = { }, template = view.getTemplate(), node = toDOM( template, elements ) return { node: node, elements: elements } } }) }); define( 'SeedView/parsers/DOMParser',[ '../Parser' ], function( Parser ) { return Parser.extend( { '+options': { name: 'dom' }, '+constructor': function() { }, parse: function( view ) { // todo add label? return { node: view.getTemplate() } } } ) } ); define( 'SeedView/parsers/defaultParsers',[ './HTMLParser', './ToDOMParser', './DOMParser' ], function( HTMLParser, ToDOMParser, DOMParser ) { return { toDOM: new ToDOMParser, html: new HTMLParser, dom: new DOMParser } } ); /** * SeedView version: "0.0.22" Copyright (c) 2011-2012, Cyril Agosta ( cyril.agosta.dev@gmail.com) All Rights Reserved. * Available via the MIT license. * see: http://github.com/cagosta/SeedView for details */ define( 'SeedView/SeedView',[ 'Seed/Seed', 'mangrove-utils/dom/all', 'Array.nocomplex/isArray', 'String.nocomplex/String.nocomplex', 'Array.nocomplex/all', './parsers/defaultParsers' ], function( Seed, dom, isArray, Str, Arr, defaultParsers ) { /** * * @constructor SeedView * */ var View = Seed.extend(  { type: 'View', accessors: [ 'data', 'node', 'template', 'elements' ], '+options': { parser: 'toDOM', // retrocompatibility, todo remove me template: null, events: null, data: null, parsers: defaultParsers, subviews: null, contained: null, elements: null, node: null }, _isView: true, '+constructor': function( a, b ) { this.data = this.data ||  {} this.subviews = this.subviews || {} this.contained = this.contained || {} this.elements = this.elements  || {} this.detectParser() this.parse() if ( typeof this.data === 'function' ) this.data = this.data.bind( this )() if ( this.events ) this.DOMEvent( this.events ) this._displayState = {} }, hasElement: function( label ) { return !!this.elements[ label ] }, buildSubviews: function() { this.eachElement( function( el, key ) { this.subviews[ key ] = new View( { template: el } ) }.bind( this ) ) }, eachElement: function( f ) { var elementIds = Object.keys( this.elements ), elements = this.elements; elementIds.each( function( key ) { f( elements[ key ], key ) } ) }, parse: function() { var parser = this.parsers[  this.parser ], parsed, elements if ( !parser ) throw new Error( 'No parser: ' + this.parser ) parsed = parser.parse( this ) if ( !parsed ) throw new Error( 'Parse error ' ) if ( !parsed.node ) throw new Error( 'No node given from parse' ) this.setNode( parsed.node ) elements = parsed.elements if ( !elements ) elements = {} elements.root = parsed.node this.setElements( elements ) }, addElement: function( key, el ) { this.elements[  key ] = el this.contained[  key ] = [] }, subview: function( label ) { // to do return this.subviews[ label ] }, getElementById: function( elmLabel, id ) { if ( !id ) { id = elmLabel elmLabel = 'root' } return this.element( elmLabel ).getElementById( id ) }, getElementsByClassName: function( elmLabel, className ) { if ( !className ) { className = elmLabel elmLabel = 'root' } return this.element( elmLabel ).getElementsByClassName( className ) }, detectParser: function() { if ( !this.template ) throw new Error( 'views/View needs a valid template' ) if ( this.parser ) return if ( this.template.nodeName ) this.parser = 'dom' else if ( typeof this.template === 'string' && this.template.charAt( 0 ) === '<' ) this.parser = 'html' }, getElementByAttribute: function( attribute, value ) { var allElements = this.element( 'root' ).getElementsByTagName( '*' ) for ( var i = 0; i < allElements.length; i++ ) { if ( allElements[ i ].getAttribute( attribute ) === value ) { return allElements[ i ]; } } }, getElementsByAttribute: function( attribute ) { var ret = [] var allElements = this.element( 'root' ).getElementsByTagName( '*' ) for ( var i = 0; i < allElements.length; i++ ) { if ( allElements[ i ].getAttribute( attribute ) ) { ret.push( allElements[ i ] ) } } return ret }, html: function() { return this.node }, clone: function() { return new View( this.template, this.data ) }, element: function( name ) { if ( !this.elements || !this.elements[ name ] ) debugger return this.elements[ name ] }, DOMEvent: function( eltRef, event, handler, capture ) { // Benj code, pretty huh ? var view = this, elt, k, c if ( arguments.length <= 2 && eltRef && eltRef.constructor === Object ) { c = !! arguments[ 1 ] for ( k in eltRef ) ( function( eltRef, events ) { var k for ( k in events ) view.DOMEvent( eltRef, k, events[ k ], c ) }( k, eltRef[ k ] ) ) } else if ( elt = view.element( eltRef ), elt ) ( function( elt, handler, view ) { var events = event.split( " " ), i = 0, l = events.length for ( ; i < l; i++ ) dom.addEventListener( elt, events[ i ], function( e ) { handler.apply( view, [  e, view ] ) }, !! capture ) }( elt, handler, view ) ) return view }, checkArguments: function( args, check ) { var allArgs = Array.prototype.slice.call( args ) // why ? return allArgs.length === check; }, toggle: function( elmLabel ) { elmLabel = elmLabel || 'root' if ( typeof this._displayState[ elmLabel ] === 'undefined' ) { this._displayState[ elmLabel ] = 1 } this._displayState[ elmLabel ] ? this.hide( elmLabel ) : this.show( elmLabel ) }, show: function( elmLabel ) { elmLabel = elmLabel ||  'root' this.css( elmLabel, { display: 'block' } ) this._displayState[ elmLabel ] = 1 }, hide: function( elmLabel ) { elmLabel = elmLabel || 'root' this.css( elmLabel, { display: 'none' } ) this._displayState[ elmLabel ] = 0 }, prepend: function() { }, attachEvent: function( elmLabel, eventName, cb ) { if ( this.checkArguments( arguments, 2 ) ) { cb = eventName; eventName = elmLabel; elmLabel = 'root'; } var el = this.element( elmLabel ) dom.addEventListener( el, eventName, cb.bind( this ) ) }, attachEvents: function( elmLabel, o ) { if ( !o ) { o = elmLabel elmLabel = 'root' } for ( var eventName in o ) if ( o.hasOwnProperty( eventName ) ) this.attachEvent( elmLabel, eventName, o[ eventName ] ) }, css: function( elmLabel, o ) { var el, style if ( this.checkArguments( arguments, 1 ) ) { o = elmLabel; elmLabel = 'root'; } el = this.element( elmLabel ) style = el.style; if ( typeof o !== 'string' ) for ( var i in o ) if ( o.hasOwnProperty( i ) ) style[ i ] = o[ i ] else for ( var i in el ) if ( el.hasOwnProperty( i ) ) if ( i == o ) return style[ o ] }, attr: function( elmLabel, o ) { var el if ( this.checkArguments( arguments, 1 ) ) { o = elmLabel; elmLabel = 'root'; } el = this.element( elmLabel ) for ( var i in o ) if ( o.hasOwnProperty( i ) ) el[ i ] = o[ i ] }, append: function( elmLabel, node ) { if ( !node ) { node = elmLabel elmLabel = 'root' } this.element( elmLabel ).appendChild( node ) }, innerText: function( elmLabel, text ) { var el if ( typeof text === 'undefined' ) { text = elmLabel elmLabel = 'root' } el = this.element( elmLabel ) if ( 'innerText' in el ) el.innerText = text else el.textContent = text }, innerHTML: function( elmLabel, text ) { elmLabel = elmLabel ||  'root' var el = this.element( elmLabel ) el.innerHTML = text }, hasClass: function( elmLabel, name ) { if ( this.checkArguments( arguments, 1 ) ) { name = elmLabel; elmLabel = 'root'; } var el = this.element( elmLabel ) return ( new RegExp( '(\\s|^)' + name + '(\\s|$)' ) ).test( el.className ) }, addClass: function( elmLabel, name ) { if ( this.checkArguments( arguments, 1 ) ) { name = elmLabel; elmLabel = 'root'; } var el = this.element( elmLabel ) if ( !this.hasClass( elmLabel, name ) ) { el.className += ( el.className ? ' ' : '' ) + name } }, removeClass: function( elmLabel, name ) { if ( this.checkArguments( arguments, 1 ) ) { name = elmLabel elmLabel = 'root' } var el = this.element( elmLabel ) if ( this.hasClass( elmLabel, name ) ) el.className = el.className.replace( new RegExp( '(\\s|^)' + name + '(\\s|$)' ), ' ' ).replace( /^\s+|\s+$/g, '' ) }, insert: function( elmLabel, views ) { if ( !views ) { views = elmLabel elmLabel = 'container' } views = Array.isArray( views ) ? views : [ views ] this.contained[ elmLabel ] = this.contained[ elmLabel ] ||  [] views.each( function( view ) { this.insertView( elmLabel, view ) }.bind( this ) ) }, viewContained: function( elmLabel ) { if ( !elmLabel ) elmLabel = 'container' return this.contained[ elmLabel ] }, insertView: function( elmLabel, view ) { if ( !view ) debugger // hell yeah this.contained[ elmLabel ].push( view ) this.element( elmLabel ).appendChild( view.html() ) }, insertAt: function( elmLabel, view, index ) { var el elmLabel = elmLabel ||  'container' el = this.element( elmLabel ) el.insertBefore( view.html(), el.childNodes[ index ] ) }, reoder: function( elmLabel, view, index ) { // broken var fromIndex = this.contained[  elmLabel ].indexOf( view ) elmLabel = elmLabel ||  'container' if ( fromIndex !== -1 ) { this.contained[ elmLabel ].splice( index, 0, this.contained[  elmLabel ].splice( fromIndex, 1 )[ 0 ] ) this.remove( elmLabel, view ) this.insertAt( elmLabel, view, index ) } }, removeAll: function( elmLabel ) { if ( !elmLabel ) elmLabel = 'container' if ( !this.hasContained( elmLabel ) ) return for ( var i = 0; i < this.contained[ elmLabel ].length; i++ ) this.remove( elmLabel, this.contained[ elmLabel ][ i ] ) }, hasContained: function( elmLabel ) { return !!this.contained[ elmLabel ] }, recover: function() { var root = this.element( 'root' ) if ( root.parentNode ) root.parentNode.removeChild( root ) }, remove: function( elmLabel, view ) { var index elmLabel = elmLabel || 'container' index = this.contained[ elmLabel ].indexOf( view ) el = view.element( 'root' ) if ( index !== -1 ) { el.parentNode && el.parentNode.removeChild( el ) } }, eachContained: function( f ) { for ( var element in this.contained ) if ( this.contained.hasOwnProperty( element ) ) f( this.viewContained( element ), element ) }, hasElement: function( label ) { return !!this.elements[ label ] }, containA: function( label ) { return !!this.contained[ label ] }, contain: function( label, view ) { if ( !view ) { view = label label = 'container' } return this.containA( label ) && this.contained[ label ].has( view ) }, hasParentNode: function() { return !!this.getParentNode() }, getParentNode: function() { return this.element( 'root' ).parentNode }, hasText: function( elmLabel, text ) { var regexp, el, innerText if ( !text ) { text = elmLabel elmLabel = 'root' } regexp = text if ( typeof regexp === 'string' ) regexp = new RegExp( regexp, 'gi' ) el = this.element( elmLabel ) if ( !el ) return false innerText = el.innerHTML return regexp.test( innerText ) } } ) return View } ); var EngineDetector = function() { this.isNode = false this.isBrowser = false this.isUnknown = false this._exports this.detect() } EngineDetector.prototype = { detect: function() { if ( typeof module !== 'undefined' && module.exports ) this._setAsNode() else if ( typeof window !== "undefined" ) this._setAsBrowser() else this._setAsUnknown() }, _setAsNode: function() { this.isNode = true this.name = 'node' }, _setAsBrowser: function() { this.isBrowser = true this._global = window this.name = 'browser' }, _setAsUnknown: function() { this.isUnknown = true this.name = 'unknown' }, setGlobal: function( e ) { this._global = e }, ifNode: function( f ) { if ( this.isNode ) f() }, ifBrowser: function( f ) { if ( this.isBrowser ) f() }, exports: function( key, exported ) { if ( this.isNode ) { this._global.exports = exported } else if ( this.isBrowser ) this._global[  key ] = exported }, } var engine = new EngineDetector() var baseUrl, requirejs; engine.ifNode( function() { baseUrl = __dirname requirejs = require( 'requirejs' ) engine.setGlobal( module ) } ) engine.ifBrowser( function() { baseUrl = '.' } ) requirejs.config( { baseUrl: function(){ return ( typeof define === 'undefined') ? __dirname: '.'}(), shim: { mocha: { exports: 'mocha' } }, paths: { SeedView: '.', engineDetector: 'bower_components/engineDetector/app', almond: 'bower_components/almond/almond', chai: 'bower_components/chai/chai', 'chai-as-promised': 'bower_components/chai-as-promised/lib/chai-as-promised', mocha: 'bower_components/mocha/mocha', 'normalize-css': 'bower_components/normalize-css/normalize.css', requirejs: 'bower_components/requirejs/require', async: 'bower_components/requirejs-plugins/src/async', depend: 'bower_components/requirejs-plugins/src/depend', font: 'bower_components/requirejs-plugins/src/font', goog: 'bower_components/requirejs-plugins/src/goog', image: 'bower_components/requirejs-plugins/src/image', json: 'bower_components/requirejs-plugins/src/json', mdown: 'bower_components/requirejs-plugins/src/mdown', noext: 'bower_components/requirejs-plugins/src/noext', propertyParser: 'bower_components/requirejs-plugins/src/propertyParser', 'Markdown.Converter': 'bower_components/requirejs-plugins/lib/Markdown.Converter', text: 'bower_components/requirejs-plugins/lib/text', 'sinon-chai': 'bower_components/sinon-chai/lib/sinon-chai', sinonjs: 'bower_components/sinonjs/sinon', 'Array.nocomplex': 'bower_components/Array.nocomplex/app', 'String.nocomplex': 'bower_components/String.nocomplex/app', 'mangrove-utils': 'bower_components/mangrove-utils/app', 'underscore.string': 'bower_components/underscore.string/lib/underscore.string', ifEngineIsNode: 'bower_components/engineDetector/app/ifEngineIsNode', ifEngineIsBrowser: 'bower_components/engineDetector/app/ifEngineIsBrowser', toDOM: 'bower_components/toDOM/app', Seed: 'bower_components/Seed/app', window: 'bower_components/engineDetector/app/window', engine: 'bower_components/engineDetector/app/engine' } } ) var isStandalone = !! requirejs._defined, synchronous = isStandalone engine.ifNode(function(){ synchronous = true }) if ( synchronous ) { // case standalone var SeedView = requirejs( 'SeedView/SeedView' ) engine.exports( 'SeedView', SeedView ) } else { requirejs( [ 'SeedView/SeedView' ], function( SeedView ) { engine.exports( 'SeedView', SeedView ) } ) } ; define("SeedView/main", function(){}); }());