UNPKG

todomvc

Version:

> Helping you select an MV\* framework

1,529 lines (1,419 loc) 411 kB
(function() { //just a shim for cordova, because the actual dependency will differ between //Android and iOS define('cordova',[],function() { return window.cordova; }); define('lavaca/util/extend',[],function() { /** * Establishes inheritance between types. After a type is extended, it receives its own static * convenience method, extend(TSub, overrides). * @class lavaca.util.extend */ /** * Establishes inheritance between types. After a type is extended, it receives its own static * convenience method, extend(TSub, overrides). * @method extend * @static * */ /** * Establishes inheritance between types. After a type is extended, it receives its own static * convenience method, extend(TSub, overrides). * @method extend * @static * @param {Function} TSub The child type which will inherit from superType * @param {Object} overrides A hash of key-value pairs that will be added to the subType * @return {Function} The subtype * */ /** * Establishes inheritance between types. After a type is extended, it receives its own static * convenience method, extend(TSub, overrides). * @method extend * @static * @param {Function} TSuper The base type to extend * @param {Function} TSub The child type which will inherit from superType * @param {Object} overrides A hash of key-value pairs that will be added to the subType * @return {Function} The subtype */ var extend = function(TSuper, TSub, overrides) { if (typeof TSuper === 'object') { overrides = TSuper; TSuper = Object; TSub = function() { // Empty }; } else if (typeof TSub === 'object') { overrides = TSub; TSub = TSuper; TSuper = Object; } function ctor() { // Empty } ctor.prototype = TSuper.prototype; TSub.prototype = new ctor; TSub.prototype.constructor = TSub; if (overrides) { for (var name in overrides) { TSub.prototype[name] = overrides[name]; } } TSub.extend = function(T, overrides) { if (typeof T === 'object') { overrides = T; T = function() { TSub.apply(this, arguments); }; } extend(TSub, T, overrides); return T; }; return TSub; }; return extend; }); define('lavaca/util/Promise',['require','./extend'],function(require) { var extend = require('./extend'); /** * Utility type for asynchronous programming * @class lavaca.util.Promise * * @constructor * * @param {Object} thisp What the "this" keyword resolves to in callbacks */ var Promise = extend(function(thisp) { /** * What the "this" keyword resolves to in callbacks * @property {Object} thisp * @default null */ this.thisp = thisp; /** * Pending handlers for the success event * @property {Array} resolvedQueue * @default [] */ this.resolvedQueue = []; /** * Pending handlers for the error event * @property {Array} rejectedQueue * @default [] */ this.rejectedQueue = []; }, { /** * Flag indicating that the promise completed successfully * @property {Boolean} succeeded * @default false */ succeeded: false, /** * Flag indicating that the promise failed to complete * @property {Boolean} failed * @default false */ failed: false, /** * Queues a callback to be executed when the promise succeeds * @method success * * @param {Function} callback The callback to execute * @return {Lavaca.util.Promise} This promise (for chaining) */ success: function(callback) { if (callback) { if (this.succeeded) { callback.apply(this.thisp, this.resolveArgs); } else { this.resolvedQueue.push(callback); } } return this; }, /** * Queues a callback to be executed when the promise fails * @method error * * @param {Function} callback The callback to execute * @return {Lavaca.util.Promise} This promise (for chaining) */ error: function(callback) { if (callback) { if (this.failed) { callback.apply(this.thisp, this.rejectArgs); } else { this.rejectedQueue.push(callback); } } return this; }, /** * Queues a callback to be executed when the promise is either rejected or resolved * @method always * * @param {Function} callback The callback to execute * @return {Lavaca.util.Promise} This promise (for chaining) */ always: function(callback) { return this.then(callback, callback); }, /** * Queues up callbacks after the promise is completed * @method then * * @param {Function} resolved A callback to execute when the operation succeeds * @param {Function} rejected A callback to execute when the operation fails * @return {Lavaca.util.Promise} This promise (for chaining) */ then: function(resolved, rejected) { return this .success(resolved) .error(rejected); }, /** * Resolves the promise successfully * @method resolve * * @params {Object} value Values to pass to the queued success callbacks * @return {Lavaca.util.Promise} This promise (for chaining) */ resolve: function(/* value1, value2, valueN */) { if (!this.succeeded && !this.failed) { this.succeeded = true; this.resolveArgs = [].slice.call(arguments, 0); var i = -1, callback; while (!!(callback = this.resolvedQueue[++i])) { callback.apply(this.thisp, this.resolveArgs); } } return this; }, /** * Resolves the promise as a failure * @method reject * * @params {String} err Failure messages * @return {Lavaca.util.Promise} This promise (for chaining) */ reject: function(/* err1, err2, errN */) { if (!this.succeeded && !this.failed) { this.failed = true; this.rejectArgs = [].slice.call(arguments, 0); var i = -1, callback; while (!!(callback = this.rejectedQueue[++i])) { callback.apply(this.thisp, this.rejectArgs); } } return this; }, /** * Queues this promise to be resolved only after several other promises * have been successfully resolved, or immediately rejected when one * of those promises is rejected * @method when * * @params {Lavaca.util.Promise} promise One or more other promises * @return {Lavaca.util.Promise} This promise (for chaining) */ when: function(/* promise1, promise2, promiseN */) { var self = this, values = [], i = -1, pendingPromiseCount = arguments.length, promise; while (!!(promise = arguments[++i])) { (function(index) { promise .success(function(v) { values[index] = v; if (--pendingPromiseCount < 1) { self.resolve.apply(self, values); } }) .error(function() { self.reject.apply(self, arguments); }); })(i); } promise = null; return this; }, /** * Produces a callback that resolves the promise with any number of arguments * @method resolver * @return {Function} The callback */ resolver: function() { var self = this; return function() { self.resolve.apply(self, arguments); }; }, /** * Produces a callback that rejects the promise with any number of arguments * @method rejector * * @return {Function} The callback */ rejector: function() { var self = this; return function() { self.reject.apply(self, arguments); }; } }); /** * * Creates a promise to be resolved only after several other promises * have been successfully resolved, or immediately rejected when one * of those promises is rejected * @method when * @static * @params {Lavaca.util.Promise} promise One or more other promises * @return {Lavaca.util.Promise} The new promise */ /** * Creates a promise to be resolved only after several other promises * have been successfully resolved, or immediately rejected when one * of those promises is rejected * @method when * @static * @param {Object} thisp The execution context of the promise * @params {Lavaca.util.Promise} promise One or more other promises * @return {Lavaca.util.Promise} The new promise */ Promise.when = function(thisp/*, promise1, promise2, promiseN */) { var thispIsPromise = thisp instanceof Promise, promise = new Promise(thispIsPromise ? window : thisp), args = [].slice.call(arguments, thispIsPromise ? 0 : 1); return promise.when.apply(promise, args); }; return Promise; }); define('lavaca/env/Device',['require','$','cordova','lavaca/util/Promise'],function(require) { var $ = require('$'), Cordova = require('cordova'), Promise = require('lavaca/util/Promise'); /** * Static utility type for working with Cordova (aka PhoneGap) and other non-standard native functionality * @class lavaca.env.Device */ var _initHasRun = false, _onInit = []; var Device = {}; /** * Indicates whether or not the app is being run through Cordova * @method isCordova * @static * * @return {Boolean} True if app is being run through Cordova */ Device.isCordova = function() { return !!Cordova; }; /** * Registers a plugin to be initialized when the device is ready * @method register * @static * * @param {String} name * @param {Function} TPlugin The plugin to register. The plugin should be a constructor function */ Device.register = function(name, TPlugin) { function install() { if (!window.plugins) { window.plugins = {}; } window.plugins[name] = new TPlugin(); } if (_initHasRun) { install(); } else { _onInit.push(install); } }; /** * Executes a Cordova command, if Cordova is available * @method exec * @static * * @param {String} className The name of the native class * @param {String} methodName The name of the class method to call * @param {Array} args Arguments to pass the method * @return {Lavaca.util.Promise} A promise */ Device.exec = function(className, methodName, args) { var promise = new Promise(window); if (Cordova) { Cordova.exec(promise.resolver(), promise.rejector(), className, methodName, args); } else { promise.reject(); } return promise; }; /** * Executes a callback when the device is ready to be used * @method init * @static * * @param {Function} callback The handler to execute when the device is ready */ Device.init = function(callback) { if (!Cordova) { $(document).ready(callback); } else if (document.addEventListener) { // Android fix document.addEventListener('deviceready', callback, false); } else { $(document).on('deviceready', callback); } }; $(document).ready(function() { var i = -1, installPlugin; while (!!(installPlugin = _onInit[++i])) { installPlugin(); } _initHasRun = true; }); return Device; }); define('lavaca/util/Disposable',['require','./extend'],function(require) { var extend = require('./extend'); function _disposeOf(obj) { var n, o, i; for (n in obj) { if (obj.hasOwnProperty(n)) { o = obj[n]; if (o) { if (typeof o === 'object' && typeof o.dispose === 'function') { o.dispose(); } else if (o instanceof Array) { for (i = o.length - 1; i > -1; i--) { if (o[i] && typeof o[i].dispose === 'function') { o[i].dispose(); } else { _disposeOf(o[i]); } } } } } } } /** * Abstract type for types that need to ready themselves for GC * @class lavaca.util.Disposable * @constructor * */ var Disposable = extend({ /** * Readies the object to be garbage collected * @method dispose * */ dispose: function() { _disposeOf(this); } }); return Disposable; }); define('mout/object/hasOwn',[],function () { /** * Safer Object.hasOwnProperty */ function hasOwn(obj, prop){ return Object.prototype.hasOwnProperty.call(obj, prop); } return hasOwn; }); define('mout/object/forIn',[],function () { var _hasDontEnumBug, _dontEnums; function checkDontEnum(){ _dontEnums = [ 'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor' ]; _hasDontEnumBug = true; for (var key in {'toString': null}) { _hasDontEnumBug = false; } } /** * Similar to Array/forEach but works over object properties and fixes Don't * Enum bug on IE. * based on: http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation */ function forIn(obj, fn, thisObj){ var key, i = 0; // no need to check if argument is a real object that way we can use // it for arrays, functions, date, etc. //post-pone check till needed if (_hasDontEnumBug == null) checkDontEnum(); for (key in obj) { if (exec(fn, obj, key, thisObj) === false) { break; } } if (_hasDontEnumBug) { while (key = _dontEnums[i++]) { // since we aren't using hasOwn check we need to make sure the // property was overwritten if (obj[key] !== Object.prototype[key]) { if (exec(fn, obj, key, thisObj) === false) { break; } } } } } function exec(fn, obj, key, thisObj){ return fn.call(thisObj, obj[key], key, obj); } return forIn; }); define('mout/object/forOwn',['./hasOwn', './forIn'], function (hasOwn, forIn) { /** * Similar to Array/forEach but works over object properties and fixes Don't * Enum bug on IE. * based on: http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation */ function forOwn(obj, fn, thisObj){ forIn(obj, function(val, key){ if (hasOwn(obj, key)) { return fn.call(thisObj, obj[key], key, obj); } }); } return forOwn; }); define('mout/lang/isPlainObject',[],function () { /** * Checks if the value is created by the `Object` constructor. */ function isPlainObject(value) { return (!!value && typeof value === 'object' && value.constructor === Object); } return isPlainObject; }); define('mout/object/deepMixIn',['./forOwn', '../lang/isPlainObject'], function (forOwn, isPlainObject) { /** * Mixes objects into the target object, recursively mixing existing child * objects. */ function deepMixIn(target, objects) { var i = 0, n = arguments.length, obj; while(++i < n){ obj = arguments[i]; if (obj) { forOwn(obj, copyProp, target); } } return target; } function copyProp(val, key) { var existing = this[key]; if (isPlainObject(val) && isPlainObject(existing)) { deepMixIn(existing, val); } else { this[key] = val; } } return deepMixIn; }); define('lavaca/events/EventDispatcher',['require','lavaca/util/Disposable','mout/object/deepMixIn'],function(require) { var Disposable = require('lavaca/util/Disposable'), deepMixIn = require('mout/object/deepMixIn'); /** * Basic event dispatcher type * @class lavaca.events.EventDispatcher * @extends lavaca.util.Disposable * @constructor * */ var EventDispatcher = Disposable.extend({ /** * When true, do not fire events * @property suppressEvents * @type Boolean * @default false * */ suppressEvents: false, /** * Bind an event handler to this object * @method on * * @param {String} type The name of the event * @param {Function} callback The function to execute when the event occurs * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ /** * Bind an event handler to this object * @method on * * @param {String} type The name of the event * @param {Function} callback The function to execute when the event occurs * @param {Object} thisp The context of the handler * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ on: function(type, callback, thisp) { var calls = this.callbacks || (this.callbacks = {}), list = calls[type] || (calls[type] = []); list[list.length] = {fn: callback, thisp: thisp}; return this; }, /** * Unbinds all event handler from this object * @method off * * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ /** * Unbinds all event handlers for an event * @method off * * @param {String} type The name of the event * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ /** * Unbinds a specific event handler * @method off * * @param {String} type The name of the event * @param {Function} callback The function handling the event * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ /** * Unbinds a specific event handler * @method off * * @param {String} type The name of the event * @param {Function} callback The function handling the event * @param {Object} thisp The context of the handler * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ off: function(type, callback, thisp) { var calls = this.callbacks, list, handler, i = -1, newList, isCallback, isThisp; if (!type) { delete this.callbacks; } else if (calls) { if (!callback) { delete calls[type]; } else { list = calls[type]; if (list) { newList = calls[type] = []; while (!!(handler = list[++i])) { isCallback = handler.fn === callback || handler.fn.fn === callback || (handler.fn.guid && handler.fn.guid === callback.guid) || // Check if is jQuery proxy of callback (handler.fn._zid && handler.fn._zid === callback._zid); // Check if is Zepto proxy of callback isThisp = thisp && (handler.thisp === thisp || handler.fn.thisp === thisp); if (!isCallback || (thisp && !isThisp)) { newList[newList.length] = handler; } } } } } return this; }, /** * Dispatches an event * @method trigger * * @param {String} type The type of event to dispatch * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ /** * Dispactches an event with additional parameters * @method trigger * * @param {String} type The type of event to dispatch * @param {Object} params Additional data points to add to the event * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ trigger: function(type, params) { if (!this.suppressEvents && this.callbacks) { var list = this.callbacks[type], event = this.createEvent(type, params), i = -1, handler; if (list) { while (!!(handler = list[++i])) { handler.fn.apply(handler.thisp || this, [event]); } } } return this; }, /** * Creates an event object * @method createEvent * * @param {String} type The type of event to create * @return {Object} The event object */ /** * Creates an event object with additional params * @method createEvent * * @param {String} type The type of event to create * @param {Object} params Additional data points to add to the event * @return {Object} The event object */ createEvent: function(type, params) { return deepMixIn({}, params || {}, { type: type, target: params && params.target ? params.target : this, currentTarget: this }); } }); return EventDispatcher; }); define('lavaca/env/ChildBrowser',['require','lavaca/env/Device','lavaca/events/EventDispatcher','lavaca/util/Promise'],function(require) { var Device = require('lavaca/env/Device'), EventDispatcher = require('lavaca/events/EventDispatcher'), Promise = require('lavaca/util/Promise'); /** * A sub-browser management utility (also accessible via window.plugins.childBrowser) * @class lavaca.env.ChildBrowser * @extends Lavaca.events.EventDispatcher * * @event open * @event close * @event change * * @constructor */ var ChildBrowser = EventDispatcher.extend({ /** * Opens a web page in the child browser (or navigates to it) * @method showWebPage * * @param {String} loc The URL to open * @return {Lavaca.util.Promise} A promise */ showWebPage: function(loc) { if (Device.isCordova()) { return Device .exec('ChildBrowser', 'showWebPage', [loc]) .error(function() { window.location.href = loc; }); } else { window.open(loc); return new Promise(window).resolve(); } }, /** * Closes the child browser, if it's open * @method close * * @return {Lavaca.util.Promise} A promise */ close: function() { return Device.exec('ChildBrowser', 'close', []); } }); Device.register('childBrowser', ChildBrowser); return ChildBrowser; }); define('lavaca/env/Detection',['require','$'],function(require) { var $ = require('$'); var Detection = {}; Detection.agent = navigator.userAgent.toLowerCase(); Detection.scrWidth = screen.width; Detection.scrHeight = screen.height; Detection.viewportWidth = window.innerWidth; Detection.viewportHeight = window.innerHeight; Detection.elemWidth = document.documentElement.clientWidth; Detection.elemHeight = document.documentElement.clientHeight; Detection.otherBrowser = (Detection.agent.search(/series60/i) > -1) || (Detection.agent.search(/symbian/i) > -1) || (Detection.agent.search(/windows\sce/i) > -1) || (Detection.agent.search(/blackberry/i) > -1); Detection.mobileOS = typeof orientation !== 'undefined'; Detection.touchOS = 'ontouchstart' in document.documentElement; Detection.blackberry = Detection.agent.search(/blackberry/i) > -1; Detection.ipad = Detection.agent.search(/ipad/i) > -1; Detection.ipod = Detection.agent.search(/ipod/i) > -1; Detection.iphone = Detection.agent.search(/iphone/i) > -1; Detection.palm = Detection.agent.search(/palm/i) > -1; Detection.symbian = Detection.agent.search(/symbian/i) > -1; Detection.iOS = Detection.iphone || Detection.ipod || Detection.ipad; Detection.iOS5 = Detection.iOS && Detection.agent.search(/os 5_/i) > 0; Detection.iOSChrome = Detection.iOS && Detection.agent.search(/CriOS/i) > 0; Detection.android = (Detection.agent.search(/android/i) > -1) || (!Detection.iOS && !Detection.otherBrowser && Detection.touchOS && Detection.mobileOS); Detection.android2 = Detection.android && (Detection.agent.search(/android\s2/i) > -1); Detection.isMobile = Detection.android || Detection.iOS || Detection.mobileOS || Detection.touchOS; Detection.android23AndBelow = (function() { var matches = Detection.agent.match(/android\s(\d)\.(\d)/i); var vi, vd; if (Array.isArray(matches) && matches.length === 3) { vi = parseInt(matches[1], 10); vd = parseInt(matches[2], 10); return (vi === 2 && vd < 3) || vi < 2; } return false; }()); Detection.iOS4AndBelow = (function() { var matches = Detection.agent.match(/os\s(\d)_/i); var v; if (Array.isArray(matches) && matches.length === 2) { v = parseInt(matches[1], 10); return v <= 4; } return false; }()); Detection.addCustomDetection = function(condition, feature, selector) { var el; if (Detection.hasOwnProperty(feature)) { throw Error('Namespace "' + feature + '" is already taken by Detection module'); } Detection[feature] = condition; if (selector !== null) { el = selector ? $(selector) : $(document.documentElement); el.toggleClass(feature, typeof condition === 'function' ? condition() : condition); } }; Detection.animationEnabled = !Detection.android; return Detection; }); define('lavaca/env/Device',['require','$','cordova','lavaca/util/Promise'],function(require) { var $ = require('$'), Cordova = require('cordova'), Promise = require('lavaca/util/Promise'); /** * Static utility type for working with Cordova (aka PhoneGap) and other non-standard native functionality * @class lavaca.env.Device */ var _initHasRun = false, _onInit = []; var Device = {}; /** * Indicates whether or not the app is being run through Cordova * @method isCordova * @static * * @return {Boolean} True if app is being run through Cordova */ Device.isCordova = function() { return !!Cordova; }; /** * Registers a plugin to be initialized when the device is ready * @method register * @static * * @param {String} name * @param {Function} TPlugin The plugin to register. The plugin should be a constructor function */ Device.register = function(name, TPlugin) { function install() { if (!window.plugins) { window.plugins = {}; } window.plugins[name] = new TPlugin(); } if (_initHasRun) { install(); } else { _onInit.push(install); } }; /** * Executes a Cordova command, if Cordova is available * @method exec * @static * * @param {String} className The name of the native class * @param {String} methodName The name of the class method to call * @param {Array} args Arguments to pass the method * @return {Lavaca.util.Promise} A promise */ Device.exec = function(className, methodName, args) { var promise = new Promise(window); if (Cordova) { Cordova.exec(promise.resolver(), promise.rejector(), className, methodName, args); } else { promise.reject(); } return promise; }; /** * Executes a callback when the device is ready to be used * @method init * @static * * @param {Function} callback The handler to execute when the device is ready */ Device.init = function(callback) { if (!Cordova) { $(document).ready(callback); } else if (document.addEventListener) { // Android fix document.addEventListener('deviceready', callback, false); } else { $(document).on('deviceready', callback); } }; $(document).ready(function() { var i = -1, installPlugin; while (!!(installPlugin = _onInit[++i])) { installPlugin(); } _initHasRun = true; }); return Device; }); define('lavaca/events/EventDispatcher',['require','lavaca/util/Disposable','mout/object/deepMixIn'],function(require) { var Disposable = require('lavaca/util/Disposable'), deepMixIn = require('mout/object/deepMixIn'); /** * Basic event dispatcher type * @class lavaca.events.EventDispatcher * @extends lavaca.util.Disposable * @constructor * */ var EventDispatcher = Disposable.extend({ /** * When true, do not fire events * @property suppressEvents * @type Boolean * @default false * */ suppressEvents: false, /** * Bind an event handler to this object * @method on * * @param {String} type The name of the event * @param {Function} callback The function to execute when the event occurs * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ /** * Bind an event handler to this object * @method on * * @param {String} type The name of the event * @param {Function} callback The function to execute when the event occurs * @param {Object} thisp The context of the handler * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ on: function(type, callback, thisp) { var calls = this.callbacks || (this.callbacks = {}), list = calls[type] || (calls[type] = []); list[list.length] = {fn: callback, thisp: thisp}; return this; }, /** * Unbinds all event handler from this object * @method off * * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ /** * Unbinds all event handlers for an event * @method off * * @param {String} type The name of the event * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ /** * Unbinds a specific event handler * @method off * * @param {String} type The name of the event * @param {Function} callback The function handling the event * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ /** * Unbinds a specific event handler * @method off * * @param {String} type The name of the event * @param {Function} callback The function handling the event * @param {Object} thisp The context of the handler * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ off: function(type, callback, thisp) { var calls = this.callbacks, list, handler, i = -1, newList, isCallback, isThisp; if (!type) { delete this.callbacks; } else if (calls) { if (!callback) { delete calls[type]; } else { list = calls[type]; if (list) { newList = calls[type] = []; while (!!(handler = list[++i])) { isCallback = handler.fn === callback || handler.fn.fn === callback || (handler.fn.guid && handler.fn.guid === callback.guid) || // Check if is jQuery proxy of callback (handler.fn._zid && handler.fn._zid === callback._zid); // Check if is Zepto proxy of callback isThisp = thisp && (handler.thisp === thisp || handler.fn.thisp === thisp); if (!isCallback || (thisp && !isThisp)) { newList[newList.length] = handler; } } } } } return this; }, /** * Dispatches an event * @method trigger * * @param {String} type The type of event to dispatch * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ /** * Dispactches an event with additional parameters * @method trigger * * @param {String} type The type of event to dispatch * @param {Object} params Additional data points to add to the event * @return {Lavaca.events.EventDispatcher} This event dispatcher (for chaining) */ trigger: function(type, params) { if (!this.suppressEvents && this.callbacks) { var list = this.callbacks[type], event = this.createEvent(type, params), i = -1, handler; if (list) { while (!!(handler = list[++i])) { handler.fn.apply(handler.thisp || this, [event]); } } } return this; }, /** * Creates an event object * @method createEvent * * @param {String} type The type of event to create * @return {Object} The event object */ /** * Creates an event object with additional params * @method createEvent * * @param {String} type The type of event to create * @param {Object} params Additional data points to add to the event * @return {Object} The event object */ createEvent: function(type, params) { return deepMixIn({}, params || {}, { type: type, target: params && params.target ? params.target : this, currentTarget: this }); } }); return EventDispatcher; }); define('lavaca/fx/Transform',['require','$'],function(require) { var $ = require('$'); var _props = { transform: 'transform', webkitTransform: '-webkit-transform', MozTransform: '-moz-transform', OTransform: '-o-transform', MSTransform: '-ms-transform' }, _prop, _cssProp, _3d = false, UNDEFINED; var Transform = {}; (function() { var style = document.createElement('div').style, s; for (s in _props) { if (s in style) { _prop = s; _cssProp = _props[s]; style[s] = 'translate3d(0,0,0)'; _3d = style[s].indexOf('translate3d') > -1 && navigator.userAgent.indexOf('Android') === -1; break; } } })(); function _isUndefined(value) { return value === UNDEFINED; } function _toOriginUnit(v) { return typeof v === 'number' ? v * 100 + '%' : v; } function _scrubRotateValue(v) { return typeof v === 'number' ? v + 'deg' : v; } function _scrubTranslateValue(v) { return typeof v === 'number' ? v + 'px' : v; } function _scrubScaleValue(v) { return typeof v === 'number' ? v + ',' + v : v; } function _scrubTransformValue(prop, value) { var isRotate = prop.indexOf('rotate') === 0, isScale = prop === 'scale', isTranslate = prop.indexOf('translate') === 0, //isAxisSpecific = /(X|Y|Z)$/.test(prop), p, css = []; if (typeof value === 'object') { for (p in value) { css.push(prop + p.toUpperCase() + '(' + (isTranslate ? _scrubTranslateValue(value[p]) : isRotate ? _scrubRotateValue(value[p]) : isScale ? _scrubScaleValue(value[p]) : value[p]) + ')'); } } else { if (isScale) { value = _scrubScaleValue(value); } else if (isRotate) { value = _scrubRotateValue(value); } else if (isTranslate) { value = _scrubTranslateValue(value); } css.push(prop + '(' + value + ')'); } return css.join(' '); } /** * Static utility type for working with CSS transforms * @class lavaca.fx.Transform */ /** * Whether or not transforms are supported by the browser * @method isSupported * @static * * @return {Boolean} True when transforms are supported */ Transform.isSupported = function() { return !!_prop; }; /** * Whether or not 3D transforms are supported by the browser * @method is3dSupported * @static * * @return {Boolean} True when 3D transforms are supported */ Transform.is3dSupported = function() { return _3d; }; /** * Converts a transform hash into a CSS string * @method toCSS * @static * * @param {Object} opts A hash of CSS transform values, with properties in * the form {translateX: 1, translateY: 1} or {translate: {x: 1, y: 1}} * @opt {Object} translate An object or string containing the translation values * @opt {Object} translateX A string (in any unit) or number (in pixels) representing the X translation value * @opt {Object} translateY A string (in any unit) or number (in pixels) representing the Y translation value * @opt {Object} translateZ A string (in any unit) or number (in pixels) representing the Z translation value * @opt {String} translate3d A string containing the 3D translation values * @opt {Object} rotate An object, string, or number (in degrees) containing the rotation value(s) * @opt {Object} rotateX A string (in any unit) or number (in degrees) representing the X rotation value * @opt {Object} rotateY A string (in any unit) or number (in degrees) representing the Y rotation value * @opt {Object} rotateZ A string (in any unit) or number (in degrees) representing the Z rotation value * @opt {String} rotate3d A string containing the 3D rotation values * @opt {Object} scale An object, string or number (in percentage points) containing the scale value(s) * @opt {Object} scaleX A string (in any unit) or number (in percentage points) representing the X scale value * @opt {Object} scaleY A string (in any unit) or number (in percentage points) representing the Y scale value * @opt {Object} scaleZ A string (in any unit) or number (in percentage points) representing the Z scale value * @opt {String} scale3d Astring containing the 3D scale values * @opt {Object} skew An object or string containing the skew values * @opt {Object} skewX A string (in any unit) or number (in pixels) representing the X skew value * @opt {Object} skewY A string (in any unit) or number (in pixels) representing the Y skew value * @opt {String} matrix A string containing the matrix transform values * @opt {String} matrix3d A string containing the 3D matrix transform values * @opt {String} perspective A string containing the perspective transform values * @return {String} The generated CSS string */ Transform.toCSS = function(opts) { var css = [], prop; if (typeof opts === 'object') { for (prop in opts) { css.push(_scrubTransformValue(prop, opts[prop])); } } else { css.push(opts); } return css.join(' '); }; /** * Gets the name of the transform CSS property * @method cssProperty * @static * * @return {String} The name of the CSS property */ Transform.cssProperty = function() { return _cssProp; }; /** * Transforms an element * @method $.fn.transform * * @param {String} value The CSS transform string * @return {jQuery} The jQuery object, for chaining */ /** * Transforms an element * @method $.fn.transform * * @param {Object} opt A hash of CSS transform values, with properties in * the form {translateX: 1, translateY: 1} or {translate: {x: 1, y: 1}} * @opt {Object} translate An object or string containing the translation values * @opt {Object} translateX A string (in any unit) or number (in pixels) representing the X translation value * @opt {Object} translateY A string (in any unit) or number (in pixels) representing the Y translation value * @opt {Object} translateZ A string (in any unit) or number (in pixels) representing the Z translation value * @opt {String} translate3d A string containing the 3D translation values * @opt {Object} rotate An object, string, or number (in degrees) containing the rotation value(s) * @opt {Object} rotateX A string (in any unit) or number (in degrees) representing the X rotation value * @opt {Object} rotateY A string (in any unit) or number (in degrees) representing the Y rotation value * @opt {Object} rotateZ A string (in any unit) or number (in degrees) representing the Z rotation value * @opt {String} rotate3d A string containing the 3D rotation values * @opt {Object} scale An object, string or number (in percentage points) containing the scale value(s) * @opt {Object} scaleX A string (in any unit) or number (in percentage points) representing the X scale value * @opt {Object} scaleY A string (in any unit) or number (in percentage points) representing the Y scale value * @opt {Object} scaleZ A string (in any unit) or number (in percentage points) representing the Z scale value * @opt {String} scale3d Astring containing the 3D scale values * @opt {Object} skew An object or string containing the skew values * @opt {Object} skewX A string (in any unit) or number (in pixels) representing the X skew value * @opt {Object} skewY A string (in any unit) or number (in pixels) representing the Y skew value * @opt {String} matrix A string containing the matrix transform values * @opt {String} matrix3d A string containing the 3D matrix transform values * @opt {String} perspective A string containing the perspective transform values * @return {jQuery} The jQuery object, for chaining */ /** * Transforms an element * @method $.fn.transform * * @param {String} value The CSS transform string * @param {String} origin The CSS transform origin * @return {jQuery} The jQuery object, for chaining */ /** * Transforms an element * @method $.fn.transform * * @param {Object} opt A hash of CSS transform values, with properties in * the form {translateX: 1, translateY: 1} or {translate: {x: 1, y: 1}} * @opt {Object} translate An object or string containing the translation values * @opt {Object} translateX A string (in any unit) or number (in pixels) representing the X translation value * @opt {Object} translateY A string (in any unit) or number (in pixels) representing the Y translation value * @opt {Object} translateZ A string (in any unit) or number (in pixels) representing the Z translation value * @opt {String} translate3d A string containing the 3D translation values * @opt {Object} rotate An object, string, or number (in degrees) containing the rotation value(s) * @opt {Object} rotateX A string (in any unit) or number (in degrees) representing the X rotation value * @opt {Object} rotateY A string (in any unit) or number (in degrees) representing the Y rotation value * @opt {Object} rotateZ A string (in any unit) or number (in degrees) representing the Z rotation value * @opt {String} rotate3d A string containing the 3D rotation values * @opt {Object} scale An object, string or number (in percentage points) containing the scale value(s) * @opt {Object} scaleX A string (in any unit) or number (in percentage points) representing the X scale value * @opt {Object} scaleY A string (in any unit) or number (in percentage points) representing the Y scale value * @opt {Object} scaleZ A string (in any unit) or number (in percentage points) representing the Z scale value * @opt {String} scale3d Astring containing the 3D scale values * @opt {Object} skew An object or string containing the skew values * @opt {Object} skewX A string (in any unit) or number (in pixels) representing the X skew value * @opt {Object} skewY A string (in any unit) or number (in pixels) representing the Y skew value * @opt {String} matrix A string containing the matrix transform values * @opt {String} matrix3d A string containing the 3D matrix transform values * @opt {String} perspective A string containing the perspective transform values * @param {String} origin The CSS transform origin * @return {jQuery} The jQuery object, for chaining */ /** * Transforms an element * @method $.fn.transform * * @param {String} value The CSS transform string * @param {Object} origin The CSS transform origin, in the form {x: N, y: N}, * where N is a decimal percentage between -1 and 1 or N is a pixel value > 1 or < -1. * @return {jQuery} The jQuery object, for chaining */ /** * Transforms an element * @method $.fn.transform * * @param {Object} opt A hash of CSS transform values, with properties in * the form {translateX: 1, translateY: 1} or {translate: {x: 1, y: 1}} * @opt {Object} translate An object or string containing the translation values * @opt {Object} translateX A string (in any unit) or number (in pixels) representing the X translation value * @opt {Object} translateY A string (in any unit) or number (in pixels) representing the Y translation value * @opt {Object} translateZ A string (in any unit) or number (in pixels) representing the Z translation value * @opt {String} translate3d A string containing the 3D translation values * @opt {Object} rotate An object, string, or number (in degrees) containing the rotation value(s) * @opt {Object} rotateX A string (in any unit) or number (in degrees) representing the X rotation value * @opt {Object} rotateY A string (in any unit) or number (in degrees) representing the Y rotation value * @opt {Object} rotateZ A string (in any unit) or number (in degrees) representing the Z rotation value * @opt {String} rotate3d A string containing the 3D rotation values * @opt {Object} scale An object, string or number (in percentage points) containing the scale value(s) * @opt {Object} scaleX A string (in any unit) or number (in percentage points) representing the X scale value * @opt {Object} scaleY A string (in any unit) or number (in percentage points) representing the Y scale value * @opt {Object} scaleZ A string (in any unit) or number (in percentage points) representing the Z scale value * @opt {String} scale3d Astring containing the 3D scale values * @opt {Object} skew An object or string containing the skew values * @opt {Object} skewX A string (in any unit) or number (in pixels) representing the X skew value * @opt {Object} skewY A string (in any unit) or number (in pixels) representing the Y skew value * @opt {String} matrix A string containing the matrix transform values * @opt {String} matrix3d A string containing the 3D matrix transform values * @opt {String} perspective A string containing the perspective transform values * @param {Object} origin The CSS transform origin, in the form {x: N, y: N}, * where N is a decimal percentage between -1 and 1 or N is a pixel value > 1 or < -1. * @return {jQuery} The jQuery object, for chaining */ $.fn.transform = function(value, origin) { if (Transform.isSupported()) { value = Transform.toCSS(value); if (origin) { if (typeof origin === 'object') { origin = _toOriginUnit(origin.x) + (_isUndefined(origin.y) ? '' : ' ' + _toOriginUnit(origin.y)); } } this.each(function() { this.style[_prop] = value; if (origin) { this.style[_prop + 'Origin'] = origin; } }); } return this; }; return Transform; }); define('lavaca/fx/Animation',['require','$','./Transform'],function(require) { var $ = require('$'), Transform = require('./Transform'); var Animation = {}; var _props = { animation: ['animation', 'animationend', 'keyframes'], webkitAnimation: ['-webkit-animation', 'webkitAnimationEnd', '-webkit-keyframes'], MozAnimation: ['-moz-animation', 'animationend', '-moz-keyframes'], OAnimation: ['-o-animation', 'oAnimationEnd', '-o-keyframes'], MSAnimation: ['-ms-animation', 'MSAnimationEnd', '-ms-keyframes'] }, _prop, _cssProp, _declaration, _event; (function() { var style = document.createElement('div').style, s, opts; for (s in _props) { if (s in style) { opts = _props[s]; _prop = s; _cssProp = opts[0]; _event = opts[1]; _declaration = opts[2]; break; } } })(); /** * Static utility type for working with CSS keyframe animations * @class lavaca.fx.Animation */ /** * Whether or not animations are supported by the browser * @method isSupported * @static * * @return {Boolean} True if CSS keyframe animations are supported */ Animation.isSupported = function() { return !!_prop; }; /** * Converts a list of keyframes to a CSS animation * @method keyframesToCSS * @static * * @param {String} name The name of the keyframe animation * @param {Object} keyframes A list of timestamped keyframes in the form {'0%': {color: 'red'}, '100%': 'color: blue'} * @return {String} The CSS keyframe animation declaration */ Animation.keyframesToCSS = function(name, keyframes) { var css = ['@', _declaration, ' ', name, '{'], time, keyframe, prop, value; for (time in keyframes) { css.push(time, '{'); keyframe = keyframes[time]; if (typeof keyframe === 'string') { css.push(keyframe); } else { for (prop in keyframe) { value = keyframe[prop]; if (prop === 'transform' && Transform) { prop = Transform.cssProperty(); value = Transform.toCSS(value); } css.push(prop, ':', value, ';'); } } css.push('}'); } css.push('}'); return css.join(''); }; /** * Generates a keyframe animation * @