A piano to hack on while going to/from work.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1112 lines
41 KiB

/*! Flight v1.1.4 | (c) Twitter, Inc. | MIT License */
(function(context) {
var factories = {}, loaded = {};
var isArray = Array.isArray || function(obj) {
return obj.constructor == Array;
};
var map = Array.map || function(arr, fn, scope) {
for (var i = 0, len = arr.length, result = []; i < len; i++) {
result.push(fn.call(scope, arr[i]));
}
return result;
};
function define() {
var args = Array.prototype.slice.call(arguments), dependencies = [], id, factory;
if (typeof args[0] == 'string') {
id = args.shift();
}
if (isArray(args[0])) {
dependencies = args.shift();
}
factory = args.shift();
factories[id] = [dependencies, factory];
}
function require(id) {
function resolve(dep) {
var relativeParts = id.split('/'), depParts = dep.split('/'), relative = false;
relativeParts.pop();
while (depParts[0] == '..' && relativeParts.length) {
relativeParts.pop();
depParts.shift();
relative = true;
}
if (depParts[0] == '.') {
depParts.shift();
relative = true;
}
if (relative) {
depParts = relativeParts.concat(depParts);
}
return depParts.join('/');
}
var unresolved, factory, dependencies;
if (typeof loaded[id] == 'undefined') {
unresolved = factories[id];
if (unresolved) {
dependencies = unresolved[0];
factory = unresolved[1];
loaded[id] = factory.apply(undefined, map(dependencies, function(id) {
return require(resolve(id));
}));
}
}
return loaded[id];
}
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define('lib/utils', [], function () {
'use strict';
var arry = [];
var DEFAULT_INTERVAL = 100;
var utils = {
isDomObj: function (obj) {
return !!(obj.nodeType || obj === window);
},
toArray: function (obj, from) {
return arry.slice.call(obj, from);
},
merge: function () {
// unpacking arguments by hand benchmarked faster
var l = arguments.length, i = 0, args = new Array(l + 1);
for (; i < l; i++)
args[i + 1] = arguments[i];
if (l === 0) {
return {};
}
//start with empty object so a copy is created
args[0] = {};
if (args[args.length - 1] === true) {
//jquery extend requires deep copy as first arg
args.pop();
args.unshift(true);
}
return $.extend.apply(undefined, args);
},
push: function (base, extra, protect) {
if (base) {
Object.keys(extra || {}).forEach(function (key) {
if (base[key] && protect) {
throw new Error('utils.push attempted to overwrite "' + key + '" while running in protected mode');
}
if (typeof base[key] == 'object' && typeof extra[key] == 'object') {
// recurse
this.push(base[key], extra[key]);
} else {
// no protect, so extra wins
base[key] = extra[key];
}
}, this);
}
return base;
},
isEnumerable: function (obj, property) {
return Object.keys(obj).indexOf(property) > -1;
},
compose: function () {
var funcs = arguments;
return function () {
var args = arguments;
for (var i = funcs.length - 1; i >= 0; i--) {
args = [funcs[i].apply(this, args)];
}
return args[0];
};
},
uniqueArray: function (array) {
var u = {}, a = [];
for (var i = 0, l = array.length; i < l; ++i) {
if (u.hasOwnProperty(array[i])) {
continue;
}
a.push(array[i]);
u[array[i]] = 1;
}
return a;
},
debounce: function (func, wait, immediate) {
if (typeof wait != 'number') {
wait = DEFAULT_INTERVAL;
}
var timeout, result;
return function () {
var context = this, args = arguments;
var later = function () {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
}
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
}
return result;
};
},
throttle: function (func, wait) {
if (typeof wait != 'number') {
wait = DEFAULT_INTERVAL;
}
var context, args, timeout, throttling, more, result;
var whenDone = this.debounce(function () {
more = throttling = false;
}, wait);
return function () {
context = this;
args = arguments;
var later = function () {
timeout = null;
if (more) {
result = func.apply(context, args);
}
whenDone();
};
if (!timeout) {
timeout = setTimeout(later, wait);
}
if (throttling) {
more = true;
} else {
throttling = true;
result = func.apply(context, args);
}
whenDone();
return result;
};
},
countThen: function (num, base) {
return function () {
if (!--num) {
return base.apply(this, arguments);
}
};
},
delegate: function (rules) {
return function (e, data) {
var target = $(e.target), parent;
Object.keys(rules).forEach(function (selector) {
if (!e.isPropagationStopped() && (parent = target.closest(selector)).length) {
data = data || {};
data.el = parent[0];
return rules[selector].apply(this, [
e,
data
]);
}
}, this);
};
},
once: function (func) {
var ran, result;
return function () {
if (ran) {
return result;
}
ran = true;
result = func.apply(this, arguments);
return result;
};
}
};
return utils;
});
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define('lib/debug', [], function () {
'use strict';
// ==========================================
// Search object model
// ==========================================
function traverse(util, searchTerm, options) {
options = options || {};
var obj = options.obj || window;
var path = options.path || (obj == window ? 'window' : '');
var props = Object.keys(obj);
props.forEach(function (prop) {
if ((tests[util] || util)(searchTerm, obj, prop)) {
console.log([
path,
'.',
prop
].join(''), '->', [
'(',
typeof obj[prop],
')'
].join(''), obj[prop]);
}
if (Object.prototype.toString.call(obj[prop]) == '[object Object]' && obj[prop] != obj && path.split('.').indexOf(prop) == -1) {
traverse(util, searchTerm, {
obj: obj[prop],
path: [
path,
prop
].join('.')
});
}
});
}
function search(util, expected, searchTerm, options) {
if (!expected || typeof searchTerm == expected) {
traverse(util, searchTerm, options);
} else {
console.error([
searchTerm,
'must be',
expected
].join(' '));
}
}
var tests = {
'name': function (searchTerm, obj, prop) {
return searchTerm == prop;
},
'nameContains': function (searchTerm, obj, prop) {
return prop.indexOf(searchTerm) > -1;
},
'type': function (searchTerm, obj, prop) {
return obj[prop] instanceof searchTerm;
},
'value': function (searchTerm, obj, prop) {
return obj[prop] === searchTerm;
},
'valueCoerced': function (searchTerm, obj, prop) {
return obj[prop] == searchTerm;
}
};
function byName(searchTerm, options) {
search('name', 'string', searchTerm, options);
}
function byNameContains(searchTerm, options) {
search('nameContains', 'string', searchTerm, options);
}
function byType(searchTerm, options) {
search('type', 'function', searchTerm, options);
}
function byValue(searchTerm, options) {
search('value', null, searchTerm, options);
}
function byValueCoerced(searchTerm, options) {
search('valueCoerced', null, searchTerm, options);
}
function custom(fn, options) {
traverse(fn, null, options);
}
// ==========================================
// Event logging
// ==========================================
var ALL = 'all';
//no filter
//log nothing by default
var logFilter = {
eventNames: [],
actions: []
};
function filterEventLogsByAction() {
var actions = [].slice.call(arguments);
logFilter.eventNames.length || (logFilter.eventNames = ALL);
logFilter.actions = actions.length ? actions : ALL;
saveLogFilter();
}
function filterEventLogsByName() {
var eventNames = [].slice.call(arguments);
logFilter.actions.length || (logFilter.actions = ALL);
logFilter.eventNames = eventNames.length ? eventNames : ALL;
saveLogFilter();
}
function hideAllEventLogs() {
logFilter.actions = [];
logFilter.eventNames = [];
saveLogFilter();
}
function showAllEventLogs() {
logFilter.actions = ALL;
logFilter.eventNames = ALL;
saveLogFilter();
}
function saveLogFilter() {
try {
if (window.localStorage) {
localStorage.setItem('logFilter_eventNames', logFilter.eventNames);
localStorage.setItem('logFilter_actions', logFilter.actions);
}
} catch (ignored) {
}
;
}
function retrieveLogFilter() {
var eventNames, actions;
try {
eventNames = window.localStorage && localStorage.getItem('logFilter_eventNames');
actions = window.localStorage && localStorage.getItem('logFilter_actions');
} catch (ignored) {
return;
}
eventNames && (logFilter.eventNames = eventNames);
actions && (logFilter.actions = actions);
// reconstitute arrays in place
Object.keys(logFilter).forEach(function (k) {
var thisProp = logFilter[k];
if (typeof thisProp == 'string' && thisProp !== ALL) {
logFilter[k] = thisProp ? thisProp.split(',') : [];
}
});
}
return {
enable: function (enable) {
this.enabled = !!enable;
if (enable && window.console) {
console.info('Booting in DEBUG mode');
console.info('You can configure event logging with DEBUG.events.logAll()/logNone()/logByName()/logByAction()');
}
retrieveLogFilter();
window.DEBUG = this;
},
find: {
byName: byName,
byNameContains: byNameContains,
byType: byType,
byValue: byValue,
byValueCoerced: byValueCoerced,
custom: custom
},
events: {
logFilter: logFilter,
logByAction: filterEventLogsByAction,
logByName: filterEventLogsByName,
logAll: showAllEventLogs,
logNone: hideAllEventLogs
}
};
});
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define('lib/compose', [
'./utils',
'./debug'
], function (utils, debug) {
'use strict';
//enumerables are shims - getOwnPropertyDescriptor shim doesn't work
var canWriteProtect = debug.enabled && !utils.isEnumerable(Object, 'getOwnPropertyDescriptor');
//whitelist of unlockable property names
var dontLock = ['mixedIn'];
if (canWriteProtect) {
//IE8 getOwnPropertyDescriptor is built-in but throws exeption on non DOM objects
try {
Object.getOwnPropertyDescriptor(Object, 'keys');
} catch (e) {
canWriteProtect = false;
}
}
function setPropertyWritability(obj, isWritable) {
if (!canWriteProtect) {
return;
}
var props = Object.create(null);
Object.keys(obj).forEach(function (key) {
if (dontLock.indexOf(key) < 0) {
var desc = Object.getOwnPropertyDescriptor(obj, key);
desc.writable = isWritable;
props[key] = desc;
}
});
Object.defineProperties(obj, props);
}
function unlockProperty(obj, prop, op) {
var writable;
if (!canWriteProtect || !obj.hasOwnProperty(prop)) {
op.call(obj);
return;
}
writable = Object.getOwnPropertyDescriptor(obj, prop).writable;
Object.defineProperty(obj, prop, { writable: true });
op.call(obj);
Object.defineProperty(obj, prop, { writable: writable });
}
function mixin(base, mixins) {
base.mixedIn = base.hasOwnProperty('mixedIn') ? base.mixedIn : [];
for (var i = 0; i < mixins.length; i++) {
if (base.mixedIn.indexOf(mixins[i]) == -1) {
setPropertyWritability(base, false);
mixins[i].call(base);
base.mixedIn.push(mixins[i]);
}
}
setPropertyWritability(base, true);
}
return {
mixin: mixin,
unlockProperty: unlockProperty
};
});
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define('lib/advice', ['./compose'], function (compose) {
'use strict';
var advice = {
around: function (base, wrapped) {
return function composedAround() {
// unpacking arguments by hand benchmarked faster
var i = 0, l = arguments.length, args = new Array(l + 1);
args[0] = base.bind(this);
for (; i < l; i++)
args[i + 1] = arguments[i];
return wrapped.apply(this, args);
};
},
before: function (base, before) {
var beforeFn = typeof before == 'function' ? before : before.obj[before.fnName];
return function composedBefore() {
beforeFn.apply(this, arguments);
return base.apply(this, arguments);
};
},
after: function (base, after) {
var afterFn = typeof after == 'function' ? after : after.obj[after.fnName];
return function composedAfter() {
var res = (base.unbound || base).apply(this, arguments);
afterFn.apply(this, arguments);
return res;
};
},
withAdvice: function () {
[
'before',
'after',
'around'
].forEach(function (m) {
this[m] = function (method, fn) {
compose.unlockProperty(this, method, function () {
if (typeof this[method] == 'function') {
this[method] = advice[m](this[method], fn);
} else {
this[method] = fn;
}
return this[method];
});
};
}, this);
}
};
return advice;
});
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define('lib/registry', [], function () {
'use strict';
function parseEventArgs(instance, args) {
var element, type, callback;
var end = args.length;
if (typeof args[end - 1] === 'function') {
end -= 1;
callback = args[end];
}
if (typeof args[end - 1] === 'object') {
end -= 1;
}
if (end == 2) {
element = args[0];
type = args[1];
} else {
element = instance.node;
type = args[0];
}
return {
element: element,
type: type,
callback: callback
};
}
function matchEvent(a, b) {
return a.element == b.element && a.type == b.type && (b.callback == null || a.callback == b.callback);
}
function Registry() {
var registry = this;
(this.reset = function () {
this.components = [];
this.allInstances = {};
this.events = [];
}).call(this);
function ComponentInfo(component) {
this.component = component;
this.attachedTo = [];
this.instances = {};
this.addInstance = function (instance) {
var instanceInfo = new InstanceInfo(instance);
this.instances[instance.identity] = instanceInfo;
this.attachedTo.push(instance.node);
return instanceInfo;
};
this.removeInstance = function (instance) {
delete this.instances[instance.identity];
var indexOfNode = this.attachedTo.indexOf(instance.node);
indexOfNode > -1 && this.attachedTo.splice(indexOfNode, 1);
if (!Object.keys(this.instances).length) {
//if I hold no more instances remove me from registry
registry.removeComponentInfo(this);
}
};
this.isAttachedTo = function (node) {
return this.attachedTo.indexOf(node) > -1;
};
}
function InstanceInfo(instance) {
this.instance = instance;
this.events = [];
this.addBind = function (event) {
this.events.push(event);
registry.events.push(event);
};
this.removeBind = function (event) {
for (var i = 0, e; e = this.events[i]; i++) {
if (matchEvent(e, event)) {
this.events.splice(i, 1);
}
}
};
}
this.addInstance = function (instance) {
var component = this.findComponentInfo(instance);
if (!component) {
component = new ComponentInfo(instance.constructor);
this.components.push(component);
}
var inst = component.addInstance(instance);
this.allInstances[instance.identity] = inst;
return component;
};
this.removeInstance = function (instance) {
var index, instInfo = this.findInstanceInfo(instance);
//remove from component info
var componentInfo = this.findComponentInfo(instance);
componentInfo && componentInfo.removeInstance(instance);
//remove from registry
delete this.allInstances[instance.identity];
};
this.removeComponentInfo = function (componentInfo) {
var index = this.components.indexOf(componentInfo);
index > -1 && this.components.splice(index, 1);
};
this.findComponentInfo = function (which) {
var component = which.attachTo ? which : which.constructor;
for (var i = 0, c; c = this.components[i]; i++) {
if (c.component === component) {
return c;
}
}
return null;
};
this.findInstanceInfo = function (instance) {
return this.allInstances[instance.identity] || null;
};
this.getBoundEventNames = function (instance) {
return this.findInstanceInfo(instance).events.map(function (ev) {
return ev.type;
});
};
this.findInstanceInfoByNode = function (node) {
var result = [];
Object.keys(this.allInstances).forEach(function (k) {
var thisInstanceInfo = this.allInstances[k];
if (thisInstanceInfo.instance.node === node) {
result.push(thisInstanceInfo);
}
}, this);
return result;
};
this.on = function (componentOn) {
var instance = registry.findInstanceInfo(this), boundCallback;
// unpacking arguments by hand benchmarked faster
var l = arguments.length, i = 1;
var otherArgs = new Array(l - 1);
for (; i < l; i++)
otherArgs[i - 1] = arguments[i];
if (instance) {
boundCallback = componentOn.apply(null, otherArgs);
if (boundCallback) {
otherArgs[otherArgs.length - 1] = boundCallback;
}
var event = parseEventArgs(this, otherArgs);
instance.addBind(event);
}
};
this.off = function () {
var event = parseEventArgs(this, arguments), instance = registry.findInstanceInfo(this);
if (instance) {
instance.removeBind(event);
}
//remove from global event registry
for (var i = 0, e; e = registry.events[i]; i++) {
if (matchEvent(e, event)) {
registry.events.splice(i, 1);
}
}
};
// debug tools may want to add advice to trigger
registry.trigger = function () {
};
this.teardown = function () {
registry.removeInstance(this);
};
this.withRegistration = function () {
this.after('initialize', function () {
registry.addInstance(this);
});
this.around('on', registry.on);
this.after('off', registry.off);
//debug tools may want to add advice to trigger
window.DEBUG && DEBUG.enabled && this.after('trigger', registry.trigger);
this.after('teardown', {
obj: registry,
fnName: 'teardown'
});
};
}
return new Registry();
});
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define('lib/base', [
'./utils',
'./registry',
'./debug'
], function (utils, registry, debug) {
'use strict';
// common mixin allocates basic functionality - used by all component prototypes
// callback context is bound to component
var componentId = 0;
function teardownInstance(instanceInfo) {
instanceInfo.events.slice().forEach(function (event) {
var args = [event.type];
event.element && args.unshift(event.element);
typeof event.callback == 'function' && args.push(event.callback);
this.off.apply(this, args);
}, instanceInfo.instance);
}
function checkSerializable(type, data) {
try {
window.postMessage(data, '*');
} catch (e) {
console.log('unserializable data for event', type, ':', data);
throw new Error([
'The event',
type,
'on component',
this.toString(),
'was triggered with non-serializable data'
].join(' '));
}
}
function proxyEventTo(targetEvent) {
return function (e, data) {
$(e.target).trigger(targetEvent, data);
};
}
function withBase() {
// delegate trigger, bind and unbind to an element
// if $element not supplied, use component's node
// other arguments are passed on
// event can be either a string specifying the type
// of the event, or a hash specifying both the type
// and a default function to be called.
this.trigger = function () {
var $element, type, data, event, defaultFn;
var lastIndex = arguments.length - 1, lastArg = arguments[lastIndex];
if (typeof lastArg != 'string' && !(lastArg && lastArg.defaultBehavior)) {
lastIndex--;
data = lastArg;
}
if (lastIndex == 1) {
$element = $(arguments[0]);
event = arguments[1];
} else {
$element = this.$node;
event = arguments[0];
}
if (event.defaultBehavior) {
defaultFn = event.defaultBehavior;
event = $.Event(event.type);
}
type = event.type || event;
if (debug.enabled && window.postMessage) {
checkSerializable.call(this, type, data);
}
if (typeof this.attr.eventData === 'object') {
data = $.extend(true, {}, this.attr.eventData, data);
}
$element.trigger(event || type, data);
if (defaultFn && !event.isDefaultPrevented()) {
(this[defaultFn] || defaultFn).call(this);
}
return $element;
};
this.on = function () {
var $element, type, callback, originalCb;
var lastIndex = arguments.length - 1, origin = arguments[lastIndex];
if (typeof origin == 'object') {
//delegate callback
originalCb = utils.delegate(this.resolveDelegateRules(origin));
} else if (typeof origin == 'string') {
originalCb = proxyEventTo(origin);
} else {
originalCb = origin;
}
if (lastIndex == 2) {
$element = $(arguments[0]);
type = arguments[1];
} else {
$element = this.$node;
type = arguments[0];
}
if (typeof originalCb != 'function' && typeof originalCb != 'object') {
throw new Error('Unable to bind to "' + type + '" because the given callback is not a function or an object');
}
callback = originalCb.bind(this);
callback.target = originalCb;
callback.context = this;
$element.on(type, callback);
// store every bound version of the callback
originalCb.bound || (originalCb.bound = []);
originalCb.bound.push(callback);
return callback;
};
this.off = function () {
var $element, type, callback;
var lastIndex = arguments.length - 1;
if (typeof arguments[lastIndex] == 'function') {
callback = arguments[lastIndex];
lastIndex -= 1;
}
if (lastIndex == 1) {
$element = $(arguments[0]);
type = arguments[1];
} else {
$element = this.$node;
type = arguments[0];
}
if (callback) {
//this callback may be the original function or a bound version
var boundFunctions = callback.target ? callback.target.bound : callback.bound || [];
//set callback to version bound against this instance
boundFunctions && boundFunctions.some(function (fn, i, arr) {
if (fn.context && this.identity == fn.context.identity) {
arr.splice(i, 1);
callback = fn;
return true;
}
}, this);
}
return $element.off(type, callback);
};
this.resolveDelegateRules = function (ruleInfo) {
var rules = {};
Object.keys(ruleInfo).forEach(function (r) {
if (!(r in this.attr)) {
throw new Error('Component "' + this.toString() + '" wants to listen on "' + r + '" but no such attribute was defined.');
}
rules[this.attr[r]] = typeof ruleInfo[r] == 'string' ? proxyEventTo(ruleInfo[r]) : ruleInfo[r];
}, this);
return rules;
};
this.defaultAttrs = function (defaults) {
utils.push(this.defaults, defaults, true) || (this.defaults = defaults);
};
this.select = function (attributeKey) {
return this.$node.find(this.attr[attributeKey]);
};
this.initialize = function (node, attrs) {
attrs || (attrs = {});
//only assign identity if there isn't one (initialize can be called multiple times)
this.identity || (this.identity = componentId++);
if (!node) {
throw new Error('Component needs a node');
}
if (node.jquery) {
this.node = node[0];
this.$node = node;
} else {
this.node = node;
this.$node = $(node);
}
// merge defaults with supplied options
// put options in attr.__proto__ to avoid merge overhead
var attr = Object.create(attrs);
for (var key in this.defaults) {
if (!attrs.hasOwnProperty(key)) {
attr[key] = this.defaults[key];
}
}
this.attr = attr;
Object.keys(this.defaults || {}).forEach(function (key) {
if (this.defaults[key] === null && this.attr[key] === null) {
throw new Error('Required attribute "' + key + '" not specified in attachTo for component "' + this.toString() + '".');
}
}, this);
return this;
};
this.teardown = function () {
teardownInstance(registry.findInstanceInfo(this));
};
}
return withBase;
});
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define('lib/logger', ['./utils'], function (utils) {
'use strict';
var actionSymbols = {
on: '<-',
trigger: '->',
off: 'x '
};
function elemToString(elem) {
var tagStr = elem.tagName ? elem.tagName.toLowerCase() : elem.toString();
var classStr = elem.className ? '.' + elem.className : '';
var result = tagStr + classStr;
return elem.tagName ? [
'\'',
'\''
].join(result) : result;
}
function log(action, component, eventArgs) {
if (!window.DEBUG || !window.DEBUG.enabled)
return;
var name, eventType, elem, fn, payload, logFilter, toRegExp, actionLoggable, nameLoggable, info;
if (typeof eventArgs[eventArgs.length - 1] == 'function') {
fn = eventArgs.pop();
fn = fn.unbound || fn; // use unbound version if any (better info)
}
if (eventArgs.length == 1) {
elem = component.$node[0];
eventType = eventArgs[0];
} else if (eventArgs.length == 2 && typeof eventArgs[1] == 'object' && !eventArgs[1].type) {
//2 args, first arg is not elem
elem = component.$node[0];
eventType = eventArgs[0];
if (action == 'trigger') {
payload = eventArgs[1];
}
} else {
//2+ args, first arg is elem
elem = eventArgs[0];
eventType = eventArgs[1];
if (action == 'trigger') {
payload = eventArgs[2];
}
}
name = typeof eventType == 'object' ? eventType.type : eventType;
logFilter = DEBUG.events.logFilter;
// no regex for you, actions...
actionLoggable = logFilter.actions == 'all' || logFilter.actions.indexOf(action) > -1;
// event name filter allow wildcards or regex...
toRegExp = function (expr) {
return expr.test ? expr : new RegExp('^' + expr.replace(/\*/g, '.*') + '$');
};
nameLoggable = logFilter.eventNames == 'all' || logFilter.eventNames.some(function (e) {
return toRegExp(e).test(name);
});
if (actionLoggable && nameLoggable) {
info = [
actionSymbols[action],
action,
'[' + name + ']'
];
payload && info.push(payload);
info.push(elemToString(elem));
info.push(component.constructor.describe.split(' ').slice(0, 3).join(' '));
console.groupCollapsed && action == 'trigger' && console.groupCollapsed(action, name);
console.info.apply(console, info);
}
}
function withLogging() {
this.before('trigger', function () {
log('trigger', this, utils.toArray(arguments));
});
if (console.groupCollapsed) {
this.after('trigger', function () {
console.groupEnd();
});
}
this.before('on', function () {
log('on', this, utils.toArray(arguments));
});
this.before('off', function () {
log('off', this, utils.toArray(arguments));
});
}
return withLogging;
});
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define('lib/component', [
'./advice',
'./utils',
'./compose',
'./base',
'./registry',
'./logger',
'./debug'
], function (advice, utils, compose, withBase, registry, withLogging, debug) {
'use strict';
var functionNameRegEx = /function (.*?)\s?\(/;
// teardown for all instances of this constructor
function teardownAll() {
var componentInfo = registry.findComponentInfo(this);
componentInfo && Object.keys(componentInfo.instances).forEach(function (k) {
var info = componentInfo.instances[k];
// It's possible that a previous teardown caused another component to teardown,
// so we can't assume that the instances object is as it was.
if (info && info.instance) {
info.instance.teardown();
}
});
}
function checkSerializable(type, data) {
try {
window.postMessage(data, '*');
} catch (e) {
console.log('unserializable data for event', type, ':', data);
throw new Error([
'The event',
type,
'on component',
this.toString(),
'was triggered with non-serializable data'
].join(' '));
}
}
function attachTo(selector) {
// unpacking arguments by hand benchmarked faster
var l = arguments.length;
var args = new Array(l - 1);
for (var i = 1; i < l; i++)
args[i - 1] = arguments[i];
if (!selector) {
throw new Error('Component needs to be attachTo\'d a jQuery object, native node or selector string');
}
var options = utils.merge.apply(utils, args);
var componentInfo = registry.findComponentInfo(this);
$(selector).each(function (i, node) {
if (componentInfo && componentInfo.isAttachedTo(node)) {
// already attached
return;
}
new this().initialize(node, options);
}.bind(this));
}
function prettyPrintMixins() {
//could be called from constructor or constructor.prototype
var mixedIn = this.mixedIn || this.prototype.mixedIn || [];
return mixedIn.map(function (mixin) {
if (mixin.name == null) {
// function name property not supported by this browser, use regex
var m = mixin.toString().match(functionNameRegEx);
return m && m[1] ? m[1] : '';
} else {
return mixin.name != 'withBase' ? mixin.name : '';
}
}).filter(Boolean).join(', ');
}
;
// define the constructor for a custom component type
// takes an unlimited number of mixin functions as arguments
// typical api call with 3 mixins: define(timeline, withTweetCapability, withScrollCapability);
function define() {
// unpacking arguments by hand benchmarked faster
var l = arguments.length;
var mixins = new Array(l);
for (var i = 0; i < l; i++)
mixins[i] = arguments[i];
var Component = function () {
};
Component.toString = Component.prototype.toString = prettyPrintMixins;
if (debug.enabled) {
Component.describe = Component.prototype.describe = Component.toString();
}
// 'options' is optional hash to be merged with 'defaults' in the component definition
Component.attachTo = attachTo;
// enables extension of existing "base" Components
Component.mixin = function () {
var newComponent = define();
//TODO: fix pretty print
var newPrototype = Object.create(Component.prototype);
newPrototype.mixedIn = [].concat(Component.prototype.mixedIn);
compose.mixin(newPrototype, arguments);
newComponent.prototype = newPrototype;
newComponent.prototype.constructor = newComponent;
return newComponent;
};
Component.teardownAll = teardownAll;
// prepend common mixins to supplied list, then mixin all flavors
if (debug.enabled) {
mixins.unshift(withLogging);
}
mixins.unshift(withBase, advice.withAdvice, registry.withRegistration);
compose.mixin(Component.prototype, mixins);
return Component;
}
define.teardownAll = function () {
registry.components.slice().forEach(function (c) {
c.component.teardownAll();
});
registry.reset();
};
return define;
});
// ==========================================
// Copyright 2013 Twitter, Inc
// Licensed under The MIT License
// http://opensource.org/licenses/MIT
// ==========================================
define('lib/index', [
'./advice',
'./component',
'./compose',
'./logger',
'./registry',
'./utils'
], function (advice, component, compose, logger, registry, utils) {
'use strict';
return {
advice: advice,
component: component,
compose: compose,
logger: logger,
registry: registry,
utils: utils
};
});
context.flight = require('lib/index');
}(this));