277 lines
10 KiB
JavaScript
Executable File
277 lines
10 KiB
JavaScript
Executable File
/*
|
|
* This file contains shims for when Underscore and Backbone
|
|
* are not included.
|
|
*
|
|
* Portions taken from Underscore.js and Backbone.js
|
|
* Both of which are Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud
|
|
*/
|
|
window.Messenger._ = (function() {
|
|
if (window._)
|
|
return window._
|
|
|
|
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
|
|
|
// Create quick reference variables for speed access to core prototypes.
|
|
var push = ArrayProto.push,
|
|
slice = ArrayProto.slice,
|
|
concat = ArrayProto.concat,
|
|
toString = ObjProto.toString,
|
|
hasOwnProperty = ObjProto.hasOwnProperty;
|
|
|
|
// All **ECMAScript 5** native function implementations that we hope to use
|
|
// are declared here.
|
|
var
|
|
nativeForEach = ArrayProto.forEach,
|
|
nativeMap = ArrayProto.map,
|
|
nativeReduce = ArrayProto.reduce,
|
|
nativeReduceRight = ArrayProto.reduceRight,
|
|
nativeFilter = ArrayProto.filter,
|
|
nativeEvery = ArrayProto.every,
|
|
nativeSome = ArrayProto.some,
|
|
nativeIndexOf = ArrayProto.indexOf,
|
|
nativeLastIndexOf = ArrayProto.lastIndexOf,
|
|
nativeIsArray = Array.isArray,
|
|
nativeKeys = Object.keys,
|
|
nativeBind = FuncProto.bind;
|
|
|
|
// Create a safe reference to the Underscore object for use below.
|
|
var _ = {};
|
|
|
|
// Establish the object that gets returned to break out of a loop iteration.
|
|
var breaker = {};
|
|
|
|
var each = _.each = _.forEach = function(obj, iterator, context) {
|
|
if (obj == null) return;
|
|
if (nativeForEach && obj.forEach === nativeForEach) {
|
|
obj.forEach(iterator, context);
|
|
} else if (obj.length === +obj.length) {
|
|
for (var i = 0, l = obj.length; i < l; i++) {
|
|
if (iterator.call(context, obj[i], i, obj) === breaker) return;
|
|
}
|
|
} else {
|
|
for (var key in obj) {
|
|
if (_.has(obj, key)) {
|
|
if (iterator.call(context, obj[key], key, obj) === breaker) return;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
_.result = function(object, property) {
|
|
if (object == null) return null;
|
|
var value = object[property];
|
|
return _.isFunction(value) ? value.call(object) : value;
|
|
};
|
|
|
|
_.once = function(func) {
|
|
var ran = false, memo;
|
|
return function() {
|
|
if (ran) return memo;
|
|
ran = true;
|
|
memo = func.apply(this, arguments);
|
|
func = null;
|
|
return memo;
|
|
};
|
|
};
|
|
|
|
var idCounter = 0;
|
|
_.uniqueId = function(prefix) {
|
|
var id = ++idCounter + '';
|
|
return prefix ? prefix + id : id;
|
|
};
|
|
|
|
_.filter = _.select = function(obj, iterator, context) {
|
|
var results = [];
|
|
if (obj == null) return results;
|
|
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
|
each(obj, function(value, index, list) {
|
|
if (iterator.call(context, value, index, list)) results[results.length] = value;
|
|
});
|
|
return results;
|
|
};
|
|
|
|
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
|
|
each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
|
|
_['is' + name] = function(obj) {
|
|
return toString.call(obj) == '[object ' + name + ']';
|
|
};
|
|
});
|
|
|
|
_.defaults = function(obj) {
|
|
each(slice.call(arguments, 1), function(source) {
|
|
if (source) {
|
|
for (var prop in source) {
|
|
if (obj[prop] == null) obj[prop] = source[prop];
|
|
}
|
|
}
|
|
});
|
|
return obj;
|
|
};
|
|
|
|
_.extend = function(obj) {
|
|
each(slice.call(arguments, 1), function(source) {
|
|
if (source) {
|
|
for (var prop in source) {
|
|
obj[prop] = source[prop];
|
|
}
|
|
}
|
|
});
|
|
return obj;
|
|
};
|
|
|
|
_.keys = nativeKeys || function(obj) {
|
|
if (obj !== Object(obj)) throw new TypeError('Invalid object');
|
|
var keys = [];
|
|
for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
|
|
return keys;
|
|
};
|
|
|
|
_.bind = function(func, context) {
|
|
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
|
var args = slice.call(arguments, 2);
|
|
return function() {
|
|
return func.apply(context, args.concat(slice.call(arguments)));
|
|
};
|
|
};
|
|
|
|
_.isObject = function(obj) {
|
|
return obj === Object(obj);
|
|
};
|
|
|
|
return _;
|
|
})();
|
|
|
|
window.Messenger.Events = (function() {
|
|
if (window.Backbone && Backbone.Events) {
|
|
return Backbone.Events;
|
|
}
|
|
|
|
var eventsShim = function() {
|
|
var eventSplitter = /\s+/;
|
|
|
|
var eventsApi = function(obj, action, name, rest) {
|
|
if (!name) return true;
|
|
if (typeof name === 'object') {
|
|
for (var key in name) {
|
|
obj[action].apply(obj, [key, name[key]].concat(rest));
|
|
}
|
|
} else if (eventSplitter.test(name)) {
|
|
var names = name.split(eventSplitter);
|
|
for (var i = 0, l = names.length; i < l; i++) {
|
|
obj[action].apply(obj, [names[i]].concat(rest));
|
|
}
|
|
} else {
|
|
return true;
|
|
}
|
|
};
|
|
|
|
var triggerEvents = function(events, args) {
|
|
var ev, i = -1, l = events.length;
|
|
switch (args.length) {
|
|
case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx);
|
|
return;
|
|
case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0]);
|
|
return;
|
|
case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1]);
|
|
return;
|
|
case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1], args[2]);
|
|
return;
|
|
default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
|
|
}
|
|
};
|
|
|
|
var Events = {
|
|
|
|
on: function(name, callback, context) {
|
|
if (!(eventsApi(this, 'on', name, [callback, context]) && callback)) return this;
|
|
this._events || (this._events = {});
|
|
var list = this._events[name] || (this._events[name] = []);
|
|
list.push({callback: callback, context: context, ctx: context || this});
|
|
return this;
|
|
},
|
|
|
|
once: function(name, callback, context) {
|
|
if (!(eventsApi(this, 'once', name, [callback, context]) && callback)) return this;
|
|
var self = this;
|
|
var once = _.once(function() {
|
|
self.off(name, once);
|
|
callback.apply(this, arguments);
|
|
});
|
|
once._callback = callback;
|
|
this.on(name, once, context);
|
|
return this;
|
|
},
|
|
|
|
off: function(name, callback, context) {
|
|
var list, ev, events, names, i, l, j, k;
|
|
if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
|
|
if (!name && !callback && !context) {
|
|
this._events = {};
|
|
return this;
|
|
}
|
|
|
|
names = name ? [name] : _.keys(this._events);
|
|
for (i = 0, l = names.length; i < l; i++) {
|
|
name = names[i];
|
|
if (list = this._events[name]) {
|
|
events = [];
|
|
if (callback || context) {
|
|
for (j = 0, k = list.length; j < k; j++) {
|
|
ev = list[j];
|
|
if ((callback && callback !== ev.callback &&
|
|
callback !== ev.callback._callback) ||
|
|
(context && context !== ev.context)) {
|
|
events.push(ev);
|
|
}
|
|
}
|
|
}
|
|
this._events[name] = events;
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
trigger: function(name) {
|
|
if (!this._events) return this;
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
if (!eventsApi(this, 'trigger', name, args)) return this;
|
|
var events = this._events[name];
|
|
var allEvents = this._events.all;
|
|
if (events) triggerEvents(events, args);
|
|
if (allEvents) triggerEvents(allEvents, arguments);
|
|
return this;
|
|
},
|
|
|
|
listenTo: function(obj, name, callback) {
|
|
var listeners = this._listeners || (this._listeners = {});
|
|
var id = obj._listenerId || (obj._listenerId = _.uniqueId('l'));
|
|
listeners[id] = obj;
|
|
obj.on(name, typeof name === 'object' ? this : callback, this);
|
|
return this;
|
|
},
|
|
|
|
stopListening: function(obj, name, callback) {
|
|
var listeners = this._listeners;
|
|
if (!listeners) return;
|
|
if (obj) {
|
|
obj.off(name, typeof name === 'object' ? this : callback, this);
|
|
if (!name && !callback) delete listeners[obj._listenerId];
|
|
} else {
|
|
if (typeof name === 'object') callback = this;
|
|
for (var id in listeners) {
|
|
listeners[id].off(name, callback, this);
|
|
}
|
|
this._listeners = {};
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
|
|
Events.bind = Events.on;
|
|
Events.unbind = Events.off;
|
|
return Events;
|
|
};
|
|
return eventsShim();
|
|
})();
|