Commit 866c258c authored by JC Brand's avatar JC Brand

Created new builds. Updates #339.

parent 7cd27a71
/** /**
* @license almond 0.3.0 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license. * Available via the MIT or new BSD license.
* see: http://github.com/jrburke/almond for details * see: http://github.com/jrburke/almond for details
*/ */
...@@ -44,12 +44,6 @@ var requirejs, require, define; ...@@ -44,12 +44,6 @@ var requirejs, require, define;
//otherwise, assume it is a top-level require that will //otherwise, assume it is a top-level require that will
//be relative to baseUrl in the end. //be relative to baseUrl in the end.
if (baseName) { 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('/'); name = name.split('/');
lastIndex = name.length - 1; lastIndex = name.length - 1;
...@@ -58,7 +52,11 @@ var requirejs, require, define; ...@@ -58,7 +52,11 @@ var requirejs, require, define;
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
} }
name = baseParts.concat(name); //Lop off the last part of baseParts, so that . matches the
//"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.
name = baseParts.slice(0, baseParts.length - 1).concat(name);
//start trimDots //start trimDots
for (i = 0; i < name.length; i += 1) { for (i = 0; i < name.length; i += 1) {
...@@ -408,6 +406,9 @@ var requirejs, require, define; ...@@ -408,6 +406,9 @@ var requirejs, require, define;
requirejs._defined = defined; requirejs._defined = defined;
define = function (name, deps, callback) { define = function (name, deps, callback) {
if (typeof name !== 'string') {
throw new Error('See almond README: incorrect module build, no module name');
}
//This module may not have dependencies //This module may not have dependencies
if (!deps.splice) { if (!deps.splice) {
...@@ -11164,9 +11165,9 @@ define('text',['module'], function (module) { ...@@ -11164,9 +11165,9 @@ define('text',['module'], function (module) {
return text; return text;
}); });
// Underscore.js 1.6.0 // Underscore.js 1.8.2
// http://underscorejs.org // http://underscorejs.org
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license. // Underscore may be freely distributed under the MIT license.
(function() { (function() {
...@@ -11180,9 +11181,6 @@ define('text',['module'], function (module) { ...@@ -11180,9 +11181,6 @@ define('text',['module'], function (module) {
// Save the previous value of the `_` variable. // Save the previous value of the `_` variable.
var previousUnderscore = root._; var previousUnderscore = root._;
// Establish the object that gets returned to break out of a loop iteration.
var breaker = {};
// Save bytes in the minified (but not gzipped) version: // Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
...@@ -11190,25 +11188,19 @@ define('text',['module'], function (module) { ...@@ -11190,25 +11188,19 @@ define('text',['module'], function (module) {
var var
push = ArrayProto.push, push = ArrayProto.push,
slice = ArrayProto.slice, slice = ArrayProto.slice,
concat = ArrayProto.concat,
toString = ObjProto.toString, toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty; hasOwnProperty = ObjProto.hasOwnProperty;
// All **ECMAScript 5** native function implementations that we hope to use // All **ECMAScript 5** native function implementations that we hope to use
// are declared here. // are declared here.
var 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, nativeIsArray = Array.isArray,
nativeKeys = Object.keys, nativeKeys = Object.keys,
nativeBind = FuncProto.bind; nativeBind = FuncProto.bind,
nativeCreate = Object.create;
// Naked function reference for surrogate-prototype-swapping.
var Ctor = function(){};
// Create a safe reference to the Underscore object for use below. // Create a safe reference to the Underscore object for use below.
var _ = function(obj) { var _ = function(obj) {
...@@ -11219,8 +11211,7 @@ define('text',['module'], function (module) { ...@@ -11219,8 +11211,7 @@ define('text',['module'], function (module) {
// Export the Underscore object for **Node.js**, with // Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in // backwards-compatibility for the old `require()` API. If we're in
// the browser, add `_` as a global object via a string identifier, // the browser, add `_` as a global object.
// for Closure Compiler "advanced" mode.
if (typeof exports !== 'undefined') { if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) { if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _; exports = module.exports = _;
...@@ -11231,161 +11222,208 @@ define('text',['module'], function (module) { ...@@ -11231,161 +11222,208 @@ define('text',['module'], function (module) {
} }
// Current version. // Current version.
_.VERSION = '1.6.0'; _.VERSION = '1.8.2';
// Internal function that returns an efficient (for current engines) version
// of the passed-in callback, to be repeatedly applied in other Underscore
// functions.
var optimizeCb = function(func, context, argCount) {
if (context === void 0) return func;
switch (argCount == null ? 3 : argCount) {
case 1: return function(value) {
return func.call(context, value);
};
case 2: return function(value, other) {
return func.call(context, value, other);
};
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
};
// A mostly-internal function to generate callbacks that can be applied
// to each element in a collection, returning the desired result — either
// identity, an arbitrary callback, a property matcher, or a property accessor.
var cb = function(value, context, argCount) {
if (value == null) return _.identity;
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
if (_.isObject(value)) return _.matcher(value);
return _.property(value);
};
_.iteratee = function(value, context) {
return cb(value, context, Infinity);
};
// An internal function for creating assigner functions.
var createAssigner = function(keysFunc, undefinedOnly) {
return function(obj) {
var length = arguments.length;
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
};
// An internal function for creating a new object that inherits from another.
var baseCreate = function(prototype) {
if (!_.isObject(prototype)) return {};
if (nativeCreate) return nativeCreate(prototype);
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
// Helper for collection methods to determine whether a collection
// should be iterated as an array or as an object
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var isArrayLike = function(collection) {
var length = collection && collection.length;
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
// Collection Functions // Collection Functions
// -------------------- // --------------------
// The cornerstone, an `each` implementation, aka `forEach`. // The cornerstone, an `each` implementation, aka `forEach`.
// Handles objects with the built-in `forEach`, arrays, and raw objects. // Handles raw objects in addition to array-likes. Treats all
// Delegates to **ECMAScript 5**'s native `forEach` if available. // sparse array-likes as if they were dense.
var each = _.each = _.forEach = function(obj, iterator, context) { _.each = _.forEach = function(obj, iteratee, context) {
if (obj == null) return obj; iteratee = optimizeCb(iteratee, context);
if (nativeForEach && obj.forEach === nativeForEach) { var i, length;
obj.forEach(iterator, context); if (isArrayLike(obj)) {
} else if (obj.length === +obj.length) { for (i = 0, length = obj.length; i < length; i++) {
for (var i = 0, length = obj.length; i < length; i++) { iteratee(obj[i], i, obj);
if (iterator.call(context, obj[i], i, obj) === breaker) return;
} }
} else { } else {
var keys = _.keys(obj); var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) { for (i = 0, length = keys.length; i < length; i++) {
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; iteratee(obj[keys[i]], keys[i], obj);
} }
} }
return obj; return obj;
}; };
// Return the results of applying the iterator to each element. // Return the results of applying the iteratee to each element.
// Delegates to **ECMAScript 5**'s native `map` if available. _.map = _.collect = function(obj, iteratee, context) {
_.map = _.collect = function(obj, iterator, context) { iteratee = cb(iteratee, context);
var results = []; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return results; length = (keys || obj).length,
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); results = Array(length);
each(obj, function(value, index, list) { for (var index = 0; index < length; index++) {
results.push(iterator.call(context, value, index, list)); var currentKey = keys ? keys[index] : index;
}); results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results; return results;
}; };
var reduceError = 'Reduce of empty array with no initial value'; // Create a reducing function iterating left or right.
function createReduce(dir) {
// **Reduce** builds up a single result from a list of values, aka `inject`, // Optimized iterator function as using arguments.length
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. // in the main function will deoptimize the, see #1991.
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { function iterator(obj, iteratee, memo, keys, index, length) {
var initial = arguments.length > 2; for (; index >= 0 && index < length; index += dir) {
if (obj == null) obj = []; var currentKey = keys ? keys[index] : index;
if (nativeReduce && obj.reduce === nativeReduce) { memo = iteratee(memo, obj[currentKey], currentKey, obj);
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
}
each(obj, function(value, index, list) {
if (!initial) {
memo = value;
initial = true;
} else {
memo = iterator.call(context, memo, value, index, list);
} }
});
if (!initial) throw new TypeError(reduceError);
return memo; return memo;
};
// The right-associative version of reduce, also known as `foldr`.
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
var initial = arguments.length > 2;
if (obj == null) obj = [];
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
}
var length = obj.length;
if (length !== +length) {
var keys = _.keys(obj);
length = keys.length;
} }
each(obj, function(value, index, list) {
index = keys ? keys[--length] : --length; return function(obj, iteratee, memo, context) {
if (!initial) { iteratee = optimizeCb(iteratee, context, 4);
memo = obj[index]; var keys = !isArrayLike(obj) && _.keys(obj),
initial = true; length = (keys || obj).length,
} else { index = dir > 0 ? 0 : length - 1;
memo = iterator.call(context, memo, obj[index], index, list); // Determine the initial value if none is provided.
if (arguments.length < 3) {
memo = obj[keys ? keys[index] : index];
index += dir;
} }
}); return iterator(obj, iteratee, memo, keys, index, length);
if (!initial) throw new TypeError(reduceError);
return memo;
}; };
}
// **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`.
_.reduce = _.foldl = _.inject = createReduce(1);
// The right-associative version of reduce, also known as `foldr`.
_.reduceRight = _.foldr = createReduce(-1);
// Return the first value which passes a truth test. Aliased as `detect`. // Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function(obj, predicate, context) { _.find = _.detect = function(obj, predicate, context) {
var result; var key;
any(obj, function(value, index, list) { if (isArrayLike(obj)) {
if (predicate.call(context, value, index, list)) { key = _.findIndex(obj, predicate, context);
result = value; } else {
return true; key = _.findKey(obj, predicate, context);
} }
}); if (key !== void 0 && key !== -1) return obj[key];
return result;
}; };
// Return all the elements that pass a truth test. // Return all the elements that pass a truth test.
// Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`. // Aliased as `select`.
_.filter = _.select = function(obj, predicate, context) { _.filter = _.select = function(obj, predicate, context) {
var results = []; var results = [];
if (obj == null) return results; predicate = cb(predicate, context);
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); _.each(obj, function(value, index, list) {
each(obj, function(value, index, list) { if (predicate(value, index, list)) results.push(value);
if (predicate.call(context, value, index, list)) results.push(value);
}); });
return results; return results;
}; };
// Return all the elements for which a truth test fails. // Return all the elements for which a truth test fails.
_.reject = function(obj, predicate, context) { _.reject = function(obj, predicate, context) {
return _.filter(obj, function(value, index, list) { return _.filter(obj, _.negate(cb(predicate)), context);
return !predicate.call(context, value, index, list);
}, context);
}; };
// Determine whether all of the elements match a truth test. // Determine whether all of the elements match a truth test.
// Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`. // Aliased as `all`.
_.every = _.all = function(obj, predicate, context) { _.every = _.all = function(obj, predicate, context) {
predicate || (predicate = _.identity); predicate = cb(predicate, context);
var result = true; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return result; length = (keys || obj).length;
if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); for (var index = 0; index < length; index++) {
each(obj, function(value, index, list) { var currentKey = keys ? keys[index] : index;
if (!(result = result && predicate.call(context, value, index, list))) return breaker; if (!predicate(obj[currentKey], currentKey, obj)) return false;
}); }
return !!result; return true;
}; };
// Determine if at least one element in the object matches a truth test. // Determine if at least one element in the object matches a truth test.
// Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`. // Aliased as `any`.
var any = _.some = _.any = function(obj, predicate, context) { _.some = _.any = function(obj, predicate, context) {
predicate || (predicate = _.identity); predicate = cb(predicate, context);
var result = false; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return result; length = (keys || obj).length;
if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); for (var index = 0; index < length; index++) {
each(obj, function(value, index, list) { var currentKey = keys ? keys[index] : index;
if (result || (result = predicate.call(context, value, index, list))) return breaker; if (predicate(obj[currentKey], currentKey, obj)) return true;
}); }
return !!result; return false;
}; };
// Determine if the array or object contains a given value (using `===`). // Determine if the array or object contains a given value (using `===`).
// Aliased as `include`. // Aliased as `includes` and `include`.
_.contains = _.include = function(obj, target) { _.contains = _.includes = _.include = function(obj, target, fromIndex) {
if (obj == null) return false; if (!isArrayLike(obj)) obj = _.values(obj);
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; return _.indexOf(obj, target, typeof fromIndex == 'number' && fromIndex) >= 0;
return any(obj, function(value) {
return value === target;
});
}; };
// Invoke a method (with arguments) on every item in a collection. // Invoke a method (with arguments) on every item in a collection.
...@@ -11393,7 +11431,8 @@ define('text',['module'], function (module) { ...@@ -11393,7 +11431,8 @@ define('text',['module'], function (module) {
var args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
var isFunc = _.isFunction(method); var isFunc = _.isFunction(method);
return _.map(obj, function(value) { return _.map(obj, function(value) {
return (isFunc ? method : value[method]).apply(value, args); var func = isFunc ? method : value[method];
return func == null ? func : func.apply(value, args);
}); });
}; };
...@@ -11405,60 +11444,76 @@ define('text',['module'], function (module) { ...@@ -11405,60 +11444,76 @@ define('text',['module'], function (module) {
// Convenience version of a common use case of `filter`: selecting only objects // Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs. // containing specific `key:value` pairs.
_.where = function(obj, attrs) { _.where = function(obj, attrs) {
return _.filter(obj, _.matches(attrs)); return _.filter(obj, _.matcher(attrs));
}; };
// Convenience version of a common use case of `find`: getting the first object // Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs. // containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) { _.findWhere = function(obj, attrs) {
return _.find(obj, _.matches(attrs)); return _.find(obj, _.matcher(attrs));
}; };
// Return the maximum element or (element-based computation). // Return the maximum element (or element-based computation).
// Can't optimize arrays of integers longer than 65,535 elements. _.max = function(obj, iteratee, context) {
// See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) var result = -Infinity, lastComputed = -Infinity,
_.max = function(obj, iterator, context) { value, computed;
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { if (iteratee == null && obj != null) {
return Math.max.apply(Math, obj); obj = isArrayLike(obj) ? obj : _.values(obj);
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value > result) {
result = value;
}
} }
var result = -Infinity, lastComputed = -Infinity; } else {
each(obj, function(value, index, list) { iteratee = cb(iteratee, context);
var computed = iterator ? iterator.call(context, value, index, list) : value; _.each(obj, function(value, index, list) {
if (computed > lastComputed) { computed = iteratee(value, index, list);
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
result = value; result = value;
lastComputed = computed; lastComputed = computed;
} }
}); });
}
return result; return result;
}; };
// Return the minimum element (or element-based computation). // Return the minimum element (or element-based computation).
_.min = function(obj, iterator, context) { _.min = function(obj, iteratee, context) {
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { var result = Infinity, lastComputed = Infinity,
return Math.min.apply(Math, obj); value, computed;
} if (iteratee == null && obj != null) {
var result = Infinity, lastComputed = Infinity; obj = isArrayLike(obj) ? obj : _.values(obj);
each(obj, function(value, index, list) { for (var i = 0, length = obj.length; i < length; i++) {
var computed = iterator ? iterator.call(context, value, index, list) : value; value = obj[i];
if (computed < lastComputed) { if (value < result) {
result = value;
}
}
} else {
iteratee = cb(iteratee, context);
_.each(obj, function(value, index, list) {
computed = iteratee(value, index, list);
if (computed < lastComputed || computed === Infinity && result === Infinity) {
result = value; result = value;
lastComputed = computed; lastComputed = computed;
} }
}); });
}
return result; return result;
}; };
// Shuffle an array, using the modern version of the // Shuffle a collection, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_.shuffle = function(obj) { _.shuffle = function(obj) {
var rand; var set = isArrayLike(obj) ? obj : _.values(obj);
var index = 0; var length = set.length;
var shuffled = []; var shuffled = Array(length);
each(obj, function(value) { for (var index = 0, rand; index < length; index++) {
rand = _.random(index++); rand = _.random(0, index);
shuffled[index - 1] = shuffled[rand]; if (rand !== index) shuffled[index] = shuffled[rand];
shuffled[rand] = value; shuffled[rand] = set[index];
}); }
return shuffled; return shuffled;
}; };
...@@ -11467,27 +11522,20 @@ define('text',['module'], function (module) { ...@@ -11467,27 +11522,20 @@ define('text',['module'], function (module) {
// The internal `guard` argument allows it to work with `map`. // The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) { _.sample = function(obj, n, guard) {
if (n == null || guard) { if (n == null || guard) {
if (obj.length !== +obj.length) obj = _.values(obj); if (!isArrayLike(obj)) obj = _.values(obj);
return obj[_.random(obj.length - 1)]; return obj[_.random(obj.length - 1)];
} }
return _.shuffle(obj).slice(0, Math.max(0, n)); return _.shuffle(obj).slice(0, Math.max(0, n));
}; };
// An internal function to generate lookup iterators. // Sort the object's values by a criterion produced by an iteratee.
var lookupIterator = function(value) { _.sortBy = function(obj, iteratee, context) {
if (value == null) return _.identity; iteratee = cb(iteratee, context);
if (_.isFunction(value)) return value;
return _.property(value);
};
// Sort the object's values by a criterion produced by an iterator.
_.sortBy = function(obj, iterator, context) {
iterator = lookupIterator(iterator);
return _.pluck(_.map(obj, function(value, index, list) { return _.pluck(_.map(obj, function(value, index, list) {
return { return {
value: value, value: value,
index: index, index: index,
criteria: iterator.call(context, value, index, list) criteria: iteratee(value, index, list)
}; };
}).sort(function(left, right) { }).sort(function(left, right) {
var a = left.criteria; var a = left.criteria;
...@@ -11502,12 +11550,12 @@ define('text',['module'], function (module) { ...@@ -11502,12 +11550,12 @@ define('text',['module'], function (module) {
// An internal function used for aggregate "group by" operations. // An internal function used for aggregate "group by" operations.
var group = function(behavior) { var group = function(behavior) {
return function(obj, iterator, context) { return function(obj, iteratee, context) {
var result = {}; var result = {};
iterator = lookupIterator(iterator); iteratee = cb(iteratee, context);
each(obj, function(value, index) { _.each(obj, function(value, index) {
var key = iterator.call(context, value, index, obj); var key = iteratee(value, index, obj);
behavior(result, key, value); behavior(result, value, key);
}); });
return result; return result;
}; };
...@@ -11515,48 +11563,46 @@ define('text',['module'], function (module) { ...@@ -11515,48 +11563,46 @@ define('text',['module'], function (module) {
// Groups the object's values by a criterion. Pass either a string attribute // Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion. // to group by, or a function that returns the criterion.
_.groupBy = group(function(result, key, value) { _.groupBy = group(function(result, value, key) {
_.has(result, key) ? result[key].push(value) : result[key] = [value]; if (_.has(result, key)) result[key].push(value); else result[key] = [value];
}); });
// Indexes the object's values by a criterion, similar to `groupBy`, but for // Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique. // when you know that your index values will be unique.
_.indexBy = group(function(result, key, value) { _.indexBy = group(function(result, value, key) {
result[key] = value; result[key] = value;
}); });
// Counts instances of an object that group by a certain criterion. Pass // Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the // either a string attribute to count by, or a function that returns the
// criterion. // criterion.
_.countBy = group(function(result, key) { _.countBy = group(function(result, value, key) {
_.has(result, key) ? result[key]++ : result[key] = 1; if (_.has(result, key)) result[key]++; else result[key] = 1;
}); });
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iterator, context) {
iterator = lookupIterator(iterator);
var value = iterator.call(context, obj);
var low = 0, high = array.length;
while (low < high) {
var mid = (low + high) >>> 1;
iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
}
return low;
};
// Safely create a real, live array from anything iterable. // Safely create a real, live array from anything iterable.
_.toArray = function(obj) { _.toArray = function(obj) {
if (!obj) return []; if (!obj) return [];
if (_.isArray(obj)) return slice.call(obj); if (_.isArray(obj)) return slice.call(obj);
if (obj.length === +obj.length) return _.map(obj, _.identity); if (isArrayLike(obj)) return _.map(obj, _.identity);
return _.values(obj); return _.values(obj);
}; };
// Return the number of elements in an object. // Return the number of elements in an object.
_.size = function(obj) { _.size = function(obj) {
if (obj == null) return 0; if (obj == null) return 0;
return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; return isArrayLike(obj) ? obj.length : _.keys(obj).length;
};
// Split a collection into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(obj, predicate, context) {
predicate = cb(predicate, context);
var pass = [], fail = [];
_.each(obj, function(value, key, obj) {
(predicate(value, key, obj) ? pass : fail).push(value);
});
return [pass, fail];
}; };
// Array Functions // Array Functions
...@@ -11567,33 +11613,30 @@ define('text',['module'], function (module) { ...@@ -11567,33 +11613,30 @@ define('text',['module'], function (module) {
// allows it to work with `_.map`. // allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) { _.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0; if (array == null) return void 0;
if ((n == null) || guard) return array[0]; if (n == null || guard) return array[0];
if (n < 0) return []; return _.initial(array, array.length - n);
return slice.call(array, 0, n);
}; };
// Returns everything but the last entry of the array. Especially useful on // Returns everything but the last entry of the array. Especially useful on
// the arguments object. Passing **n** will return all the values in // the arguments object. Passing **n** will return all the values in
// the array, excluding the last N. The **guard** check allows it to work with // the array, excluding the last N.
// `_.map`.
_.initial = function(array, n, guard) { _.initial = function(array, n, guard) {
return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
}; };
// Get the last element of an array. Passing **n** will return the last N // Get the last element of an array. Passing **n** will return the last N
// values in the array. The **guard** check allows it to work with `_.map`. // values in the array.
_.last = function(array, n, guard) { _.last = function(array, n, guard) {
if (array == null) return void 0; if (array == null) return void 0;
if ((n == null) || guard) return array[array.length - 1]; if (n == null || guard) return array[array.length - 1];
return slice.call(array, Math.max(array.length - n, 0)); return _.rest(array, Math.max(0, array.length - n));
}; };
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`. // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
// Especially useful on the arguments object. Passing an **n** will return // Especially useful on the arguments object. Passing an **n** will return
// the rest N values in the array. The **guard** // the rest N values in the array.
// check allows it to work with `_.map`.
_.rest = _.tail = _.drop = function(array, n, guard) { _.rest = _.tail = _.drop = function(array, n, guard) {
return slice.call(array, (n == null) || guard ? 1 : n); return slice.call(array, n == null || guard ? 1 : n);
}; };
// Trim out all falsy values from an array. // Trim out all falsy values from an array.
...@@ -11602,23 +11645,28 @@ define('text',['module'], function (module) { ...@@ -11602,23 +11645,28 @@ define('text',['module'], function (module) {
}; };
// Internal implementation of a recursive `flatten` function. // Internal implementation of a recursive `flatten` function.
var flatten = function(input, shallow, output) { var flatten = function(input, shallow, strict, startIndex) {
if (shallow && _.every(input, _.isArray)) { var output = [], idx = 0;
return concat.apply(output, input); for (var i = startIndex || 0, length = input && input.length; i < length; i++) {
var value = input[i];
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
//flatten current level of array or arguments object
if (!shallow) value = flatten(value, shallow, strict);
var j = 0, len = value.length;
output.length += len;
while (j < len) {
output[idx++] = value[j++];
}
} else if (!strict) {
output[idx++] = value;
} }
each(input, function(value) {
if (_.isArray(value) || _.isArguments(value)) {
shallow ? push.apply(output, value) : flatten(value, shallow, output);
} else {
output.push(value);
} }
});
return output; return output;
}; };
// Flatten out an array, either recursively (by default), or just one level. // Flatten out an array, either recursively (by default), or just one level.
_.flatten = function(array, shallow) { _.flatten = function(array, shallow) {
return flatten(array, shallow, []); return flatten(array, shallow, false);
}; };
// Return a version of the array that does not contain the specified value(s). // Return a version of the array that does not contain the specified value(s).
...@@ -11626,79 +11674,93 @@ define('text',['module'], function (module) { ...@@ -11626,79 +11674,93 @@ define('text',['module'], function (module) {
return _.difference(array, slice.call(arguments, 1)); return _.difference(array, slice.call(arguments, 1));
}; };
// Split an array into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(array, predicate) {
var pass = [], fail = [];
each(array, function(elem) {
(predicate(elem) ? pass : fail).push(elem);
});
return [pass, fail];
};
// Produce a duplicate-free version of the array. If the array has already // Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm. // been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`. // Aliased as `unique`.
_.uniq = _.unique = function(array, isSorted, iterator, context) { _.uniq = _.unique = function(array, isSorted, iteratee, context) {
if (_.isFunction(isSorted)) { if (array == null) return [];
context = iterator; if (!_.isBoolean(isSorted)) {
iterator = isSorted; context = iteratee;
iteratee = isSorted;
isSorted = false; isSorted = false;
} }
var initial = iterator ? _.map(array, iterator, context) : array; if (iteratee != null) iteratee = cb(iteratee, context);
var results = []; var result = [];
var seen = []; var seen = [];
each(initial, function(value, index) { for (var i = 0, length = array.length; i < length; i++) {
if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { var value = array[i],
seen.push(value); computed = iteratee ? iteratee(value, i, array) : value;
results.push(array[index]); if (isSorted) {
if (!i || seen !== computed) result.push(value);
seen = computed;
} else if (iteratee) {
if (!_.contains(seen, computed)) {
seen.push(computed);
result.push(value);
} }
}); } else if (!_.contains(result, value)) {
return results; result.push(value);
}
}
return result;
}; };
// Produce an array that contains the union: each distinct element from all of // Produce an array that contains the union: each distinct element from all of
// the passed-in arrays. // the passed-in arrays.
_.union = function() { _.union = function() {
return _.uniq(_.flatten(arguments, true)); return _.uniq(flatten(arguments, true, true));
}; };
// Produce an array that contains every item shared between all the // Produce an array that contains every item shared between all the
// passed-in arrays. // passed-in arrays.
_.intersection = function(array) { _.intersection = function(array) {
var rest = slice.call(arguments, 1); if (array == null) return [];
return _.filter(_.uniq(array), function(item) { var result = [];
return _.every(rest, function(other) { var argsLength = arguments.length;
return _.contains(other, item); for (var i = 0, length = array.length; i < length; i++) {
}); var item = array[i];
}); if (_.contains(result, item)) continue;
for (var j = 1; j < argsLength; j++) {
if (!_.contains(arguments[j], item)) break;
}
if (j === argsLength) result.push(item);
}
return result;
}; };
// Take the difference between one array and a number of other arrays. // Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain. // Only the elements present in just the first array will remain.
_.difference = function(array) { _.difference = function(array) {
var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); var rest = flatten(arguments, true, true, 1);
return _.filter(array, function(value){ return !_.contains(rest, value); }); return _.filter(array, function(value){
return !_.contains(rest, value);
});
}; };
// Zip together multiple lists into a single array -- elements that share // Zip together multiple lists into a single array -- elements that share
// an index go together. // an index go together.
_.zip = function() { _.zip = function() {
var length = _.max(_.pluck(arguments, 'length').concat(0)); return _.unzip(arguments);
var results = new Array(length); };
for (var i = 0; i < length; i++) {
results[i] = _.pluck(arguments, '' + i); // Complement of _.zip. Unzip accepts an array of arrays and groups
// each array's elements on shared indices
_.unzip = function(array) {
var length = array && _.max(array, 'length').length || 0;
var result = Array(length);
for (var index = 0; index < length; index++) {
result[index] = _.pluck(array, index);
} }
return results; return result;
}; };
// Converts lists into objects. Pass either a single array of `[key, value]` // Converts lists into objects. Pass either a single array of `[key, value]`
// pairs, or two parallel arrays of the same length -- one of keys, and one of // pairs, or two parallel arrays of the same length -- one of keys, and one of
// the corresponding values. // the corresponding values.
_.object = function(list, values) { _.object = function(list, values) {
if (list == null) return {};
var result = {}; var result = {};
for (var i = 0, length = list.length; i < length; i++) { for (var i = 0, length = list && list.length; i < length; i++) {
if (values) { if (values) {
result[list[i]] = values[i]; result[list[i]] = values[i];
} else { } else {
...@@ -11708,40 +11770,68 @@ define('text',['module'], function (module) { ...@@ -11708,40 +11770,68 @@ define('text',['module'], function (module) {
return result; return result;
}; };
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), // Return the position of the first occurrence of an item in an array,
// we need this function. Return the position of the first occurrence of an // or -1 if the item is not included in the array.
// item in an array, or -1 if the item is not included in the array.
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
// If the array is large and already in sort order, pass `true` // If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search. // for **isSorted** to use binary search.
_.indexOf = function(array, item, isSorted) { _.indexOf = function(array, item, isSorted) {
if (array == null) return -1; var i = 0, length = array && array.length;
var i = 0, length = array.length;
if (isSorted) {
if (typeof isSorted == 'number') { if (typeof isSorted == 'number') {
i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
} else { } else if (isSorted && length) {
i = _.sortedIndex(array, item); i = _.sortedIndex(array, item);
return array[i] === item ? i : -1; return array[i] === item ? i : -1;
} }
if (item !== item) {
return _.findIndex(slice.call(array, i), _.isNaN);
} }
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
for (; i < length; i++) if (array[i] === item) return i; for (; i < length; i++) if (array[i] === item) return i;
return -1; return -1;
}; };
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
_.lastIndexOf = function(array, item, from) { _.lastIndexOf = function(array, item, from) {
if (array == null) return -1; var idx = array ? array.length : 0;
var hasIndex = from != null; if (typeof from == 'number') {
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); }
if (item !== item) {
return _.findLastIndex(slice.call(array, 0, idx), _.isNaN);
} }
var i = (hasIndex ? from : array.length); while (--idx >= 0) if (array[idx] === item) return idx;
while (i--) if (array[i] === item) return i;
return -1; return -1;
}; };
// Generator function to create the findIndex and findLastIndex functions
function createIndexFinder(dir) {
return function(array, predicate, context) {
predicate = cb(predicate, context);
var length = array != null && array.length;
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
}
// Returns the first index on an array-like that passes a predicate test
_.findIndex = createIndexFinder(1);
_.findLastIndex = createIndexFinder(-1);
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iteratee, context) {
iteratee = cb(iteratee, context, 1);
var value = iteratee(obj);
var low = 0, high = array.length;
while (low < high) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
};
// Generate an integer Array containing an arithmetic progression. A port of // Generate an integer Array containing an arithmetic progression. A port of
// the native Python `range()` function. See // the native Python `range()` function. See
// [the Python documentation](http://docs.python.org/library/functions.html#range). // [the Python documentation](http://docs.python.org/library/functions.html#range).
...@@ -11750,15 +11840,13 @@ define('text',['module'], function (module) { ...@@ -11750,15 +11840,13 @@ define('text',['module'], function (module) {
stop = start || 0; stop = start || 0;
start = 0; start = 0;
} }
step = arguments[2] || 1; step = step || 1;
var length = Math.max(Math.ceil((stop - start) / step), 0); var length = Math.max(Math.ceil((stop - start) / step), 0);
var idx = 0; var range = Array(length);
var range = new Array(length);
while(idx < length) { for (var idx = 0; idx < length; idx++, start += step) {
range[idx++] = start; range[idx] = start;
start += step;
} }
return range; return range;
...@@ -11767,26 +11855,27 @@ define('text',['module'], function (module) { ...@@ -11767,26 +11855,27 @@ define('text',['module'], function (module) {
// Function (ahem) Functions // Function (ahem) Functions
// ------------------ // ------------------
// Reusable constructor function for prototype setting. // Determines whether to execute a function as a constructor
var ctor = function(){}; // or a normal function with the provided arguments
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
var self = baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
if (_.isObject(result)) return result;
return self;
};
// Create a function bound to a given object (assigning `this`, and arguments, // Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
// available. // available.
_.bind = function(func, context) { _.bind = function(func, context) {
var args, bound;
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError; if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
return bound = function() { var bound = function() {
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
ctor.prototype = func.prototype;
var self = new ctor;
ctor.prototype = null;
var result = func.apply(self, args.concat(slice.call(arguments)));
if (Object(result) === result) return result;
return self;
}; };
return bound;
}; };
// Partially apply a function by creating a version that has had some of its // Partially apply a function by creating a version that has had some of its
...@@ -11794,49 +11883,55 @@ define('text',['module'], function (module) { ...@@ -11794,49 +11883,55 @@ define('text',['module'], function (module) {
// as a placeholder, allowing any combination of arguments to be pre-filled. // as a placeholder, allowing any combination of arguments to be pre-filled.
_.partial = function(func) { _.partial = function(func) {
var boundArgs = slice.call(arguments, 1); var boundArgs = slice.call(arguments, 1);
return function() { var bound = function() {
var position = 0; var position = 0, length = boundArgs.length;
var args = boundArgs.slice(); var args = Array(length);
for (var i = 0, length = args.length; i < length; i++) { for (var i = 0; i < length; i++) {
if (args[i] === _) args[i] = arguments[position++]; args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
} }
while (position < arguments.length) args.push(arguments[position++]); while (position < arguments.length) args.push(arguments[position++]);
return func.apply(this, args); return executeBound(func, bound, this, this, args);
}; };
return bound;
}; };
// Bind a number of an object's methods to that object. Remaining arguments // Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks // are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it. // defined on an object belong to it.
_.bindAll = function(obj) { _.bindAll = function(obj) {
var funcs = slice.call(arguments, 1); var i, length = arguments.length, key;
if (funcs.length === 0) throw new Error('bindAll must be passed function names'); if (length <= 1) throw new Error('bindAll must be passed function names');
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); for (i = 1; i < length; i++) {
key = arguments[i];
obj[key] = _.bind(obj[key], obj);
}
return obj; return obj;
}; };
// Memoize an expensive function by storing its results. // Memoize an expensive function by storing its results.
_.memoize = function(func, hasher) { _.memoize = function(func, hasher) {
var memo = {}; var memoize = function(key) {
hasher || (hasher = _.identity); var cache = memoize.cache;
return function() { var address = '' + (hasher ? hasher.apply(this, arguments) : key);
var key = hasher.apply(this, arguments); if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); return cache[address];
}; };
memoize.cache = {};
return memoize;
}; };
// Delays a function for the given number of milliseconds, and then calls // Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied. // it with the arguments supplied.
_.delay = function(func, wait) { _.delay = function(func, wait) {
var args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
return setTimeout(function(){ return func.apply(null, args); }, wait); return setTimeout(function(){
return func.apply(null, args);
}, wait);
}; };
// Defers a function, scheduling it to run after the current call stack has // Defers a function, scheduling it to run after the current call stack has
// cleared. // cleared.
_.defer = function(func) { _.defer = _.partial(_.delay, _, 1);
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
};
// Returns a function, that, when invoked, will only be triggered at most once // Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run // during a given window of time. Normally, the throttled function will run
...@@ -11847,12 +11942,12 @@ define('text',['module'], function (module) { ...@@ -11847,12 +11942,12 @@ define('text',['module'], function (module) {
var context, args, result; var context, args, result;
var timeout = null; var timeout = null;
var previous = 0; var previous = 0;
options || (options = {}); if (!options) options = {};
var later = function() { var later = function() {
previous = options.leading === false ? 0 : _.now(); previous = options.leading === false ? 0 : _.now();
timeout = null; timeout = null;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
}; };
return function() { return function() {
var now = _.now(); var now = _.now();
...@@ -11860,12 +11955,14 @@ define('text',['module'], function (module) { ...@@ -11860,12 +11955,14 @@ define('text',['module'], function (module) {
var remaining = wait - (now - previous); var remaining = wait - (now - previous);
context = this; context = this;
args = arguments; args = arguments;
if (remaining <= 0) { if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout); clearTimeout(timeout);
timeout = null; timeout = null;
}
previous = now; previous = now;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) { } else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining); timeout = setTimeout(later, remaining);
} }
...@@ -11882,13 +11979,14 @@ define('text',['module'], function (module) { ...@@ -11882,13 +11979,14 @@ define('text',['module'], function (module) {
var later = function() { var later = function() {
var last = _.now() - timestamp; var last = _.now() - timestamp;
if (last < wait) {
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last); timeout = setTimeout(later, wait - last);
} else { } else {
timeout = null; timeout = null;
if (!immediate) { if (!immediate) {
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
} }
} }
}; };
...@@ -11898,9 +11996,7 @@ define('text',['module'], function (module) { ...@@ -11898,9 +11996,7 @@ define('text',['module'], function (module) {
args = arguments; args = arguments;
timestamp = _.now(); timestamp = _.now();
var callNow = immediate && !timeout; var callNow = immediate && !timeout;
if (!timeout) { if (!timeout) timeout = setTimeout(later, wait);
timeout = setTimeout(later, wait);
}
if (callNow) { if (callNow) {
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; context = args = null;
...@@ -11910,19 +12006,6 @@ define('text',['module'], function (module) { ...@@ -11910,19 +12006,6 @@ define('text',['module'], function (module) {
}; };
}; };
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
// Returns the first function passed as an argument to the second, // Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and // allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function. // conditionally execute the original function.
...@@ -11930,20 +12013,27 @@ define('text',['module'], function (module) { ...@@ -11930,20 +12013,27 @@ define('text',['module'], function (module) {
return _.partial(wrapper, func); return _.partial(wrapper, func);
}; };
// Returns a negated version of the passed-in predicate.
_.negate = function(predicate) {
return function() {
return !predicate.apply(this, arguments);
};
};
// Returns a function that is the composition of a list of functions, each // Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows. // consuming the return value of the function that follows.
_.compose = function() { _.compose = function() {
var funcs = arguments;
return function() {
var args = arguments; var args = arguments;
for (var i = funcs.length - 1; i >= 0; i--) { var start = args.length - 1;
args = [funcs[i].apply(this, args)]; return function() {
} var i = start;
return args[0]; var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
}; };
}; };
// Returns a function that will only be executed after being called N times. // Returns a function that will only be executed on and after the Nth call.
_.after = function(times, func) { _.after = function(times, func) {
return function() { return function() {
if (--times < 1) { if (--times < 1) {
...@@ -11952,16 +12042,66 @@ define('text',['module'], function (module) { ...@@ -11952,16 +12042,66 @@ define('text',['module'], function (module) {
}; };
}; };
// Returns a function that will only be executed up to (but not including) the Nth call.
_.before = function(times, func) {
var memo;
return function() {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
};
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = _.partial(_.before, 2);
// Object Functions // Object Functions
// ---------------- // ----------------
// Retrieve the names of an object's properties. // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
function collectNonEnumProps(obj, keys) {
var nonEnumIdx = nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
// Constructor is a special case.
var prop = 'constructor';
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
while (nonEnumIdx--) {
prop = nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
keys.push(prop);
}
}
}
// Retrieve the names of an object's own properties.
// Delegates to **ECMAScript 5**'s native `Object.keys` // Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = function(obj) { _.keys = function(obj) {
if (!_.isObject(obj)) return []; if (!_.isObject(obj)) return [];
if (nativeKeys) return nativeKeys(obj); if (nativeKeys) return nativeKeys(obj);
var keys = []; var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key); for (var key in obj) if (_.has(obj, key)) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Retrieve all the property names of an object.
_.allKeys = function(obj) {
if (!_.isObject(obj)) return [];
var keys = [];
for (var key in obj) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys; return keys;
}; };
...@@ -11969,18 +12109,33 @@ define('text',['module'], function (module) { ...@@ -11969,18 +12109,33 @@ define('text',['module'], function (module) {
_.values = function(obj) { _.values = function(obj) {
var keys = _.keys(obj); var keys = _.keys(obj);
var length = keys.length; var length = keys.length;
var values = new Array(length); var values = Array(length);
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]]; values[i] = obj[keys[i]];
} }
return values; return values;
}; };
// Returns the results of applying the iteratee to each element of the object
// In contrast to _.map it returns an object
_.mapObject = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = _.keys(obj),
length = keys.length,
results = {},
currentKey;
for (var index = 0; index < length; index++) {
currentKey = keys[index];
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
// Convert an object into a list of `[key, value]` pairs. // Convert an object into a list of `[key, value]` pairs.
_.pairs = function(obj) { _.pairs = function(obj) {
var keys = _.keys(obj); var keys = _.keys(obj);
var length = keys.length; var length = keys.length;
var pairs = new Array(length); var pairs = Array(length);
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]]; pairs[i] = [keys[i], obj[keys[i]]];
} }
...@@ -12008,48 +12163,57 @@ define('text',['module'], function (module) { ...@@ -12008,48 +12163,57 @@ define('text',['module'], function (module) {
}; };
// Extend a given object with all the properties in passed-in object(s). // Extend a given object with all the properties in passed-in object(s).
_.extend = function(obj) { _.extend = createAssigner(_.allKeys);
each(slice.call(arguments, 1), function(source) {
if (source) { // Assigns a given object with all the own properties in the passed-in object(s)
for (var prop in source) { // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
obj[prop] = source[prop]; _.extendOwn = _.assign = createAssigner(_.keys);
}
// Returns the first key on an object that passes a predicate test
_.findKey = function(obj, predicate, context) {
predicate = cb(predicate, context);
var keys = _.keys(obj), key;
for (var i = 0, length = keys.length; i < length; i++) {
key = keys[i];
if (predicate(obj[key], key, obj)) return key;
} }
});
return obj;
}; };
// Return a copy of the object only containing the whitelisted properties. // Return a copy of the object only containing the whitelisted properties.
_.pick = function(obj) { _.pick = function(object, oiteratee, context) {
var copy = {}; var result = {}, obj = object, iteratee, keys;
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); if (obj == null) return result;
each(keys, function(key) { if (_.isFunction(oiteratee)) {
if (key in obj) copy[key] = obj[key]; keys = _.allKeys(obj);
}); iteratee = optimizeCb(oiteratee, context);
return copy; } else {
keys = flatten(arguments, false, false, 1);
iteratee = function(value, key, obj) { return key in obj; };
obj = Object(obj);
}
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
var value = obj[key];
if (iteratee(value, key, obj)) result[key] = value;
}
return result;
}; };
// Return a copy of the object without the blacklisted properties. // Return a copy of the object without the blacklisted properties.
_.omit = function(obj) { _.omit = function(obj, iteratee, context) {
var copy = {}; if (_.isFunction(iteratee)) {
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); iteratee = _.negate(iteratee);
for (var key in obj) { } else {
if (!_.contains(keys, key)) copy[key] = obj[key]; var keys = _.map(flatten(arguments, false, false, 1), String);
iteratee = function(value, key) {
return !_.contains(keys, key);
};
} }
return copy; return _.pick(obj, iteratee, context);
}; };
// Fill in a given object with default properties. // Fill in a given object with default properties.
_.defaults = function(obj) { _.defaults = createAssigner(_.allKeys, true);
each(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) {
if (obj[prop] === void 0) obj[prop] = source[prop];
}
}
});
return obj;
};
// Create a (shallow-cloned) duplicate of an object. // Create a (shallow-cloned) duplicate of an object.
_.clone = function(obj) { _.clone = function(obj) {
...@@ -12065,11 +12229,24 @@ define('text',['module'], function (module) { ...@@ -12065,11 +12229,24 @@ define('text',['module'], function (module) {
return obj; return obj;
}; };
// Returns whether an object has a given set of `key:value` pairs.
_.isMatch = function(object, attrs) {
var keys = _.keys(attrs), length = keys.length;
if (object == null) return !length;
var obj = Object(object);
for (var i = 0; i < length; i++) {
var key = keys[i];
if (attrs[key] !== obj[key] || !(key in obj)) return false;
}
return true;
};
// Internal recursive comparison function for `isEqual`. // Internal recursive comparison function for `isEqual`.
var eq = function(a, b, aStack, bStack) { var eq = function(a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical. // Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a == 1 / b; if (a === b) return a !== 0 || 1 / a === 1 / b;
// A strict comparison is necessary because `null == undefined`. // A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b; if (a == null || b == null) return a === b;
// Unwrap any wrapped objects. // Unwrap any wrapped objects.
...@@ -12077,98 +12254,98 @@ define('text',['module'], function (module) { ...@@ -12077,98 +12254,98 @@ define('text',['module'], function (module) {
if (b instanceof _) b = b._wrapped; if (b instanceof _) b = b._wrapped;
// Compare `[[Class]]` names. // Compare `[[Class]]` names.
var className = toString.call(a); var className = toString.call(a);
if (className != toString.call(b)) return false; if (className !== toString.call(b)) return false;
switch (className) { switch (className) {
// Strings, numbers, dates, and booleans are compared by value. // Strings, numbers, regular expressions, dates, and booleans are compared by value.
case '[object RegExp]':
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case '[object String]': case '[object String]':
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`. // equivalent to `new String("5")`.
return a == String(b); return '' + a === '' + b;
case '[object Number]': case '[object Number]':
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for // `NaN`s are equivalent, but non-reflexive.
// other numeric values. // Object(NaN) is equivalent to NaN
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); if (+a !== +a) return +b !== +b;
// An `egal` comparison is performed for other numeric values.
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]': case '[object Date]':
case '[object Boolean]': case '[object Boolean]':
// Coerce dates and booleans to numeric primitive values. Dates are compared by their // Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations // millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent. // of `NaN` are not equivalent.
return +a == +b; return +a === +b;
// RegExps are compared by their source patterns and flags.
case '[object RegExp]':
return a.source == b.source &&
a.global == b.global &&
a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase;
} }
var areArrays = className === '[object Array]';
if (!areArrays) {
if (typeof a != 'object' || typeof b != 'object') return false; if (typeof a != 'object' || typeof b != 'object') return false;
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
_.isFunction(bCtor) && bCtor instanceof bCtor)
&& ('constructor' in a && 'constructor' in b)) {
return false;
}
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic // Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
// Initializing stack of traversed objects.
// It's done here since we only need them for objects and arrays comparison.
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length; var length = aStack.length;
while (length--) { while (length--) {
// Linear search. Performance is inversely proportional to the number of // Linear search. Performance is inversely proportional to the number of
// unique nested structures. // unique nested structures.
if (aStack[length] == a) return bStack[length] == b; if (aStack[length] === a) return bStack[length] === b;
}
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
_.isFunction(bCtor) && (bCtor instanceof bCtor))
&& ('constructor' in a && 'constructor' in b)) {
return false;
} }
// Add the first object to the stack of traversed objects. // Add the first object to the stack of traversed objects.
aStack.push(a); aStack.push(a);
bStack.push(b); bStack.push(b);
var size = 0, result = true;
// Recursively compare objects and arrays. // Recursively compare objects and arrays.
if (className == '[object Array]') { if (areArrays) {
// Compare array lengths to determine if a deep comparison is necessary. // Compare array lengths to determine if a deep comparison is necessary.
size = a.length; length = a.length;
result = size == b.length; if (length !== b.length) return false;
if (result) {
// Deep compare the contents, ignoring non-numeric properties. // Deep compare the contents, ignoring non-numeric properties.
while (size--) { while (length--) {
if (!(result = eq(a[size], b[size], aStack, bStack))) break; if (!eq(a[length], b[length], aStack, bStack)) return false;
}
} }
} else { } else {
// Deep compare objects. // Deep compare objects.
for (var key in a) { var keys = _.keys(a), key;
if (_.has(a, key)) { length = keys.length;
// Count the expected number of properties. // Ensure that both objects contain the same number of properties before comparing deep equality.
size++; if (_.keys(b).length !== length) return false;
// Deep compare each member. while (length--) {
if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; // Deep compare each member
} key = keys[length];
} if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
// Ensure that both objects contain the same number of properties.
if (result) {
for (key in b) {
if (_.has(b, key) && !(size--)) break;
}
result = !size;
} }
} }
// Remove the first object from the stack of traversed objects. // Remove the first object from the stack of traversed objects.
aStack.pop(); aStack.pop();
bStack.pop(); bStack.pop();
return result; return true;
}; };
// Perform a deep comparison to check if two objects are equal. // Perform a deep comparison to check if two objects are equal.
_.isEqual = function(a, b) { _.isEqual = function(a, b) {
return eq(a, b, [], []); return eq(a, b);
}; };
// Is a given array, string, or object empty? // Is a given array, string, or object empty?
// An "empty" object has no enumerable own-properties. // An "empty" object has no enumerable own-properties.
_.isEmpty = function(obj) { _.isEmpty = function(obj) {
if (obj == null) return true; if (obj == null) return true;
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
for (var key in obj) if (_.has(obj, key)) return false; return _.keys(obj).length === 0;
return true;
}; };
// Is a given value a DOM element? // Is a given value a DOM element?
...@@ -12179,33 +12356,35 @@ define('text',['module'], function (module) { ...@@ -12179,33 +12356,35 @@ define('text',['module'], function (module) {
// Is a given value an array? // Is a given value an array?
// Delegates to ECMA5's native Array.isArray // Delegates to ECMA5's native Array.isArray
_.isArray = nativeIsArray || function(obj) { _.isArray = nativeIsArray || function(obj) {
return toString.call(obj) == '[object Array]'; return toString.call(obj) === '[object Array]';
}; };
// Is a given variable an object? // Is a given variable an object?
_.isObject = function(obj) { _.isObject = function(obj) {
return obj === Object(obj); var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
}; };
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
_['is' + name] = function(obj) { _['is' + name] = function(obj) {
return toString.call(obj) == '[object ' + name + ']'; return toString.call(obj) === '[object ' + name + ']';
}; };
}); });
// Define a fallback version of the method in browsers (ahem, IE), where // Define a fallback version of the method in browsers (ahem, IE < 9), where
// there isn't any inspectable "Arguments" type. // there isn't any inspectable "Arguments" type.
if (!_.isArguments(arguments)) { if (!_.isArguments(arguments)) {
_.isArguments = function(obj) { _.isArguments = function(obj) {
return !!(obj && _.has(obj, 'callee')); return _.has(obj, 'callee');
}; };
} }
// Optimize `isFunction` if appropriate. // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
if (typeof (/./) !== 'function') { // IE 11 (#1621), and in Safari 8 (#1929).
if (typeof /./ != 'function' && typeof Int8Array != 'object') {
_.isFunction = function(obj) { _.isFunction = function(obj) {
return typeof obj === 'function'; return typeof obj == 'function' || false;
}; };
} }
...@@ -12216,12 +12395,12 @@ define('text',['module'], function (module) { ...@@ -12216,12 +12395,12 @@ define('text',['module'], function (module) {
// Is the given value `NaN`? (NaN is the only number which does not equal itself). // Is the given value `NaN`? (NaN is the only number which does not equal itself).
_.isNaN = function(obj) { _.isNaN = function(obj) {
return _.isNumber(obj) && obj != +obj; return _.isNumber(obj) && obj !== +obj;
}; };
// Is a given value a boolean? // Is a given value a boolean?
_.isBoolean = function(obj) { _.isBoolean = function(obj) {
return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
}; };
// Is a given value equal to null? // Is a given value equal to null?
...@@ -12237,7 +12416,7 @@ define('text',['module'], function (module) { ...@@ -12237,7 +12416,7 @@ define('text',['module'], function (module) {
// Shortcut function for checking if an object has a given property directly // Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype). // on itself (in other words, not on a prototype).
_.has = function(obj, key) { _.has = function(obj, key) {
return hasOwnProperty.call(obj, key); return obj != null && hasOwnProperty.call(obj, key);
}; };
// Utility Functions // Utility Functions
...@@ -12250,39 +12429,47 @@ define('text',['module'], function (module) { ...@@ -12250,39 +12429,47 @@ define('text',['module'], function (module) {
return this; return this;
}; };
// Keep the identity function around for default iterators. // Keep the identity function around for default iteratees.
_.identity = function(value) { _.identity = function(value) {
return value; return value;
}; };
// Predicate-generating functions. Often useful outside of Underscore.
_.constant = function(value) { _.constant = function(value) {
return function () { return function() {
return value; return value;
}; };
}; };
_.noop = function(){};
_.property = function(key) { _.property = function(key) {
return function(obj) { return function(obj) {
return obj == null ? void 0 : obj[key];
};
};
// Generates a function for a given object that returns a given property.
_.propertyOf = function(obj) {
return obj == null ? function(){} : function(key) {
return obj[key]; return obj[key];
}; };
}; };
// Returns a predicate for checking whether an object has a given set of `key:value` pairs. // Returns a predicate for checking whether an object has a given set of
_.matches = function(attrs) { // `key:value` pairs.
_.matcher = _.matches = function(attrs) {
attrs = _.extendOwn({}, attrs);
return function(obj) { return function(obj) {
if (obj === attrs) return true; //avoid comparing an object to itself. return _.isMatch(obj, attrs);
for (var key in attrs) { };
if (attrs[key] !== obj[key])
return false;
}
return true;
}
}; };
// Run a function **n** times. // Run a function **n** times.
_.times = function(n, iterator, context) { _.times = function(n, iteratee, context) {
var accum = Array(Math.max(0, n)); var accum = Array(Math.max(0, n));
for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); iteratee = optimizeCb(iteratee, context, 1);
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
return accum; return accum;
}; };
...@@ -12296,56 +12483,48 @@ define('text',['module'], function (module) { ...@@ -12296,56 +12483,48 @@ define('text',['module'], function (module) {
}; };
// A (possibly faster) way to get the current timestamp as an integer. // A (possibly faster) way to get the current timestamp as an integer.
_.now = Date.now || function() { return new Date().getTime(); }; _.now = Date.now || function() {
return new Date().getTime();
};
// List of HTML entities for escaping. // List of HTML entities for escaping.
var entityMap = { var escapeMap = {
escape: {
'&': '&amp;', '&': '&amp;',
'<': '&lt;', '<': '&lt;',
'>': '&gt;', '>': '&gt;',
'"': '&quot;', '"': '&quot;',
"'": '&#x27;' "'": '&#x27;',
} '`': '&#x60;'
};
entityMap.unescape = _.invert(entityMap.escape);
// Regexes containing the keys and values listed immediately above.
var entityRegexes = {
escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
}; };
var unescapeMap = _.invert(escapeMap);
// Functions for escaping and unescaping strings to/from HTML interpolation. // Functions for escaping and unescaping strings to/from HTML interpolation.
_.each(['escape', 'unescape'], function(method) { var createEscaper = function(map) {
_[method] = function(string) { var escaper = function(match) {
if (string == null) return ''; return map[match];
return ('' + string).replace(entityRegexes[method], function(match) {
return entityMap[method][match];
});
}; };
}); // Regexes for identifying a key that needs to be escaped
var source = '(?:' + _.keys(map).join('|') + ')';
var testRegexp = RegExp(source);
var replaceRegexp = RegExp(source, 'g');
return function(string) {
string = string == null ? '' : '' + string;
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
};
};
_.escape = createEscaper(escapeMap);
_.unescape = createEscaper(unescapeMap);
// If the value of the named `property` is a function then invoke it with the // If the value of the named `property` is a function then invoke it with the
// `object` as context; otherwise, return it. // `object` as context; otherwise, return it.
_.result = function(object, property) { _.result = function(object, property, fallback) {
if (object == null) return void 0; var value = object == null ? void 0 : object[property];
var value = object[property]; if (value === void 0) {
value = fallback;
}
return _.isFunction(value) ? value.call(object) : value; return _.isFunction(value) ? value.call(object) : value;
}; };
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result.call(this, func.apply(_, args));
};
});
};
// Generate a unique integer id (unique within the entire client session). // Generate a unique integer id (unique within the entire client session).
// Useful for temporary DOM ids. // Useful for temporary DOM ids.
var idCounter = 0; var idCounter = 0;
...@@ -12374,22 +12553,26 @@ define('text',['module'], function (module) { ...@@ -12374,22 +12553,26 @@ define('text',['module'], function (module) {
'\\': '\\', '\\': '\\',
'\r': 'r', '\r': 'r',
'\n': 'n', '\n': 'n',
'\t': 't',
'\u2028': 'u2028', '\u2028': 'u2028',
'\u2029': 'u2029' '\u2029': 'u2029'
}; };
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function(match) {
return '\\' + escapes[match];
};
// JavaScript micro-templating, similar to John Resig's implementation. // JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace, // Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code. // and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) { // NB: `oldSettings` only exists for backwards compatibility.
var render; _.template = function(text, settings, oldSettings) {
if (!settings && oldSettings) settings = oldSettings;
settings = _.defaults({}, settings, _.templateSettings); settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation. // Combine delimiters into one regular expression via alternation.
var matcher = new RegExp([ var matcher = RegExp([
(settings.escape || noMatch).source, (settings.escape || noMatch).source,
(settings.interpolate || noMatch).source, (settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source (settings.evaluate || noMatch).source
...@@ -12399,19 +12582,18 @@ define('text',['module'], function (module) { ...@@ -12399,19 +12582,18 @@ define('text',['module'], function (module) {
var index = 0; var index = 0;
var source = "__p+='"; var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset) source += text.slice(index, offset).replace(escaper, escapeChar);
.replace(escaper, function(match) { return '\\' + escapes[match]; }); index = offset + match.length;
if (escape) { if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
} } else if (interpolate) {
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
} } else if (evaluate) {
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='"; source += "';\n" + evaluate + "\n__p+='";
} }
index = offset + match.length;
// Adobe VMs need the match returned to produce the correct offest.
return match; return match;
}); });
source += "';\n"; source += "';\n";
...@@ -12421,29 +12603,31 @@ define('text',['module'], function (module) { ...@@ -12421,29 +12603,31 @@ define('text',['module'], function (module) {
source = "var __t,__p='',__j=Array.prototype.join," + source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" + "print=function(){__p+=__j.call(arguments,'');};\n" +
source + "return __p;\n"; source + 'return __p;\n';
try { try {
render = new Function(settings.variable || 'obj', '_', source); var render = new Function(settings.variable || 'obj', '_', source);
} catch (e) { } catch (e) {
e.source = source; e.source = source;
throw e; throw e;
} }
if (data) return render(data, _);
var template = function(data) { var template = function(data) {
return render.call(this, data, _); return render.call(this, data, _);
}; };
// Provide the compiled function source as a convenience for precompilation. // Provide the compiled source as a convenience for precompilation.
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; var argument = settings.variable || 'obj';
template.source = 'function(' + argument + '){\n' + source + '}';
return template; return template;
}; };
// Add a "chain" function, which will delegate to the wrapper. // Add a "chain" function. Start chaining a wrapped Underscore object.
_.chain = function(obj) { _.chain = function(obj) {
return _(obj).chain(); var instance = _(obj);
instance._chain = true;
return instance;
}; };
// OOP // OOP
...@@ -12453,46 +12637,56 @@ define('text',['module'], function (module) { ...@@ -12453,46 +12637,56 @@ define('text',['module'], function (module) {
// underscore functions. Wrapped objects may be chained. // underscore functions. Wrapped objects may be chained.
// Helper function to continue chaining intermediate results. // Helper function to continue chaining intermediate results.
var result = function(obj) { var result = function(instance, obj) {
return this._chain ? _(obj).chain() : obj; return instance._chain ? _(obj).chain() : obj;
};
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result(this, func.apply(_, args));
};
});
}; };
// Add all of the Underscore functions to the wrapper object. // Add all of the Underscore functions to the wrapper object.
_.mixin(_); _.mixin(_);
// Add all mutator Array functions to the wrapper. // Add all mutator Array functions to the wrapper.
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
var method = ArrayProto[name]; var method = ArrayProto[name];
_.prototype[name] = function() { _.prototype[name] = function() {
var obj = this._wrapped; var obj = this._wrapped;
method.apply(obj, arguments); method.apply(obj, arguments);
if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
return result.call(this, obj); return result(this, obj);
}; };
}); });
// Add all accessor Array functions to the wrapper. // Add all accessor Array functions to the wrapper.
each(['concat', 'join', 'slice'], function(name) { _.each(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name]; var method = ArrayProto[name];
_.prototype[name] = function() { _.prototype[name] = function() {
return result.call(this, method.apply(this._wrapped, arguments)); return result(this, method.apply(this._wrapped, arguments));
}; };
}); });
_.extend(_.prototype, {
// Start chaining a wrapped Underscore object.
chain: function() {
this._chain = true;
return this;
},
// Extracts the result from a wrapped and chained object. // Extracts the result from a wrapped and chained object.
value: function() { _.prototype.value = function() {
return this._wrapped; return this._wrapped;
} };
}); // Provide unwrapping proxy for some methods used in engine operations
// such as arithmetic and JSON stringification.
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
_.prototype.toString = function() {
return '' + this._wrapped;
};
// AMD registration happens at the end for compatibility with AMD loaders // AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general // that may not enforce next-turn semantics on modules. Even though general
...@@ -12506,7 +12700,7 @@ define('text',['module'], function (module) { ...@@ -12506,7 +12700,7 @@ define('text',['module'], function (module) {
return _; return _;
}); });
} }
}).call(this); }.call(this));
// RequireJS UnderscoreJS template plugin // RequireJS UnderscoreJS template plugin
// http://github.com/jfparadis/requirejs-tpl // http://github.com/jfparadis/requirejs-tpl
...@@ -13031,7 +13225,7 @@ var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments ...@@ -13031,7 +13225,7 @@ var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments
with(obj||{}){ with(obj||{}){
__p+='<form id="converse-login" method="post">\n <label>'+ __p+='<form id="converse-login" method="post">\n <label>'+
((__t=(label_username))==null?'':__t)+ ((__t=(label_username))==null?'':__t)+
'</label>\n <input type="username" name="jid" placeholder="user@server">\n <label>'+ '</label>\n <input type="email" name="jid" placeholder="user@server">\n <label>'+
((__t=(label_password))==null?'':__t)+ ((__t=(label_password))==null?'':__t)+
'</label>\n <input type="password" name="password" placeholder="password">\n <input class="submit" type="submit" value="'+ '</label>\n <input type="password" name="password" placeholder="password">\n <input class="submit" type="submit" value="'+
((__t=(label_login))==null?'':__t)+ ((__t=(label_login))==null?'':__t)+
...@@ -13360,7 +13554,9 @@ __p+='<form class="add-chatroom" action="" method="post">\n <label>'+ ...@@ -13360,7 +13554,9 @@ __p+='<form class="add-chatroom" action="" method="post">\n <label>'+
((__t=(label_nickname))==null?'':__t)+ ((__t=(label_nickname))==null?'':__t)+
'</label>\n <input type="text" name="nick" class="new-chatroom-nick"\n placeholder="'+ '</label>\n <input type="text" name="nick" class="new-chatroom-nick"\n placeholder="'+
((__t=(label_nickname))==null?'':__t)+ ((__t=(label_nickname))==null?'':__t)+
'"/>\n <label>'+ '"/>\n <label'+
((__t=(server_label_global_attr))==null?'':__t)+
'>'+
((__t=(label_server))==null?'':__t)+ ((__t=(label_server))==null?'':__t)+
'</label>\n <input type="'+ '</label>\n <input type="'+
((__t=(server_input_type))==null?'':__t)+ ((__t=(server_input_type))==null?'':__t)+
...@@ -13406,9 +13602,13 @@ __p+='<a class="open-chat" title="Name: '+ ...@@ -13406,9 +13602,13 @@ __p+='<a class="open-chat" title="Name: '+
((__t=(desc_status))==null?'':__t)+ ((__t=(desc_status))==null?'':__t)+
'"></span>'+ '"></span>'+
((__t=(fullname))==null?'':__t)+ ((__t=(fullname))==null?'':__t)+
'</a>\n<a class="remove-xmpp-contact icon-remove" title="'+ '</a>\n';
if (allow_contact_removal) {
__p+='\n<a class="remove-xmpp-contact icon-remove" title="'+
((__t=(desc_remove))==null?'':__t)+ ((__t=(desc_remove))==null?'':__t)+
'" href="#"></a>\n'; '" href="#"></a>\n';
}
__p+='\n';
} }
return __p; return __p;
}; }); }; });
...@@ -26939,19 +27139,6 @@ define("converse-dependencies", [ ...@@ -26939,19 +27139,6 @@ define("converse-dependencies", [
return this; return this;
}; };
var playNotification = function () {
var audio;
if (converse.play_sounds && typeof Audio !== "undefined"){
audio = new Audio("sounds/msg_received.ogg");
if (audio.canPlayType('/audio/ogg')) {
audio.play();
} else {
audio = new Audio("/sounds/msg_received.mp3");
audio.play();
}
}
};
var converse = { var converse = {
plugins: {}, plugins: {},
templates: templates, templates: templates,
...@@ -27058,6 +27245,7 @@ define("converse-dependencies", [ ...@@ -27058,6 +27245,7 @@ define("converse-dependencies", [
// Default configuration values // Default configuration values
// ---------------------------- // ----------------------------
this.default_settings = { this.default_settings = {
allow_contact_removal: true,
allow_contact_requests: true, allow_contact_requests: true,
allow_dragresize: true, allow_dragresize: true,
allow_logout: true, allow_logout: true,
...@@ -27172,6 +27360,19 @@ define("converse-dependencies", [ ...@@ -27172,6 +27360,19 @@ define("converse-dependencies", [
// Module-level functions // Module-level functions
// ---------------------- // ----------------------
this.playNotification = function () {
var audio;
if (converse.play_sounds && typeof Audio !== "undefined"){
audio = new Audio("sounds/msg_received.ogg");
if (audio.canPlayType('/audio/ogg')) {
audio.play();
} else {
audio = new Audio("/sounds/msg_received.mp3");
audio.play();
}
}
};
this.giveFeedback = function (message, klass) { this.giveFeedback = function (message, klass) {
$('.conn-feedback').each(function (idx, el) { $('.conn-feedback').each(function (idx, el) {
var $el = $(el); var $el = $(el);
...@@ -27244,7 +27445,6 @@ define("converse-dependencies", [ ...@@ -27244,7 +27445,6 @@ define("converse-dependencies", [
this.reconnect = function () { this.reconnect = function () {
converse.giveFeedback(__('Reconnecting'), 'error'); converse.giveFeedback(__('Reconnecting'), 'error');
converse.emit('reconnect');
if (!converse.prebind) { if (!converse.prebind) {
this.connection.connect( this.connection.connect(
this.connection.jid, this.connection.jid,
...@@ -27256,6 +27456,10 @@ define("converse-dependencies", [ ...@@ -27256,6 +27456,10 @@ define("converse-dependencies", [
this.connection.hold, this.connection.hold,
this.connection.route this.connection.route
); );
} else if (converse.prebind_url) {
this.clearSession();
this._tearDown();
this.startNewBOSHSession();
} }
}; };
...@@ -27292,6 +27496,7 @@ define("converse-dependencies", [ ...@@ -27292,6 +27496,7 @@ define("converse-dependencies", [
converse.giveFeedback(__('Authentication Failed'), 'error'); converse.giveFeedback(__('Authentication Failed'), 'error');
converse.connection.disconnect(__('Authentication Failed')); converse.connection.disconnect(__('Authentication Failed'));
} else if (status === Strophe.Status.DISCONNECTING) { } else if (status === Strophe.Status.DISCONNECTING) {
// FIXME: what about prebind?
if (!converse.connection.connected) { if (!converse.connection.connected) {
converse.renderLoginPanel(); converse.renderLoginPanel();
} }
...@@ -27367,8 +27572,8 @@ define("converse-dependencies", [ ...@@ -27367,8 +27572,8 @@ define("converse-dependencies", [
this.clearSession = function () { this.clearSession = function () {
this.roster.browserStorage._clear(); this.roster.browserStorage._clear();
this.session.browserStorage._clear(); this.session.browserStorage._clear();
// XXX: this should perhaps go into the beforeunload handler var controlbox = converse.chatboxes.get('controlbox');
converse.chatboxes.get('controlbox').save({'connected': false}); controlbox.save({'connected': false});
}; };
this.setSession = function () { this.setSession = function () {
...@@ -28573,6 +28778,7 @@ define("converse-dependencies", [ ...@@ -28573,6 +28778,7 @@ define("converse-dependencies", [
this.$el.html( this.$el.html(
converse.templates.room_panel({ converse.templates.room_panel({
'server_input_type': converse.hide_muc_server && 'hidden' || 'text', 'server_input_type': converse.hide_muc_server && 'hidden' || 'text',
'server_label_global_attr': converse.hide_muc_server && ' hidden' || '',
'label_room_name': __('Room name'), 'label_room_name': __('Room name'),
'label_nickname': __('Nickname'), 'label_nickname': __('Nickname'),
'label_server': __('Server'), 'label_server': __('Server'),
...@@ -29785,7 +29991,7 @@ define("converse-dependencies", [ ...@@ -29785,7 +29991,7 @@ define("converse-dependencies", [
} }
this.model.createMessage($message); this.model.createMessage($message);
if (!delayed && sender !== this.model.get('nick') && (new RegExp("\\b"+this.model.get('nick')+"\\b")).test(body)) { if (!delayed && sender !== this.model.get('nick') && (new RegExp("\\b"+this.model.get('nick')+"\\b")).test(body)) {
playNotification(); converse.playNotification();
} }
if (sender !== this.model.get('nick')) { if (sender !== this.model.get('nick')) {
// We only emit an event if it's not our own message // We only emit an event if it's not our own message
...@@ -29955,7 +30161,7 @@ define("converse-dependencies", [ ...@@ -29955,7 +30161,7 @@ define("converse-dependencies", [
return true; // We already have this message stored. return true; // We already have this message stored.
} }
if (!this.isOnlyChatStateNotification($message) && from !== converse.bare_jid) { if (!this.isOnlyChatStateNotification($message) && from !== converse.bare_jid) {
playNotification(); converse.playNotification();
} }
chatbox.receiveMessage($message); chatbox.receiveMessage($message);
converse.roster.addResource(contact_jid, resource); converse.roster.addResource(contact_jid, resource);
...@@ -30386,7 +30592,8 @@ define("converse-dependencies", [ ...@@ -30386,7 +30592,8 @@ define("converse-dependencies", [
_.extend(item.toJSON(), { _.extend(item.toJSON(), {
'desc_status': STATUSES[chat_status||'offline'], 'desc_status': STATUSES[chat_status||'offline'],
'desc_chat': __('Click to chat with this contact'), 'desc_chat': __('Click to chat with this contact'),
'desc_remove': __('Click to remove this contact') 'desc_remove': __('Click to remove this contact'),
'allow_contact_removal': converse.allow_contact_removal
}) })
)); ));
} }
...@@ -30400,6 +30607,7 @@ define("converse-dependencies", [ ...@@ -30400,6 +30607,7 @@ define("converse-dependencies", [
removeContact: function (ev) { removeContact: function (ev) {
if (ev && ev.preventDefault) { ev.preventDefault(); } if (ev && ev.preventDefault) { ev.preventDefault(); }
if (!converse.allow_contact_removal) { return; }
var result = confirm(__("Are you sure you want to remove this contact?")); var result = confirm(__("Are you sure you want to remove this contact?"));
if (result === true) { if (result === true) {
var bare_jid = this.model.get('jid'); var bare_jid = this.model.get('jid');
...@@ -32100,20 +32308,32 @@ define("converse-dependencies", [ ...@@ -32100,20 +32308,32 @@ define("converse-dependencies", [
} }
}; };
this.startNewBOSHSession = function () {
$.ajax({
url: this.prebind_url,
type: 'GET',
success: function (response) {
this.session.save({rid: response.rid});
this.connection.attach(
response.jid,
response.sid,
response.rid,
this.onConnect
);
}.bind(this),
error: function (response) {
delete this.connection;
this.emit('noResumeableSession');
}.bind(this)
});
};
this.initConnection = function () { this.initConnection = function () {
var rid, sid, jid; var rid, sid, jid;
if (this.connection && this.connection.connected) { if (this.connection && this.connection.connected) {
this.setUpXMLLogging(); this.setUpXMLLogging();
this.onConnected(); this.onConnected();
} else { } else {
// XXX: it's not yet clear what the order of preference should
// be between RID and SID received via the initialize method or
// those received from sessionStorage.
//
// What do you we if we receive values from both avenues?
//
// Also, what do we do when the keepalive session values are
// expired? Do we try to fall back?
if (!this.bosh_service_url && ! this.websocket_url) { if (!this.bosh_service_url && ! this.websocket_url) {
throw("Error: you must supply a value for the bosh_service_url or websocket_url"); throw("Error: you must supply a value for the bosh_service_url or websocket_url");
} }
...@@ -32139,33 +32359,25 @@ define("converse-dependencies", [ ...@@ -32139,33 +32359,25 @@ define("converse-dependencies", [
rid = this.session.get('rid'); rid = this.session.get('rid');
sid = this.session.get('sid'); sid = this.session.get('sid');
jid = this.session.get('jid'); jid = this.session.get('jid');
if (rid && jid && sid) { if (this.prebind) {
// The RID needs to be increased with each request. if (!this.jid) {
this.session.save({rid: rid}); throw("When using 'keepalive' with 'prebind, you must supply the JID of the current user.");
}
if (rid && sid && jid && Strophe.getBareJidFromJid(jid) === Strophe.getBareJidFromJid(this.jid)) {
this.session.save({rid: rid}); // The RID needs to be increased with each request.
this.connection.attach(jid, sid, rid, this.onConnect); this.connection.attach(jid, sid, rid, this.onConnect);
} else if (this.prebind) { } else if (this.prebind_url) {
if (this.prebind_url) { this.startNewBOSHSession();
$.ajax({
url: this.prebind_url,
type: 'GET',
success: function (response) {
this.session.save({rid: rid});
this.connection.attach(
response.jid,
response.sid,
response.rid,
this.onConnect
);
}.bind(this),
error: function (response) {
delete this.connection;
this.emit('noResumeableSession');
}.bind(this)
});
} else { } else {
delete this.connection; delete this.connection;
this.emit('noResumeableSession'); this.emit('noResumeableSession');
} }
} else {
// Non-prebind case.
if (rid && sid && jid) {
this.session.save({rid: rid}); // The RID needs to be increased with each request.
this.connection.attach(jid, sid, rid, this.onConnect);
}
} }
} }
} }
...@@ -32245,6 +32457,14 @@ define("converse-dependencies", [ ...@@ -32245,6 +32457,14 @@ define("converse-dependencies", [
'initialize': function (settings, callback) { 'initialize': function (settings, callback) {
converse.initialize(settings, callback); converse.initialize(settings, callback);
}, },
'disconnect': function () {
converse.connection.disconnect();
},
'account': {
'logout': function () {
converse.logOut();
},
},
'settings': { 'settings': {
'get': function (key) { 'get': function (key) {
if (_.contains(Object.keys(converse.default_settings), key)) { if (_.contains(Object.keys(converse.default_settings), key)) {
...@@ -32550,7 +32770,6 @@ require.config({ ...@@ -32550,7 +32770,6 @@ require.config({
// define module dependencies for modules not using define // define module dependencies for modules not using define
shim: { shim: {
'underscore': { exports: '_' },
'crypto.aes': { deps: ['crypto.cipher-core'] }, 'crypto.aes': { deps: ['crypto.cipher-core'] },
'crypto.cipher-core': { deps: ['crypto.enc-base64', 'crypto.evpkdf'] }, 'crypto.cipher-core': { deps: ['crypto.enc-base64', 'crypto.evpkdf'] },
'crypto.enc-base64': { deps: ['crypto.core'] }, 'crypto.enc-base64': { deps: ['crypto.core'] },
This source diff could not be displayed because it is too large. You can view the blob instead.
/** /**
* @license almond 0.3.0 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license. * Available via the MIT or new BSD license.
* see: http://github.com/jrburke/almond for details * see: http://github.com/jrburke/almond for details
*/ */
...@@ -44,12 +44,6 @@ var requirejs, require, define; ...@@ -44,12 +44,6 @@ var requirejs, require, define;
//otherwise, assume it is a top-level require that will //otherwise, assume it is a top-level require that will
//be relative to baseUrl in the end. //be relative to baseUrl in the end.
if (baseName) { 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('/'); name = name.split('/');
lastIndex = name.length - 1; lastIndex = name.length - 1;
...@@ -58,7 +52,11 @@ var requirejs, require, define; ...@@ -58,7 +52,11 @@ var requirejs, require, define;
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
} }
name = baseParts.concat(name); //Lop off the last part of baseParts, so that . matches the
//"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.
name = baseParts.slice(0, baseParts.length - 1).concat(name);
//start trimDots //start trimDots
for (i = 0; i < name.length; i += 1) { for (i = 0; i < name.length; i += 1) {
...@@ -408,6 +406,9 @@ var requirejs, require, define; ...@@ -408,6 +406,9 @@ var requirejs, require, define;
requirejs._defined = defined; requirejs._defined = defined;
define = function (name, deps, callback) { define = function (name, deps, callback) {
if (typeof name !== 'string') {
throw new Error('See almond README: incorrect module build, no module name');
}
//This module may not have dependencies //This module may not have dependencies
if (!deps.splice) { if (!deps.splice) {
...@@ -11164,9 +11165,9 @@ define('text',['module'], function (module) { ...@@ -11164,9 +11165,9 @@ define('text',['module'], function (module) {
return text; return text;
}); });
// Underscore.js 1.6.0 // Underscore.js 1.8.2
// http://underscorejs.org // http://underscorejs.org
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license. // Underscore may be freely distributed under the MIT license.
(function() { (function() {
...@@ -11180,9 +11181,6 @@ define('text',['module'], function (module) { ...@@ -11180,9 +11181,6 @@ define('text',['module'], function (module) {
// Save the previous value of the `_` variable. // Save the previous value of the `_` variable.
var previousUnderscore = root._; var previousUnderscore = root._;
// Establish the object that gets returned to break out of a loop iteration.
var breaker = {};
// Save bytes in the minified (but not gzipped) version: // Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
...@@ -11190,25 +11188,19 @@ define('text',['module'], function (module) { ...@@ -11190,25 +11188,19 @@ define('text',['module'], function (module) {
var var
push = ArrayProto.push, push = ArrayProto.push,
slice = ArrayProto.slice, slice = ArrayProto.slice,
concat = ArrayProto.concat,
toString = ObjProto.toString, toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty; hasOwnProperty = ObjProto.hasOwnProperty;
// All **ECMAScript 5** native function implementations that we hope to use // All **ECMAScript 5** native function implementations that we hope to use
// are declared here. // are declared here.
var 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, nativeIsArray = Array.isArray,
nativeKeys = Object.keys, nativeKeys = Object.keys,
nativeBind = FuncProto.bind; nativeBind = FuncProto.bind,
nativeCreate = Object.create;
// Naked function reference for surrogate-prototype-swapping.
var Ctor = function(){};
// Create a safe reference to the Underscore object for use below. // Create a safe reference to the Underscore object for use below.
var _ = function(obj) { var _ = function(obj) {
...@@ -11219,8 +11211,7 @@ define('text',['module'], function (module) { ...@@ -11219,8 +11211,7 @@ define('text',['module'], function (module) {
// Export the Underscore object for **Node.js**, with // Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in // backwards-compatibility for the old `require()` API. If we're in
// the browser, add `_` as a global object via a string identifier, // the browser, add `_` as a global object.
// for Closure Compiler "advanced" mode.
if (typeof exports !== 'undefined') { if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) { if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _; exports = module.exports = _;
...@@ -11231,161 +11222,208 @@ define('text',['module'], function (module) { ...@@ -11231,161 +11222,208 @@ define('text',['module'], function (module) {
} }
// Current version. // Current version.
_.VERSION = '1.6.0'; _.VERSION = '1.8.2';
// Internal function that returns an efficient (for current engines) version
// of the passed-in callback, to be repeatedly applied in other Underscore
// functions.
var optimizeCb = function(func, context, argCount) {
if (context === void 0) return func;
switch (argCount == null ? 3 : argCount) {
case 1: return function(value) {
return func.call(context, value);
};
case 2: return function(value, other) {
return func.call(context, value, other);
};
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
};
// A mostly-internal function to generate callbacks that can be applied
// to each element in a collection, returning the desired result — either
// identity, an arbitrary callback, a property matcher, or a property accessor.
var cb = function(value, context, argCount) {
if (value == null) return _.identity;
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
if (_.isObject(value)) return _.matcher(value);
return _.property(value);
};
_.iteratee = function(value, context) {
return cb(value, context, Infinity);
};
// An internal function for creating assigner functions.
var createAssigner = function(keysFunc, undefinedOnly) {
return function(obj) {
var length = arguments.length;
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
};
// An internal function for creating a new object that inherits from another.
var baseCreate = function(prototype) {
if (!_.isObject(prototype)) return {};
if (nativeCreate) return nativeCreate(prototype);
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
// Helper for collection methods to determine whether a collection
// should be iterated as an array or as an object
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var isArrayLike = function(collection) {
var length = collection && collection.length;
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
// Collection Functions // Collection Functions
// -------------------- // --------------------
// The cornerstone, an `each` implementation, aka `forEach`. // The cornerstone, an `each` implementation, aka `forEach`.
// Handles objects with the built-in `forEach`, arrays, and raw objects. // Handles raw objects in addition to array-likes. Treats all
// Delegates to **ECMAScript 5**'s native `forEach` if available. // sparse array-likes as if they were dense.
var each = _.each = _.forEach = function(obj, iterator, context) { _.each = _.forEach = function(obj, iteratee, context) {
if (obj == null) return obj; iteratee = optimizeCb(iteratee, context);
if (nativeForEach && obj.forEach === nativeForEach) { var i, length;
obj.forEach(iterator, context); if (isArrayLike(obj)) {
} else if (obj.length === +obj.length) { for (i = 0, length = obj.length; i < length; i++) {
for (var i = 0, length = obj.length; i < length; i++) { iteratee(obj[i], i, obj);
if (iterator.call(context, obj[i], i, obj) === breaker) return;
} }
} else { } else {
var keys = _.keys(obj); var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) { for (i = 0, length = keys.length; i < length; i++) {
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; iteratee(obj[keys[i]], keys[i], obj);
} }
} }
return obj; return obj;
}; };
// Return the results of applying the iterator to each element. // Return the results of applying the iteratee to each element.
// Delegates to **ECMAScript 5**'s native `map` if available. _.map = _.collect = function(obj, iteratee, context) {
_.map = _.collect = function(obj, iterator, context) { iteratee = cb(iteratee, context);
var results = []; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return results; length = (keys || obj).length,
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); results = Array(length);
each(obj, function(value, index, list) { for (var index = 0; index < length; index++) {
results.push(iterator.call(context, value, index, list)); var currentKey = keys ? keys[index] : index;
}); results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results; return results;
}; };
var reduceError = 'Reduce of empty array with no initial value'; // Create a reducing function iterating left or right.
function createReduce(dir) {
// **Reduce** builds up a single result from a list of values, aka `inject`, // Optimized iterator function as using arguments.length
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. // in the main function will deoptimize the, see #1991.
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { function iterator(obj, iteratee, memo, keys, index, length) {
var initial = arguments.length > 2; for (; index >= 0 && index < length; index += dir) {
if (obj == null) obj = []; var currentKey = keys ? keys[index] : index;
if (nativeReduce && obj.reduce === nativeReduce) { memo = iteratee(memo, obj[currentKey], currentKey, obj);
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
}
each(obj, function(value, index, list) {
if (!initial) {
memo = value;
initial = true;
} else {
memo = iterator.call(context, memo, value, index, list);
} }
});
if (!initial) throw new TypeError(reduceError);
return memo; return memo;
};
// The right-associative version of reduce, also known as `foldr`.
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
var initial = arguments.length > 2;
if (obj == null) obj = [];
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
}
var length = obj.length;
if (length !== +length) {
var keys = _.keys(obj);
length = keys.length;
} }
each(obj, function(value, index, list) {
index = keys ? keys[--length] : --length; return function(obj, iteratee, memo, context) {
if (!initial) { iteratee = optimizeCb(iteratee, context, 4);
memo = obj[index]; var keys = !isArrayLike(obj) && _.keys(obj),
initial = true; length = (keys || obj).length,
} else { index = dir > 0 ? 0 : length - 1;
memo = iterator.call(context, memo, obj[index], index, list); // Determine the initial value if none is provided.
if (arguments.length < 3) {
memo = obj[keys ? keys[index] : index];
index += dir;
} }
}); return iterator(obj, iteratee, memo, keys, index, length);
if (!initial) throw new TypeError(reduceError);
return memo;
}; };
}
// **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`.
_.reduce = _.foldl = _.inject = createReduce(1);
// The right-associative version of reduce, also known as `foldr`.
_.reduceRight = _.foldr = createReduce(-1);
// Return the first value which passes a truth test. Aliased as `detect`. // Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function(obj, predicate, context) { _.find = _.detect = function(obj, predicate, context) {
var result; var key;
any(obj, function(value, index, list) { if (isArrayLike(obj)) {
if (predicate.call(context, value, index, list)) { key = _.findIndex(obj, predicate, context);
result = value; } else {
return true; key = _.findKey(obj, predicate, context);
} }
}); if (key !== void 0 && key !== -1) return obj[key];
return result;
}; };
// Return all the elements that pass a truth test. // Return all the elements that pass a truth test.
// Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`. // Aliased as `select`.
_.filter = _.select = function(obj, predicate, context) { _.filter = _.select = function(obj, predicate, context) {
var results = []; var results = [];
if (obj == null) return results; predicate = cb(predicate, context);
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); _.each(obj, function(value, index, list) {
each(obj, function(value, index, list) { if (predicate(value, index, list)) results.push(value);
if (predicate.call(context, value, index, list)) results.push(value);
}); });
return results; return results;
}; };
// Return all the elements for which a truth test fails. // Return all the elements for which a truth test fails.
_.reject = function(obj, predicate, context) { _.reject = function(obj, predicate, context) {
return _.filter(obj, function(value, index, list) { return _.filter(obj, _.negate(cb(predicate)), context);
return !predicate.call(context, value, index, list);
}, context);
}; };
// Determine whether all of the elements match a truth test. // Determine whether all of the elements match a truth test.
// Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`. // Aliased as `all`.
_.every = _.all = function(obj, predicate, context) { _.every = _.all = function(obj, predicate, context) {
predicate || (predicate = _.identity); predicate = cb(predicate, context);
var result = true; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return result; length = (keys || obj).length;
if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); for (var index = 0; index < length; index++) {
each(obj, function(value, index, list) { var currentKey = keys ? keys[index] : index;
if (!(result = result && predicate.call(context, value, index, list))) return breaker; if (!predicate(obj[currentKey], currentKey, obj)) return false;
}); }
return !!result; return true;
}; };
// Determine if at least one element in the object matches a truth test. // Determine if at least one element in the object matches a truth test.
// Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`. // Aliased as `any`.
var any = _.some = _.any = function(obj, predicate, context) { _.some = _.any = function(obj, predicate, context) {
predicate || (predicate = _.identity); predicate = cb(predicate, context);
var result = false; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return result; length = (keys || obj).length;
if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); for (var index = 0; index < length; index++) {
each(obj, function(value, index, list) { var currentKey = keys ? keys[index] : index;
if (result || (result = predicate.call(context, value, index, list))) return breaker; if (predicate(obj[currentKey], currentKey, obj)) return true;
}); }
return !!result; return false;
}; };
// Determine if the array or object contains a given value (using `===`). // Determine if the array or object contains a given value (using `===`).
// Aliased as `include`. // Aliased as `includes` and `include`.
_.contains = _.include = function(obj, target) { _.contains = _.includes = _.include = function(obj, target, fromIndex) {
if (obj == null) return false; if (!isArrayLike(obj)) obj = _.values(obj);
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; return _.indexOf(obj, target, typeof fromIndex == 'number' && fromIndex) >= 0;
return any(obj, function(value) {
return value === target;
});
}; };
// Invoke a method (with arguments) on every item in a collection. // Invoke a method (with arguments) on every item in a collection.
...@@ -11393,7 +11431,8 @@ define('text',['module'], function (module) { ...@@ -11393,7 +11431,8 @@ define('text',['module'], function (module) {
var args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
var isFunc = _.isFunction(method); var isFunc = _.isFunction(method);
return _.map(obj, function(value) { return _.map(obj, function(value) {
return (isFunc ? method : value[method]).apply(value, args); var func = isFunc ? method : value[method];
return func == null ? func : func.apply(value, args);
}); });
}; };
...@@ -11405,60 +11444,76 @@ define('text',['module'], function (module) { ...@@ -11405,60 +11444,76 @@ define('text',['module'], function (module) {
// Convenience version of a common use case of `filter`: selecting only objects // Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs. // containing specific `key:value` pairs.
_.where = function(obj, attrs) { _.where = function(obj, attrs) {
return _.filter(obj, _.matches(attrs)); return _.filter(obj, _.matcher(attrs));
}; };
// Convenience version of a common use case of `find`: getting the first object // Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs. // containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) { _.findWhere = function(obj, attrs) {
return _.find(obj, _.matches(attrs)); return _.find(obj, _.matcher(attrs));
}; };
// Return the maximum element or (element-based computation). // Return the maximum element (or element-based computation).
// Can't optimize arrays of integers longer than 65,535 elements. _.max = function(obj, iteratee, context) {
// See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) var result = -Infinity, lastComputed = -Infinity,
_.max = function(obj, iterator, context) { value, computed;
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { if (iteratee == null && obj != null) {
return Math.max.apply(Math, obj); obj = isArrayLike(obj) ? obj : _.values(obj);
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value > result) {
result = value;
}
} }
var result = -Infinity, lastComputed = -Infinity; } else {
each(obj, function(value, index, list) { iteratee = cb(iteratee, context);
var computed = iterator ? iterator.call(context, value, index, list) : value; _.each(obj, function(value, index, list) {
if (computed > lastComputed) { computed = iteratee(value, index, list);
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
result = value; result = value;
lastComputed = computed; lastComputed = computed;
} }
}); });
}
return result; return result;
}; };
// Return the minimum element (or element-based computation). // Return the minimum element (or element-based computation).
_.min = function(obj, iterator, context) { _.min = function(obj, iteratee, context) {
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { var result = Infinity, lastComputed = Infinity,
return Math.min.apply(Math, obj); value, computed;
} if (iteratee == null && obj != null) {
var result = Infinity, lastComputed = Infinity; obj = isArrayLike(obj) ? obj : _.values(obj);
each(obj, function(value, index, list) { for (var i = 0, length = obj.length; i < length; i++) {
var computed = iterator ? iterator.call(context, value, index, list) : value; value = obj[i];
if (computed < lastComputed) { if (value < result) {
result = value;
}
}
} else {
iteratee = cb(iteratee, context);
_.each(obj, function(value, index, list) {
computed = iteratee(value, index, list);
if (computed < lastComputed || computed === Infinity && result === Infinity) {
result = value; result = value;
lastComputed = computed; lastComputed = computed;
} }
}); });
}
return result; return result;
}; };
// Shuffle an array, using the modern version of the // Shuffle a collection, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_.shuffle = function(obj) { _.shuffle = function(obj) {
var rand; var set = isArrayLike(obj) ? obj : _.values(obj);
var index = 0; var length = set.length;
var shuffled = []; var shuffled = Array(length);
each(obj, function(value) { for (var index = 0, rand; index < length; index++) {
rand = _.random(index++); rand = _.random(0, index);
shuffled[index - 1] = shuffled[rand]; if (rand !== index) shuffled[index] = shuffled[rand];
shuffled[rand] = value; shuffled[rand] = set[index];
}); }
return shuffled; return shuffled;
}; };
...@@ -11467,27 +11522,20 @@ define('text',['module'], function (module) { ...@@ -11467,27 +11522,20 @@ define('text',['module'], function (module) {
// The internal `guard` argument allows it to work with `map`. // The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) { _.sample = function(obj, n, guard) {
if (n == null || guard) { if (n == null || guard) {
if (obj.length !== +obj.length) obj = _.values(obj); if (!isArrayLike(obj)) obj = _.values(obj);
return obj[_.random(obj.length - 1)]; return obj[_.random(obj.length - 1)];
} }
return _.shuffle(obj).slice(0, Math.max(0, n)); return _.shuffle(obj).slice(0, Math.max(0, n));
}; };
// An internal function to generate lookup iterators. // Sort the object's values by a criterion produced by an iteratee.
var lookupIterator = function(value) { _.sortBy = function(obj, iteratee, context) {
if (value == null) return _.identity; iteratee = cb(iteratee, context);
if (_.isFunction(value)) return value;
return _.property(value);
};
// Sort the object's values by a criterion produced by an iterator.
_.sortBy = function(obj, iterator, context) {
iterator = lookupIterator(iterator);
return _.pluck(_.map(obj, function(value, index, list) { return _.pluck(_.map(obj, function(value, index, list) {
return { return {
value: value, value: value,
index: index, index: index,
criteria: iterator.call(context, value, index, list) criteria: iteratee(value, index, list)
}; };
}).sort(function(left, right) { }).sort(function(left, right) {
var a = left.criteria; var a = left.criteria;
...@@ -11502,12 +11550,12 @@ define('text',['module'], function (module) { ...@@ -11502,12 +11550,12 @@ define('text',['module'], function (module) {
// An internal function used for aggregate "group by" operations. // An internal function used for aggregate "group by" operations.
var group = function(behavior) { var group = function(behavior) {
return function(obj, iterator, context) { return function(obj, iteratee, context) {
var result = {}; var result = {};
iterator = lookupIterator(iterator); iteratee = cb(iteratee, context);
each(obj, function(value, index) { _.each(obj, function(value, index) {
var key = iterator.call(context, value, index, obj); var key = iteratee(value, index, obj);
behavior(result, key, value); behavior(result, value, key);
}); });
return result; return result;
}; };
...@@ -11515,48 +11563,46 @@ define('text',['module'], function (module) { ...@@ -11515,48 +11563,46 @@ define('text',['module'], function (module) {
// Groups the object's values by a criterion. Pass either a string attribute // Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion. // to group by, or a function that returns the criterion.
_.groupBy = group(function(result, key, value) { _.groupBy = group(function(result, value, key) {
_.has(result, key) ? result[key].push(value) : result[key] = [value]; if (_.has(result, key)) result[key].push(value); else result[key] = [value];
}); });
// Indexes the object's values by a criterion, similar to `groupBy`, but for // Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique. // when you know that your index values will be unique.
_.indexBy = group(function(result, key, value) { _.indexBy = group(function(result, value, key) {
result[key] = value; result[key] = value;
}); });
// Counts instances of an object that group by a certain criterion. Pass // Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the // either a string attribute to count by, or a function that returns the
// criterion. // criterion.
_.countBy = group(function(result, key) { _.countBy = group(function(result, value, key) {
_.has(result, key) ? result[key]++ : result[key] = 1; if (_.has(result, key)) result[key]++; else result[key] = 1;
}); });
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iterator, context) {
iterator = lookupIterator(iterator);
var value = iterator.call(context, obj);
var low = 0, high = array.length;
while (low < high) {
var mid = (low + high) >>> 1;
iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
}
return low;
};
// Safely create a real, live array from anything iterable. // Safely create a real, live array from anything iterable.
_.toArray = function(obj) { _.toArray = function(obj) {
if (!obj) return []; if (!obj) return [];
if (_.isArray(obj)) return slice.call(obj); if (_.isArray(obj)) return slice.call(obj);
if (obj.length === +obj.length) return _.map(obj, _.identity); if (isArrayLike(obj)) return _.map(obj, _.identity);
return _.values(obj); return _.values(obj);
}; };
// Return the number of elements in an object. // Return the number of elements in an object.
_.size = function(obj) { _.size = function(obj) {
if (obj == null) return 0; if (obj == null) return 0;
return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; return isArrayLike(obj) ? obj.length : _.keys(obj).length;
};
// Split a collection into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(obj, predicate, context) {
predicate = cb(predicate, context);
var pass = [], fail = [];
_.each(obj, function(value, key, obj) {
(predicate(value, key, obj) ? pass : fail).push(value);
});
return [pass, fail];
}; };
// Array Functions // Array Functions
...@@ -11567,33 +11613,30 @@ define('text',['module'], function (module) { ...@@ -11567,33 +11613,30 @@ define('text',['module'], function (module) {
// allows it to work with `_.map`. // allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) { _.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0; if (array == null) return void 0;
if ((n == null) || guard) return array[0]; if (n == null || guard) return array[0];
if (n < 0) return []; return _.initial(array, array.length - n);
return slice.call(array, 0, n);
}; };
// Returns everything but the last entry of the array. Especially useful on // Returns everything but the last entry of the array. Especially useful on
// the arguments object. Passing **n** will return all the values in // the arguments object. Passing **n** will return all the values in
// the array, excluding the last N. The **guard** check allows it to work with // the array, excluding the last N.
// `_.map`.
_.initial = function(array, n, guard) { _.initial = function(array, n, guard) {
return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
}; };
// Get the last element of an array. Passing **n** will return the last N // Get the last element of an array. Passing **n** will return the last N
// values in the array. The **guard** check allows it to work with `_.map`. // values in the array.
_.last = function(array, n, guard) { _.last = function(array, n, guard) {
if (array == null) return void 0; if (array == null) return void 0;
if ((n == null) || guard) return array[array.length - 1]; if (n == null || guard) return array[array.length - 1];
return slice.call(array, Math.max(array.length - n, 0)); return _.rest(array, Math.max(0, array.length - n));
}; };
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`. // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
// Especially useful on the arguments object. Passing an **n** will return // Especially useful on the arguments object. Passing an **n** will return
// the rest N values in the array. The **guard** // the rest N values in the array.
// check allows it to work with `_.map`.
_.rest = _.tail = _.drop = function(array, n, guard) { _.rest = _.tail = _.drop = function(array, n, guard) {
return slice.call(array, (n == null) || guard ? 1 : n); return slice.call(array, n == null || guard ? 1 : n);
}; };
// Trim out all falsy values from an array. // Trim out all falsy values from an array.
...@@ -11602,23 +11645,28 @@ define('text',['module'], function (module) { ...@@ -11602,23 +11645,28 @@ define('text',['module'], function (module) {
}; };
// Internal implementation of a recursive `flatten` function. // Internal implementation of a recursive `flatten` function.
var flatten = function(input, shallow, output) { var flatten = function(input, shallow, strict, startIndex) {
if (shallow && _.every(input, _.isArray)) { var output = [], idx = 0;
return concat.apply(output, input); for (var i = startIndex || 0, length = input && input.length; i < length; i++) {
var value = input[i];
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
//flatten current level of array or arguments object
if (!shallow) value = flatten(value, shallow, strict);
var j = 0, len = value.length;
output.length += len;
while (j < len) {
output[idx++] = value[j++];
}
} else if (!strict) {
output[idx++] = value;
} }
each(input, function(value) {
if (_.isArray(value) || _.isArguments(value)) {
shallow ? push.apply(output, value) : flatten(value, shallow, output);
} else {
output.push(value);
} }
});
return output; return output;
}; };
// Flatten out an array, either recursively (by default), or just one level. // Flatten out an array, either recursively (by default), or just one level.
_.flatten = function(array, shallow) { _.flatten = function(array, shallow) {
return flatten(array, shallow, []); return flatten(array, shallow, false);
}; };
// Return a version of the array that does not contain the specified value(s). // Return a version of the array that does not contain the specified value(s).
...@@ -11626,79 +11674,93 @@ define('text',['module'], function (module) { ...@@ -11626,79 +11674,93 @@ define('text',['module'], function (module) {
return _.difference(array, slice.call(arguments, 1)); return _.difference(array, slice.call(arguments, 1));
}; };
// Split an array into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(array, predicate) {
var pass = [], fail = [];
each(array, function(elem) {
(predicate(elem) ? pass : fail).push(elem);
});
return [pass, fail];
};
// Produce a duplicate-free version of the array. If the array has already // Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm. // been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`. // Aliased as `unique`.
_.uniq = _.unique = function(array, isSorted, iterator, context) { _.uniq = _.unique = function(array, isSorted, iteratee, context) {
if (_.isFunction(isSorted)) { if (array == null) return [];
context = iterator; if (!_.isBoolean(isSorted)) {
iterator = isSorted; context = iteratee;
iteratee = isSorted;
isSorted = false; isSorted = false;
} }
var initial = iterator ? _.map(array, iterator, context) : array; if (iteratee != null) iteratee = cb(iteratee, context);
var results = []; var result = [];
var seen = []; var seen = [];
each(initial, function(value, index) { for (var i = 0, length = array.length; i < length; i++) {
if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { var value = array[i],
seen.push(value); computed = iteratee ? iteratee(value, i, array) : value;
results.push(array[index]); if (isSorted) {
if (!i || seen !== computed) result.push(value);
seen = computed;
} else if (iteratee) {
if (!_.contains(seen, computed)) {
seen.push(computed);
result.push(value);
} }
}); } else if (!_.contains(result, value)) {
return results; result.push(value);
}
}
return result;
}; };
// Produce an array that contains the union: each distinct element from all of // Produce an array that contains the union: each distinct element from all of
// the passed-in arrays. // the passed-in arrays.
_.union = function() { _.union = function() {
return _.uniq(_.flatten(arguments, true)); return _.uniq(flatten(arguments, true, true));
}; };
// Produce an array that contains every item shared between all the // Produce an array that contains every item shared between all the
// passed-in arrays. // passed-in arrays.
_.intersection = function(array) { _.intersection = function(array) {
var rest = slice.call(arguments, 1); if (array == null) return [];
return _.filter(_.uniq(array), function(item) { var result = [];
return _.every(rest, function(other) { var argsLength = arguments.length;
return _.contains(other, item); for (var i = 0, length = array.length; i < length; i++) {
}); var item = array[i];
}); if (_.contains(result, item)) continue;
for (var j = 1; j < argsLength; j++) {
if (!_.contains(arguments[j], item)) break;
}
if (j === argsLength) result.push(item);
}
return result;
}; };
// Take the difference between one array and a number of other arrays. // Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain. // Only the elements present in just the first array will remain.
_.difference = function(array) { _.difference = function(array) {
var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); var rest = flatten(arguments, true, true, 1);
return _.filter(array, function(value){ return !_.contains(rest, value); }); return _.filter(array, function(value){
return !_.contains(rest, value);
});
}; };
// Zip together multiple lists into a single array -- elements that share // Zip together multiple lists into a single array -- elements that share
// an index go together. // an index go together.
_.zip = function() { _.zip = function() {
var length = _.max(_.pluck(arguments, 'length').concat(0)); return _.unzip(arguments);
var results = new Array(length); };
for (var i = 0; i < length; i++) {
results[i] = _.pluck(arguments, '' + i); // Complement of _.zip. Unzip accepts an array of arrays and groups
// each array's elements on shared indices
_.unzip = function(array) {
var length = array && _.max(array, 'length').length || 0;
var result = Array(length);
for (var index = 0; index < length; index++) {
result[index] = _.pluck(array, index);
} }
return results; return result;
}; };
// Converts lists into objects. Pass either a single array of `[key, value]` // Converts lists into objects. Pass either a single array of `[key, value]`
// pairs, or two parallel arrays of the same length -- one of keys, and one of // pairs, or two parallel arrays of the same length -- one of keys, and one of
// the corresponding values. // the corresponding values.
_.object = function(list, values) { _.object = function(list, values) {
if (list == null) return {};
var result = {}; var result = {};
for (var i = 0, length = list.length; i < length; i++) { for (var i = 0, length = list && list.length; i < length; i++) {
if (values) { if (values) {
result[list[i]] = values[i]; result[list[i]] = values[i];
} else { } else {
...@@ -11708,40 +11770,68 @@ define('text',['module'], function (module) { ...@@ -11708,40 +11770,68 @@ define('text',['module'], function (module) {
return result; return result;
}; };
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), // Return the position of the first occurrence of an item in an array,
// we need this function. Return the position of the first occurrence of an // or -1 if the item is not included in the array.
// item in an array, or -1 if the item is not included in the array.
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
// If the array is large and already in sort order, pass `true` // If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search. // for **isSorted** to use binary search.
_.indexOf = function(array, item, isSorted) { _.indexOf = function(array, item, isSorted) {
if (array == null) return -1; var i = 0, length = array && array.length;
var i = 0, length = array.length;
if (isSorted) {
if (typeof isSorted == 'number') { if (typeof isSorted == 'number') {
i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
} else { } else if (isSorted && length) {
i = _.sortedIndex(array, item); i = _.sortedIndex(array, item);
return array[i] === item ? i : -1; return array[i] === item ? i : -1;
} }
if (item !== item) {
return _.findIndex(slice.call(array, i), _.isNaN);
} }
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
for (; i < length; i++) if (array[i] === item) return i; for (; i < length; i++) if (array[i] === item) return i;
return -1; return -1;
}; };
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
_.lastIndexOf = function(array, item, from) { _.lastIndexOf = function(array, item, from) {
if (array == null) return -1; var idx = array ? array.length : 0;
var hasIndex = from != null; if (typeof from == 'number') {
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); }
if (item !== item) {
return _.findLastIndex(slice.call(array, 0, idx), _.isNaN);
} }
var i = (hasIndex ? from : array.length); while (--idx >= 0) if (array[idx] === item) return idx;
while (i--) if (array[i] === item) return i;
return -1; return -1;
}; };
// Generator function to create the findIndex and findLastIndex functions
function createIndexFinder(dir) {
return function(array, predicate, context) {
predicate = cb(predicate, context);
var length = array != null && array.length;
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
}
// Returns the first index on an array-like that passes a predicate test
_.findIndex = createIndexFinder(1);
_.findLastIndex = createIndexFinder(-1);
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iteratee, context) {
iteratee = cb(iteratee, context, 1);
var value = iteratee(obj);
var low = 0, high = array.length;
while (low < high) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
};
// Generate an integer Array containing an arithmetic progression. A port of // Generate an integer Array containing an arithmetic progression. A port of
// the native Python `range()` function. See // the native Python `range()` function. See
// [the Python documentation](http://docs.python.org/library/functions.html#range). // [the Python documentation](http://docs.python.org/library/functions.html#range).
...@@ -11750,15 +11840,13 @@ define('text',['module'], function (module) { ...@@ -11750,15 +11840,13 @@ define('text',['module'], function (module) {
stop = start || 0; stop = start || 0;
start = 0; start = 0;
} }
step = arguments[2] || 1; step = step || 1;
var length = Math.max(Math.ceil((stop - start) / step), 0); var length = Math.max(Math.ceil((stop - start) / step), 0);
var idx = 0; var range = Array(length);
var range = new Array(length);
while(idx < length) { for (var idx = 0; idx < length; idx++, start += step) {
range[idx++] = start; range[idx] = start;
start += step;
} }
return range; return range;
...@@ -11767,26 +11855,27 @@ define('text',['module'], function (module) { ...@@ -11767,26 +11855,27 @@ define('text',['module'], function (module) {
// Function (ahem) Functions // Function (ahem) Functions
// ------------------ // ------------------
// Reusable constructor function for prototype setting. // Determines whether to execute a function as a constructor
var ctor = function(){}; // or a normal function with the provided arguments
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
var self = baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
if (_.isObject(result)) return result;
return self;
};
// Create a function bound to a given object (assigning `this`, and arguments, // Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
// available. // available.
_.bind = function(func, context) { _.bind = function(func, context) {
var args, bound;
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError; if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
return bound = function() { var bound = function() {
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
ctor.prototype = func.prototype;
var self = new ctor;
ctor.prototype = null;
var result = func.apply(self, args.concat(slice.call(arguments)));
if (Object(result) === result) return result;
return self;
}; };
return bound;
}; };
// Partially apply a function by creating a version that has had some of its // Partially apply a function by creating a version that has had some of its
...@@ -11794,49 +11883,55 @@ define('text',['module'], function (module) { ...@@ -11794,49 +11883,55 @@ define('text',['module'], function (module) {
// as a placeholder, allowing any combination of arguments to be pre-filled. // as a placeholder, allowing any combination of arguments to be pre-filled.
_.partial = function(func) { _.partial = function(func) {
var boundArgs = slice.call(arguments, 1); var boundArgs = slice.call(arguments, 1);
return function() { var bound = function() {
var position = 0; var position = 0, length = boundArgs.length;
var args = boundArgs.slice(); var args = Array(length);
for (var i = 0, length = args.length; i < length; i++) { for (var i = 0; i < length; i++) {
if (args[i] === _) args[i] = arguments[position++]; args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
} }
while (position < arguments.length) args.push(arguments[position++]); while (position < arguments.length) args.push(arguments[position++]);
return func.apply(this, args); return executeBound(func, bound, this, this, args);
}; };
return bound;
}; };
// Bind a number of an object's methods to that object. Remaining arguments // Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks // are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it. // defined on an object belong to it.
_.bindAll = function(obj) { _.bindAll = function(obj) {
var funcs = slice.call(arguments, 1); var i, length = arguments.length, key;
if (funcs.length === 0) throw new Error('bindAll must be passed function names'); if (length <= 1) throw new Error('bindAll must be passed function names');
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); for (i = 1; i < length; i++) {
key = arguments[i];
obj[key] = _.bind(obj[key], obj);
}
return obj; return obj;
}; };
// Memoize an expensive function by storing its results. // Memoize an expensive function by storing its results.
_.memoize = function(func, hasher) { _.memoize = function(func, hasher) {
var memo = {}; var memoize = function(key) {
hasher || (hasher = _.identity); var cache = memoize.cache;
return function() { var address = '' + (hasher ? hasher.apply(this, arguments) : key);
var key = hasher.apply(this, arguments); if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); return cache[address];
}; };
memoize.cache = {};
return memoize;
}; };
// Delays a function for the given number of milliseconds, and then calls // Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied. // it with the arguments supplied.
_.delay = function(func, wait) { _.delay = function(func, wait) {
var args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
return setTimeout(function(){ return func.apply(null, args); }, wait); return setTimeout(function(){
return func.apply(null, args);
}, wait);
}; };
// Defers a function, scheduling it to run after the current call stack has // Defers a function, scheduling it to run after the current call stack has
// cleared. // cleared.
_.defer = function(func) { _.defer = _.partial(_.delay, _, 1);
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
};
// Returns a function, that, when invoked, will only be triggered at most once // Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run // during a given window of time. Normally, the throttled function will run
...@@ -11847,12 +11942,12 @@ define('text',['module'], function (module) { ...@@ -11847,12 +11942,12 @@ define('text',['module'], function (module) {
var context, args, result; var context, args, result;
var timeout = null; var timeout = null;
var previous = 0; var previous = 0;
options || (options = {}); if (!options) options = {};
var later = function() { var later = function() {
previous = options.leading === false ? 0 : _.now(); previous = options.leading === false ? 0 : _.now();
timeout = null; timeout = null;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
}; };
return function() { return function() {
var now = _.now(); var now = _.now();
...@@ -11860,12 +11955,14 @@ define('text',['module'], function (module) { ...@@ -11860,12 +11955,14 @@ define('text',['module'], function (module) {
var remaining = wait - (now - previous); var remaining = wait - (now - previous);
context = this; context = this;
args = arguments; args = arguments;
if (remaining <= 0) { if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout); clearTimeout(timeout);
timeout = null; timeout = null;
}
previous = now; previous = now;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) { } else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining); timeout = setTimeout(later, remaining);
} }
...@@ -11882,13 +11979,14 @@ define('text',['module'], function (module) { ...@@ -11882,13 +11979,14 @@ define('text',['module'], function (module) {
var later = function() { var later = function() {
var last = _.now() - timestamp; var last = _.now() - timestamp;
if (last < wait) {
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last); timeout = setTimeout(later, wait - last);
} else { } else {
timeout = null; timeout = null;
if (!immediate) { if (!immediate) {
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
} }
} }
}; };
...@@ -11898,9 +11996,7 @@ define('text',['module'], function (module) { ...@@ -11898,9 +11996,7 @@ define('text',['module'], function (module) {
args = arguments; args = arguments;
timestamp = _.now(); timestamp = _.now();
var callNow = immediate && !timeout; var callNow = immediate && !timeout;
if (!timeout) { if (!timeout) timeout = setTimeout(later, wait);
timeout = setTimeout(later, wait);
}
if (callNow) { if (callNow) {
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; context = args = null;
...@@ -11910,19 +12006,6 @@ define('text',['module'], function (module) { ...@@ -11910,19 +12006,6 @@ define('text',['module'], function (module) {
}; };
}; };
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
// Returns the first function passed as an argument to the second, // Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and // allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function. // conditionally execute the original function.
...@@ -11930,20 +12013,27 @@ define('text',['module'], function (module) { ...@@ -11930,20 +12013,27 @@ define('text',['module'], function (module) {
return _.partial(wrapper, func); return _.partial(wrapper, func);
}; };
// Returns a negated version of the passed-in predicate.
_.negate = function(predicate) {
return function() {
return !predicate.apply(this, arguments);
};
};
// Returns a function that is the composition of a list of functions, each // Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows. // consuming the return value of the function that follows.
_.compose = function() { _.compose = function() {
var funcs = arguments;
return function() {
var args = arguments; var args = arguments;
for (var i = funcs.length - 1; i >= 0; i--) { var start = args.length - 1;
args = [funcs[i].apply(this, args)]; return function() {
} var i = start;
return args[0]; var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
}; };
}; };
// Returns a function that will only be executed after being called N times. // Returns a function that will only be executed on and after the Nth call.
_.after = function(times, func) { _.after = function(times, func) {
return function() { return function() {
if (--times < 1) { if (--times < 1) {
...@@ -11952,16 +12042,66 @@ define('text',['module'], function (module) { ...@@ -11952,16 +12042,66 @@ define('text',['module'], function (module) {
}; };
}; };
// Returns a function that will only be executed up to (but not including) the Nth call.
_.before = function(times, func) {
var memo;
return function() {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
};
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = _.partial(_.before, 2);
// Object Functions // Object Functions
// ---------------- // ----------------
// Retrieve the names of an object's properties. // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
function collectNonEnumProps(obj, keys) {
var nonEnumIdx = nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
// Constructor is a special case.
var prop = 'constructor';
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
while (nonEnumIdx--) {
prop = nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
keys.push(prop);
}
}
}
// Retrieve the names of an object's own properties.
// Delegates to **ECMAScript 5**'s native `Object.keys` // Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = function(obj) { _.keys = function(obj) {
if (!_.isObject(obj)) return []; if (!_.isObject(obj)) return [];
if (nativeKeys) return nativeKeys(obj); if (nativeKeys) return nativeKeys(obj);
var keys = []; var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key); for (var key in obj) if (_.has(obj, key)) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Retrieve all the property names of an object.
_.allKeys = function(obj) {
if (!_.isObject(obj)) return [];
var keys = [];
for (var key in obj) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys; return keys;
}; };
...@@ -11969,18 +12109,33 @@ define('text',['module'], function (module) { ...@@ -11969,18 +12109,33 @@ define('text',['module'], function (module) {
_.values = function(obj) { _.values = function(obj) {
var keys = _.keys(obj); var keys = _.keys(obj);
var length = keys.length; var length = keys.length;
var values = new Array(length); var values = Array(length);
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]]; values[i] = obj[keys[i]];
} }
return values; return values;
}; };
// Returns the results of applying the iteratee to each element of the object
// In contrast to _.map it returns an object
_.mapObject = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = _.keys(obj),
length = keys.length,
results = {},
currentKey;
for (var index = 0; index < length; index++) {
currentKey = keys[index];
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
// Convert an object into a list of `[key, value]` pairs. // Convert an object into a list of `[key, value]` pairs.
_.pairs = function(obj) { _.pairs = function(obj) {
var keys = _.keys(obj); var keys = _.keys(obj);
var length = keys.length; var length = keys.length;
var pairs = new Array(length); var pairs = Array(length);
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]]; pairs[i] = [keys[i], obj[keys[i]]];
} }
...@@ -12008,48 +12163,57 @@ define('text',['module'], function (module) { ...@@ -12008,48 +12163,57 @@ define('text',['module'], function (module) {
}; };
// Extend a given object with all the properties in passed-in object(s). // Extend a given object with all the properties in passed-in object(s).
_.extend = function(obj) { _.extend = createAssigner(_.allKeys);
each(slice.call(arguments, 1), function(source) {
if (source) { // Assigns a given object with all the own properties in the passed-in object(s)
for (var prop in source) { // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
obj[prop] = source[prop]; _.extendOwn = _.assign = createAssigner(_.keys);
}
// Returns the first key on an object that passes a predicate test
_.findKey = function(obj, predicate, context) {
predicate = cb(predicate, context);
var keys = _.keys(obj), key;
for (var i = 0, length = keys.length; i < length; i++) {
key = keys[i];
if (predicate(obj[key], key, obj)) return key;
} }
});
return obj;
}; };
// Return a copy of the object only containing the whitelisted properties. // Return a copy of the object only containing the whitelisted properties.
_.pick = function(obj) { _.pick = function(object, oiteratee, context) {
var copy = {}; var result = {}, obj = object, iteratee, keys;
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); if (obj == null) return result;
each(keys, function(key) { if (_.isFunction(oiteratee)) {
if (key in obj) copy[key] = obj[key]; keys = _.allKeys(obj);
}); iteratee = optimizeCb(oiteratee, context);
return copy; } else {
keys = flatten(arguments, false, false, 1);
iteratee = function(value, key, obj) { return key in obj; };
obj = Object(obj);
}
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
var value = obj[key];
if (iteratee(value, key, obj)) result[key] = value;
}
return result;
}; };
// Return a copy of the object without the blacklisted properties. // Return a copy of the object without the blacklisted properties.
_.omit = function(obj) { _.omit = function(obj, iteratee, context) {
var copy = {}; if (_.isFunction(iteratee)) {
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); iteratee = _.negate(iteratee);
for (var key in obj) { } else {
if (!_.contains(keys, key)) copy[key] = obj[key]; var keys = _.map(flatten(arguments, false, false, 1), String);
iteratee = function(value, key) {
return !_.contains(keys, key);
};
} }
return copy; return _.pick(obj, iteratee, context);
}; };
// Fill in a given object with default properties. // Fill in a given object with default properties.
_.defaults = function(obj) { _.defaults = createAssigner(_.allKeys, true);
each(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) {
if (obj[prop] === void 0) obj[prop] = source[prop];
}
}
});
return obj;
};
// Create a (shallow-cloned) duplicate of an object. // Create a (shallow-cloned) duplicate of an object.
_.clone = function(obj) { _.clone = function(obj) {
...@@ -12065,11 +12229,24 @@ define('text',['module'], function (module) { ...@@ -12065,11 +12229,24 @@ define('text',['module'], function (module) {
return obj; return obj;
}; };
// Returns whether an object has a given set of `key:value` pairs.
_.isMatch = function(object, attrs) {
var keys = _.keys(attrs), length = keys.length;
if (object == null) return !length;
var obj = Object(object);
for (var i = 0; i < length; i++) {
var key = keys[i];
if (attrs[key] !== obj[key] || !(key in obj)) return false;
}
return true;
};
// Internal recursive comparison function for `isEqual`. // Internal recursive comparison function for `isEqual`.
var eq = function(a, b, aStack, bStack) { var eq = function(a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical. // Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a == 1 / b; if (a === b) return a !== 0 || 1 / a === 1 / b;
// A strict comparison is necessary because `null == undefined`. // A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b; if (a == null || b == null) return a === b;
// Unwrap any wrapped objects. // Unwrap any wrapped objects.
...@@ -12077,98 +12254,98 @@ define('text',['module'], function (module) { ...@@ -12077,98 +12254,98 @@ define('text',['module'], function (module) {
if (b instanceof _) b = b._wrapped; if (b instanceof _) b = b._wrapped;
// Compare `[[Class]]` names. // Compare `[[Class]]` names.
var className = toString.call(a); var className = toString.call(a);
if (className != toString.call(b)) return false; if (className !== toString.call(b)) return false;
switch (className) { switch (className) {
// Strings, numbers, dates, and booleans are compared by value. // Strings, numbers, regular expressions, dates, and booleans are compared by value.
case '[object RegExp]':
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case '[object String]': case '[object String]':
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`. // equivalent to `new String("5")`.
return a == String(b); return '' + a === '' + b;
case '[object Number]': case '[object Number]':
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for // `NaN`s are equivalent, but non-reflexive.
// other numeric values. // Object(NaN) is equivalent to NaN
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); if (+a !== +a) return +b !== +b;
// An `egal` comparison is performed for other numeric values.
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]': case '[object Date]':
case '[object Boolean]': case '[object Boolean]':
// Coerce dates and booleans to numeric primitive values. Dates are compared by their // Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations // millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent. // of `NaN` are not equivalent.
return +a == +b; return +a === +b;
// RegExps are compared by their source patterns and flags.
case '[object RegExp]':
return a.source == b.source &&
a.global == b.global &&
a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase;
} }
var areArrays = className === '[object Array]';
if (!areArrays) {
if (typeof a != 'object' || typeof b != 'object') return false; if (typeof a != 'object' || typeof b != 'object') return false;
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
_.isFunction(bCtor) && bCtor instanceof bCtor)
&& ('constructor' in a && 'constructor' in b)) {
return false;
}
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic // Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
// Initializing stack of traversed objects.
// It's done here since we only need them for objects and arrays comparison.
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length; var length = aStack.length;
while (length--) { while (length--) {
// Linear search. Performance is inversely proportional to the number of // Linear search. Performance is inversely proportional to the number of
// unique nested structures. // unique nested structures.
if (aStack[length] == a) return bStack[length] == b; if (aStack[length] === a) return bStack[length] === b;
}
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
_.isFunction(bCtor) && (bCtor instanceof bCtor))
&& ('constructor' in a && 'constructor' in b)) {
return false;
} }
// Add the first object to the stack of traversed objects. // Add the first object to the stack of traversed objects.
aStack.push(a); aStack.push(a);
bStack.push(b); bStack.push(b);
var size = 0, result = true;
// Recursively compare objects and arrays. // Recursively compare objects and arrays.
if (className == '[object Array]') { if (areArrays) {
// Compare array lengths to determine if a deep comparison is necessary. // Compare array lengths to determine if a deep comparison is necessary.
size = a.length; length = a.length;
result = size == b.length; if (length !== b.length) return false;
if (result) {
// Deep compare the contents, ignoring non-numeric properties. // Deep compare the contents, ignoring non-numeric properties.
while (size--) { while (length--) {
if (!(result = eq(a[size], b[size], aStack, bStack))) break; if (!eq(a[length], b[length], aStack, bStack)) return false;
}
} }
} else { } else {
// Deep compare objects. // Deep compare objects.
for (var key in a) { var keys = _.keys(a), key;
if (_.has(a, key)) { length = keys.length;
// Count the expected number of properties. // Ensure that both objects contain the same number of properties before comparing deep equality.
size++; if (_.keys(b).length !== length) return false;
// Deep compare each member. while (length--) {
if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; // Deep compare each member
} key = keys[length];
} if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
// Ensure that both objects contain the same number of properties.
if (result) {
for (key in b) {
if (_.has(b, key) && !(size--)) break;
}
result = !size;
} }
} }
// Remove the first object from the stack of traversed objects. // Remove the first object from the stack of traversed objects.
aStack.pop(); aStack.pop();
bStack.pop(); bStack.pop();
return result; return true;
}; };
// Perform a deep comparison to check if two objects are equal. // Perform a deep comparison to check if two objects are equal.
_.isEqual = function(a, b) { _.isEqual = function(a, b) {
return eq(a, b, [], []); return eq(a, b);
}; };
// Is a given array, string, or object empty? // Is a given array, string, or object empty?
// An "empty" object has no enumerable own-properties. // An "empty" object has no enumerable own-properties.
_.isEmpty = function(obj) { _.isEmpty = function(obj) {
if (obj == null) return true; if (obj == null) return true;
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
for (var key in obj) if (_.has(obj, key)) return false; return _.keys(obj).length === 0;
return true;
}; };
// Is a given value a DOM element? // Is a given value a DOM element?
...@@ -12179,33 +12356,35 @@ define('text',['module'], function (module) { ...@@ -12179,33 +12356,35 @@ define('text',['module'], function (module) {
// Is a given value an array? // Is a given value an array?
// Delegates to ECMA5's native Array.isArray // Delegates to ECMA5's native Array.isArray
_.isArray = nativeIsArray || function(obj) { _.isArray = nativeIsArray || function(obj) {
return toString.call(obj) == '[object Array]'; return toString.call(obj) === '[object Array]';
}; };
// Is a given variable an object? // Is a given variable an object?
_.isObject = function(obj) { _.isObject = function(obj) {
return obj === Object(obj); var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
}; };
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
_['is' + name] = function(obj) { _['is' + name] = function(obj) {
return toString.call(obj) == '[object ' + name + ']'; return toString.call(obj) === '[object ' + name + ']';
}; };
}); });
// Define a fallback version of the method in browsers (ahem, IE), where // Define a fallback version of the method in browsers (ahem, IE < 9), where
// there isn't any inspectable "Arguments" type. // there isn't any inspectable "Arguments" type.
if (!_.isArguments(arguments)) { if (!_.isArguments(arguments)) {
_.isArguments = function(obj) { _.isArguments = function(obj) {
return !!(obj && _.has(obj, 'callee')); return _.has(obj, 'callee');
}; };
} }
// Optimize `isFunction` if appropriate. // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
if (typeof (/./) !== 'function') { // IE 11 (#1621), and in Safari 8 (#1929).
if (typeof /./ != 'function' && typeof Int8Array != 'object') {
_.isFunction = function(obj) { _.isFunction = function(obj) {
return typeof obj === 'function'; return typeof obj == 'function' || false;
}; };
} }
...@@ -12216,12 +12395,12 @@ define('text',['module'], function (module) { ...@@ -12216,12 +12395,12 @@ define('text',['module'], function (module) {
// Is the given value `NaN`? (NaN is the only number which does not equal itself). // Is the given value `NaN`? (NaN is the only number which does not equal itself).
_.isNaN = function(obj) { _.isNaN = function(obj) {
return _.isNumber(obj) && obj != +obj; return _.isNumber(obj) && obj !== +obj;
}; };
// Is a given value a boolean? // Is a given value a boolean?
_.isBoolean = function(obj) { _.isBoolean = function(obj) {
return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
}; };
// Is a given value equal to null? // Is a given value equal to null?
...@@ -12237,7 +12416,7 @@ define('text',['module'], function (module) { ...@@ -12237,7 +12416,7 @@ define('text',['module'], function (module) {
// Shortcut function for checking if an object has a given property directly // Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype). // on itself (in other words, not on a prototype).
_.has = function(obj, key) { _.has = function(obj, key) {
return hasOwnProperty.call(obj, key); return obj != null && hasOwnProperty.call(obj, key);
}; };
// Utility Functions // Utility Functions
...@@ -12250,39 +12429,47 @@ define('text',['module'], function (module) { ...@@ -12250,39 +12429,47 @@ define('text',['module'], function (module) {
return this; return this;
}; };
// Keep the identity function around for default iterators. // Keep the identity function around for default iteratees.
_.identity = function(value) { _.identity = function(value) {
return value; return value;
}; };
// Predicate-generating functions. Often useful outside of Underscore.
_.constant = function(value) { _.constant = function(value) {
return function () { return function() {
return value; return value;
}; };
}; };
_.noop = function(){};
_.property = function(key) { _.property = function(key) {
return function(obj) { return function(obj) {
return obj == null ? void 0 : obj[key];
};
};
// Generates a function for a given object that returns a given property.
_.propertyOf = function(obj) {
return obj == null ? function(){} : function(key) {
return obj[key]; return obj[key];
}; };
}; };
// Returns a predicate for checking whether an object has a given set of `key:value` pairs. // Returns a predicate for checking whether an object has a given set of
_.matches = function(attrs) { // `key:value` pairs.
_.matcher = _.matches = function(attrs) {
attrs = _.extendOwn({}, attrs);
return function(obj) { return function(obj) {
if (obj === attrs) return true; //avoid comparing an object to itself. return _.isMatch(obj, attrs);
for (var key in attrs) { };
if (attrs[key] !== obj[key])
return false;
}
return true;
}
}; };
// Run a function **n** times. // Run a function **n** times.
_.times = function(n, iterator, context) { _.times = function(n, iteratee, context) {
var accum = Array(Math.max(0, n)); var accum = Array(Math.max(0, n));
for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); iteratee = optimizeCb(iteratee, context, 1);
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
return accum; return accum;
}; };
...@@ -12296,56 +12483,48 @@ define('text',['module'], function (module) { ...@@ -12296,56 +12483,48 @@ define('text',['module'], function (module) {
}; };
// A (possibly faster) way to get the current timestamp as an integer. // A (possibly faster) way to get the current timestamp as an integer.
_.now = Date.now || function() { return new Date().getTime(); }; _.now = Date.now || function() {
return new Date().getTime();
};
// List of HTML entities for escaping. // List of HTML entities for escaping.
var entityMap = { var escapeMap = {
escape: {
'&': '&amp;', '&': '&amp;',
'<': '&lt;', '<': '&lt;',
'>': '&gt;', '>': '&gt;',
'"': '&quot;', '"': '&quot;',
"'": '&#x27;' "'": '&#x27;',
} '`': '&#x60;'
};
entityMap.unescape = _.invert(entityMap.escape);
// Regexes containing the keys and values listed immediately above.
var entityRegexes = {
escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
}; };
var unescapeMap = _.invert(escapeMap);
// Functions for escaping and unescaping strings to/from HTML interpolation. // Functions for escaping and unescaping strings to/from HTML interpolation.
_.each(['escape', 'unescape'], function(method) { var createEscaper = function(map) {
_[method] = function(string) { var escaper = function(match) {
if (string == null) return ''; return map[match];
return ('' + string).replace(entityRegexes[method], function(match) {
return entityMap[method][match];
});
}; };
}); // Regexes for identifying a key that needs to be escaped
var source = '(?:' + _.keys(map).join('|') + ')';
var testRegexp = RegExp(source);
var replaceRegexp = RegExp(source, 'g');
return function(string) {
string = string == null ? '' : '' + string;
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
};
};
_.escape = createEscaper(escapeMap);
_.unescape = createEscaper(unescapeMap);
// If the value of the named `property` is a function then invoke it with the // If the value of the named `property` is a function then invoke it with the
// `object` as context; otherwise, return it. // `object` as context; otherwise, return it.
_.result = function(object, property) { _.result = function(object, property, fallback) {
if (object == null) return void 0; var value = object == null ? void 0 : object[property];
var value = object[property]; if (value === void 0) {
value = fallback;
}
return _.isFunction(value) ? value.call(object) : value; return _.isFunction(value) ? value.call(object) : value;
}; };
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result.call(this, func.apply(_, args));
};
});
};
// Generate a unique integer id (unique within the entire client session). // Generate a unique integer id (unique within the entire client session).
// Useful for temporary DOM ids. // Useful for temporary DOM ids.
var idCounter = 0; var idCounter = 0;
...@@ -12374,22 +12553,26 @@ define('text',['module'], function (module) { ...@@ -12374,22 +12553,26 @@ define('text',['module'], function (module) {
'\\': '\\', '\\': '\\',
'\r': 'r', '\r': 'r',
'\n': 'n', '\n': 'n',
'\t': 't',
'\u2028': 'u2028', '\u2028': 'u2028',
'\u2029': 'u2029' '\u2029': 'u2029'
}; };
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function(match) {
return '\\' + escapes[match];
};
// JavaScript micro-templating, similar to John Resig's implementation. // JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace, // Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code. // and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) { // NB: `oldSettings` only exists for backwards compatibility.
var render; _.template = function(text, settings, oldSettings) {
if (!settings && oldSettings) settings = oldSettings;
settings = _.defaults({}, settings, _.templateSettings); settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation. // Combine delimiters into one regular expression via alternation.
var matcher = new RegExp([ var matcher = RegExp([
(settings.escape || noMatch).source, (settings.escape || noMatch).source,
(settings.interpolate || noMatch).source, (settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source (settings.evaluate || noMatch).source
...@@ -12399,19 +12582,18 @@ define('text',['module'], function (module) { ...@@ -12399,19 +12582,18 @@ define('text',['module'], function (module) {
var index = 0; var index = 0;
var source = "__p+='"; var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset) source += text.slice(index, offset).replace(escaper, escapeChar);
.replace(escaper, function(match) { return '\\' + escapes[match]; }); index = offset + match.length;
if (escape) { if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
} } else if (interpolate) {
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
} } else if (evaluate) {
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='"; source += "';\n" + evaluate + "\n__p+='";
} }
index = offset + match.length;
// Adobe VMs need the match returned to produce the correct offest.
return match; return match;
}); });
source += "';\n"; source += "';\n";
...@@ -12421,29 +12603,31 @@ define('text',['module'], function (module) { ...@@ -12421,29 +12603,31 @@ define('text',['module'], function (module) {
source = "var __t,__p='',__j=Array.prototype.join," + source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" + "print=function(){__p+=__j.call(arguments,'');};\n" +
source + "return __p;\n"; source + 'return __p;\n';
try { try {
render = new Function(settings.variable || 'obj', '_', source); var render = new Function(settings.variable || 'obj', '_', source);
} catch (e) { } catch (e) {
e.source = source; e.source = source;
throw e; throw e;
} }
if (data) return render(data, _);
var template = function(data) { var template = function(data) {
return render.call(this, data, _); return render.call(this, data, _);
}; };
// Provide the compiled function source as a convenience for precompilation. // Provide the compiled source as a convenience for precompilation.
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; var argument = settings.variable || 'obj';
template.source = 'function(' + argument + '){\n' + source + '}';
return template; return template;
}; };
// Add a "chain" function, which will delegate to the wrapper. // Add a "chain" function. Start chaining a wrapped Underscore object.
_.chain = function(obj) { _.chain = function(obj) {
return _(obj).chain(); var instance = _(obj);
instance._chain = true;
return instance;
}; };
// OOP // OOP
...@@ -12453,46 +12637,56 @@ define('text',['module'], function (module) { ...@@ -12453,46 +12637,56 @@ define('text',['module'], function (module) {
// underscore functions. Wrapped objects may be chained. // underscore functions. Wrapped objects may be chained.
// Helper function to continue chaining intermediate results. // Helper function to continue chaining intermediate results.
var result = function(obj) { var result = function(instance, obj) {
return this._chain ? _(obj).chain() : obj; return instance._chain ? _(obj).chain() : obj;
};
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result(this, func.apply(_, args));
};
});
}; };
// Add all of the Underscore functions to the wrapper object. // Add all of the Underscore functions to the wrapper object.
_.mixin(_); _.mixin(_);
// Add all mutator Array functions to the wrapper. // Add all mutator Array functions to the wrapper.
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
var method = ArrayProto[name]; var method = ArrayProto[name];
_.prototype[name] = function() { _.prototype[name] = function() {
var obj = this._wrapped; var obj = this._wrapped;
method.apply(obj, arguments); method.apply(obj, arguments);
if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
return result.call(this, obj); return result(this, obj);
}; };
}); });
// Add all accessor Array functions to the wrapper. // Add all accessor Array functions to the wrapper.
each(['concat', 'join', 'slice'], function(name) { _.each(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name]; var method = ArrayProto[name];
_.prototype[name] = function() { _.prototype[name] = function() {
return result.call(this, method.apply(this._wrapped, arguments)); return result(this, method.apply(this._wrapped, arguments));
}; };
}); });
_.extend(_.prototype, {
// Start chaining a wrapped Underscore object.
chain: function() {
this._chain = true;
return this;
},
// Extracts the result from a wrapped and chained object. // Extracts the result from a wrapped and chained object.
value: function() { _.prototype.value = function() {
return this._wrapped; return this._wrapped;
} };
}); // Provide unwrapping proxy for some methods used in engine operations
// such as arithmetic and JSON stringification.
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
_.prototype.toString = function() {
return '' + this._wrapped;
};
// AMD registration happens at the end for compatibility with AMD loaders // AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general // that may not enforce next-turn semantics on modules. Even though general
...@@ -12506,7 +12700,7 @@ define('text',['module'], function (module) { ...@@ -12506,7 +12700,7 @@ define('text',['module'], function (module) {
return _; return _;
}); });
} }
}).call(this); }.call(this));
// RequireJS UnderscoreJS template plugin // RequireJS UnderscoreJS template plugin
// http://github.com/jfparadis/requirejs-tpl // http://github.com/jfparadis/requirejs-tpl
...@@ -13031,7 +13225,7 @@ var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments ...@@ -13031,7 +13225,7 @@ var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments
with(obj||{}){ with(obj||{}){
__p+='<form id="converse-login" method="post">\n <label>'+ __p+='<form id="converse-login" method="post">\n <label>'+
((__t=(label_username))==null?'':__t)+ ((__t=(label_username))==null?'':__t)+
'</label>\n <input type="username" name="jid" placeholder="user@server">\n <label>'+ '</label>\n <input type="email" name="jid" placeholder="user@server">\n <label>'+
((__t=(label_password))==null?'':__t)+ ((__t=(label_password))==null?'':__t)+
'</label>\n <input type="password" name="password" placeholder="password">\n <input class="submit" type="submit" value="'+ '</label>\n <input type="password" name="password" placeholder="password">\n <input class="submit" type="submit" value="'+
((__t=(label_login))==null?'':__t)+ ((__t=(label_login))==null?'':__t)+
...@@ -13360,7 +13554,9 @@ __p+='<form class="add-chatroom" action="" method="post">\n <label>'+ ...@@ -13360,7 +13554,9 @@ __p+='<form class="add-chatroom" action="" method="post">\n <label>'+
((__t=(label_nickname))==null?'':__t)+ ((__t=(label_nickname))==null?'':__t)+
'</label>\n <input type="text" name="nick" class="new-chatroom-nick"\n placeholder="'+ '</label>\n <input type="text" name="nick" class="new-chatroom-nick"\n placeholder="'+
((__t=(label_nickname))==null?'':__t)+ ((__t=(label_nickname))==null?'':__t)+
'"/>\n <label>'+ '"/>\n <label'+
((__t=(server_label_global_attr))==null?'':__t)+
'>'+
((__t=(label_server))==null?'':__t)+ ((__t=(label_server))==null?'':__t)+
'</label>\n <input type="'+ '</label>\n <input type="'+
((__t=(server_input_type))==null?'':__t)+ ((__t=(server_input_type))==null?'':__t)+
...@@ -13406,9 +13602,13 @@ __p+='<a class="open-chat" title="Name: '+ ...@@ -13406,9 +13602,13 @@ __p+='<a class="open-chat" title="Name: '+
((__t=(desc_status))==null?'':__t)+ ((__t=(desc_status))==null?'':__t)+
'"></span>'+ '"></span>'+
((__t=(fullname))==null?'':__t)+ ((__t=(fullname))==null?'':__t)+
'</a>\n<a class="remove-xmpp-contact icon-remove" title="'+ '</a>\n';
if (allow_contact_removal) {
__p+='\n<a class="remove-xmpp-contact icon-remove" title="'+
((__t=(desc_remove))==null?'':__t)+ ((__t=(desc_remove))==null?'':__t)+
'" href="#"></a>\n'; '" href="#"></a>\n';
}
__p+='\n';
} }
return __p; return __p;
}; }); }; });
...@@ -27013,19 +27213,6 @@ define("converse-dependencies", [ ...@@ -27013,19 +27213,6 @@ define("converse-dependencies", [
return this; return this;
}; };
var playNotification = function () {
var audio;
if (converse.play_sounds && typeof Audio !== "undefined"){
audio = new Audio("sounds/msg_received.ogg");
if (audio.canPlayType('/audio/ogg')) {
audio.play();
} else {
audio = new Audio("/sounds/msg_received.mp3");
audio.play();
}
}
};
var converse = { var converse = {
plugins: {}, plugins: {},
templates: templates, templates: templates,
...@@ -27132,6 +27319,7 @@ define("converse-dependencies", [ ...@@ -27132,6 +27319,7 @@ define("converse-dependencies", [
// Default configuration values // Default configuration values
// ---------------------------- // ----------------------------
this.default_settings = { this.default_settings = {
allow_contact_removal: true,
allow_contact_requests: true, allow_contact_requests: true,
allow_dragresize: true, allow_dragresize: true,
allow_logout: true, allow_logout: true,
...@@ -27246,6 +27434,19 @@ define("converse-dependencies", [ ...@@ -27246,6 +27434,19 @@ define("converse-dependencies", [
// Module-level functions // Module-level functions
// ---------------------- // ----------------------
this.playNotification = function () {
var audio;
if (converse.play_sounds && typeof Audio !== "undefined"){
audio = new Audio("sounds/msg_received.ogg");
if (audio.canPlayType('/audio/ogg')) {
audio.play();
} else {
audio = new Audio("/sounds/msg_received.mp3");
audio.play();
}
}
};
this.giveFeedback = function (message, klass) { this.giveFeedback = function (message, klass) {
$('.conn-feedback').each(function (idx, el) { $('.conn-feedback').each(function (idx, el) {
var $el = $(el); var $el = $(el);
...@@ -27318,7 +27519,6 @@ define("converse-dependencies", [ ...@@ -27318,7 +27519,6 @@ define("converse-dependencies", [
this.reconnect = function () { this.reconnect = function () {
converse.giveFeedback(__('Reconnecting'), 'error'); converse.giveFeedback(__('Reconnecting'), 'error');
converse.emit('reconnect');
if (!converse.prebind) { if (!converse.prebind) {
this.connection.connect( this.connection.connect(
this.connection.jid, this.connection.jid,
...@@ -27330,6 +27530,10 @@ define("converse-dependencies", [ ...@@ -27330,6 +27530,10 @@ define("converse-dependencies", [
this.connection.hold, this.connection.hold,
this.connection.route this.connection.route
); );
} else if (converse.prebind_url) {
this.clearSession();
this._tearDown();
this.startNewBOSHSession();
} }
}; };
...@@ -27366,6 +27570,7 @@ define("converse-dependencies", [ ...@@ -27366,6 +27570,7 @@ define("converse-dependencies", [
converse.giveFeedback(__('Authentication Failed'), 'error'); converse.giveFeedback(__('Authentication Failed'), 'error');
converse.connection.disconnect(__('Authentication Failed')); converse.connection.disconnect(__('Authentication Failed'));
} else if (status === Strophe.Status.DISCONNECTING) { } else if (status === Strophe.Status.DISCONNECTING) {
// FIXME: what about prebind?
if (!converse.connection.connected) { if (!converse.connection.connected) {
converse.renderLoginPanel(); converse.renderLoginPanel();
} }
...@@ -27441,8 +27646,8 @@ define("converse-dependencies", [ ...@@ -27441,8 +27646,8 @@ define("converse-dependencies", [
this.clearSession = function () { this.clearSession = function () {
this.roster.browserStorage._clear(); this.roster.browserStorage._clear();
this.session.browserStorage._clear(); this.session.browserStorage._clear();
// XXX: this should perhaps go into the beforeunload handler var controlbox = converse.chatboxes.get('controlbox');
converse.chatboxes.get('controlbox').save({'connected': false}); controlbox.save({'connected': false});
}; };
this.setSession = function () { this.setSession = function () {
...@@ -28647,6 +28852,7 @@ define("converse-dependencies", [ ...@@ -28647,6 +28852,7 @@ define("converse-dependencies", [
this.$el.html( this.$el.html(
converse.templates.room_panel({ converse.templates.room_panel({
'server_input_type': converse.hide_muc_server && 'hidden' || 'text', 'server_input_type': converse.hide_muc_server && 'hidden' || 'text',
'server_label_global_attr': converse.hide_muc_server && ' hidden' || '',
'label_room_name': __('Room name'), 'label_room_name': __('Room name'),
'label_nickname': __('Nickname'), 'label_nickname': __('Nickname'),
'label_server': __('Server'), 'label_server': __('Server'),
...@@ -29859,7 +30065,7 @@ define("converse-dependencies", [ ...@@ -29859,7 +30065,7 @@ define("converse-dependencies", [
} }
this.model.createMessage($message); this.model.createMessage($message);
if (!delayed && sender !== this.model.get('nick') && (new RegExp("\\b"+this.model.get('nick')+"\\b")).test(body)) { if (!delayed && sender !== this.model.get('nick') && (new RegExp("\\b"+this.model.get('nick')+"\\b")).test(body)) {
playNotification(); converse.playNotification();
} }
if (sender !== this.model.get('nick')) { if (sender !== this.model.get('nick')) {
// We only emit an event if it's not our own message // We only emit an event if it's not our own message
...@@ -30029,7 +30235,7 @@ define("converse-dependencies", [ ...@@ -30029,7 +30235,7 @@ define("converse-dependencies", [
return true; // We already have this message stored. return true; // We already have this message stored.
} }
if (!this.isOnlyChatStateNotification($message) && from !== converse.bare_jid) { if (!this.isOnlyChatStateNotification($message) && from !== converse.bare_jid) {
playNotification(); converse.playNotification();
} }
chatbox.receiveMessage($message); chatbox.receiveMessage($message);
converse.roster.addResource(contact_jid, resource); converse.roster.addResource(contact_jid, resource);
...@@ -30460,7 +30666,8 @@ define("converse-dependencies", [ ...@@ -30460,7 +30666,8 @@ define("converse-dependencies", [
_.extend(item.toJSON(), { _.extend(item.toJSON(), {
'desc_status': STATUSES[chat_status||'offline'], 'desc_status': STATUSES[chat_status||'offline'],
'desc_chat': __('Click to chat with this contact'), 'desc_chat': __('Click to chat with this contact'),
'desc_remove': __('Click to remove this contact') 'desc_remove': __('Click to remove this contact'),
'allow_contact_removal': converse.allow_contact_removal
}) })
)); ));
} }
...@@ -30474,6 +30681,7 @@ define("converse-dependencies", [ ...@@ -30474,6 +30681,7 @@ define("converse-dependencies", [
removeContact: function (ev) { removeContact: function (ev) {
if (ev && ev.preventDefault) { ev.preventDefault(); } if (ev && ev.preventDefault) { ev.preventDefault(); }
if (!converse.allow_contact_removal) { return; }
var result = confirm(__("Are you sure you want to remove this contact?")); var result = confirm(__("Are you sure you want to remove this contact?"));
if (result === true) { if (result === true) {
var bare_jid = this.model.get('jid'); var bare_jid = this.model.get('jid');
...@@ -32174,20 +32382,32 @@ define("converse-dependencies", [ ...@@ -32174,20 +32382,32 @@ define("converse-dependencies", [
} }
}; };
this.startNewBOSHSession = function () {
$.ajax({
url: this.prebind_url,
type: 'GET',
success: function (response) {
this.session.save({rid: response.rid});
this.connection.attach(
response.jid,
response.sid,
response.rid,
this.onConnect
);
}.bind(this),
error: function (response) {
delete this.connection;
this.emit('noResumeableSession');
}.bind(this)
});
};
this.initConnection = function () { this.initConnection = function () {
var rid, sid, jid; var rid, sid, jid;
if (this.connection && this.connection.connected) { if (this.connection && this.connection.connected) {
this.setUpXMLLogging(); this.setUpXMLLogging();
this.onConnected(); this.onConnected();
} else { } else {
// XXX: it's not yet clear what the order of preference should
// be between RID and SID received via the initialize method or
// those received from sessionStorage.
//
// What do you we if we receive values from both avenues?
//
// Also, what do we do when the keepalive session values are
// expired? Do we try to fall back?
if (!this.bosh_service_url && ! this.websocket_url) { if (!this.bosh_service_url && ! this.websocket_url) {
throw("Error: you must supply a value for the bosh_service_url or websocket_url"); throw("Error: you must supply a value for the bosh_service_url or websocket_url");
} }
...@@ -32213,33 +32433,25 @@ define("converse-dependencies", [ ...@@ -32213,33 +32433,25 @@ define("converse-dependencies", [
rid = this.session.get('rid'); rid = this.session.get('rid');
sid = this.session.get('sid'); sid = this.session.get('sid');
jid = this.session.get('jid'); jid = this.session.get('jid');
if (rid && jid && sid) { if (this.prebind) {
// The RID needs to be increased with each request. if (!this.jid) {
this.session.save({rid: rid}); throw("When using 'keepalive' with 'prebind, you must supply the JID of the current user.");
}
if (rid && sid && jid && Strophe.getBareJidFromJid(jid) === Strophe.getBareJidFromJid(this.jid)) {
this.session.save({rid: rid}); // The RID needs to be increased with each request.
this.connection.attach(jid, sid, rid, this.onConnect); this.connection.attach(jid, sid, rid, this.onConnect);
} else if (this.prebind) { } else if (this.prebind_url) {
if (this.prebind_url) { this.startNewBOSHSession();
$.ajax({
url: this.prebind_url,
type: 'GET',
success: function (response) {
this.session.save({rid: rid});
this.connection.attach(
response.jid,
response.sid,
response.rid,
this.onConnect
);
}.bind(this),
error: function (response) {
delete this.connection;
this.emit('noResumeableSession');
}.bind(this)
});
} else { } else {
delete this.connection; delete this.connection;
this.emit('noResumeableSession'); this.emit('noResumeableSession');
} }
} else {
// Non-prebind case.
if (rid && sid && jid) {
this.session.save({rid: rid}); // The RID needs to be increased with each request.
this.connection.attach(jid, sid, rid, this.onConnect);
}
} }
} }
} }
...@@ -32319,6 +32531,14 @@ define("converse-dependencies", [ ...@@ -32319,6 +32531,14 @@ define("converse-dependencies", [
'initialize': function (settings, callback) { 'initialize': function (settings, callback) {
converse.initialize(settings, callback); converse.initialize(settings, callback);
}, },
'disconnect': function () {
converse.connection.disconnect();
},
'account': {
'logout': function () {
converse.logOut();
},
},
'settings': { 'settings': {
'get': function (key) { 'get': function (key) {
if (_.contains(Object.keys(converse.default_settings), key)) { if (_.contains(Object.keys(converse.default_settings), key)) {
...@@ -32624,7 +32844,6 @@ require.config({ ...@@ -32624,7 +32844,6 @@ require.config({
// define module dependencies for modules not using define // define module dependencies for modules not using define
shim: { shim: {
'underscore': { exports: '_' },
'crypto.aes': { deps: ['crypto.cipher-core'] }, 'crypto.aes': { deps: ['crypto.cipher-core'] },
'crypto.cipher-core': { deps: ['crypto.enc-base64', 'crypto.evpkdf'] }, 'crypto.cipher-core': { deps: ['crypto.enc-base64', 'crypto.evpkdf'] },
'crypto.enc-base64': { deps: ['crypto.core'] }, 'crypto.enc-base64': { deps: ['crypto.core'] },
This source diff could not be displayed because it is too large. You can view the blob instead.
/** /**
* @license almond 0.3.0 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license. * Available via the MIT or new BSD license.
* see: http://github.com/jrburke/almond for details * see: http://github.com/jrburke/almond for details
*/ */
...@@ -44,12 +44,6 @@ var requirejs, require, define; ...@@ -44,12 +44,6 @@ var requirejs, require, define;
//otherwise, assume it is a top-level require that will //otherwise, assume it is a top-level require that will
//be relative to baseUrl in the end. //be relative to baseUrl in the end.
if (baseName) { 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('/'); name = name.split('/');
lastIndex = name.length - 1; lastIndex = name.length - 1;
...@@ -58,7 +52,11 @@ var requirejs, require, define; ...@@ -58,7 +52,11 @@ var requirejs, require, define;
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
} }
name = baseParts.concat(name); //Lop off the last part of baseParts, so that . matches the
//"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.
name = baseParts.slice(0, baseParts.length - 1).concat(name);
//start trimDots //start trimDots
for (i = 0; i < name.length; i += 1) { for (i = 0; i < name.length; i += 1) {
...@@ -408,6 +406,9 @@ var requirejs, require, define; ...@@ -408,6 +406,9 @@ var requirejs, require, define;
requirejs._defined = defined; requirejs._defined = defined;
define = function (name, deps, callback) { define = function (name, deps, callback) {
if (typeof name !== 'string') {
throw new Error('See almond README: incorrect module build, no module name');
}
//This module may not have dependencies //This module may not have dependencies
if (!deps.splice) { if (!deps.splice) {
...@@ -11164,9 +11165,9 @@ define('text',['module'], function (module) { ...@@ -11164,9 +11165,9 @@ define('text',['module'], function (module) {
return text; return text;
}); });
// Underscore.js 1.6.0 // Underscore.js 1.8.2
// http://underscorejs.org // http://underscorejs.org
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license. // Underscore may be freely distributed under the MIT license.
(function() { (function() {
...@@ -11180,9 +11181,6 @@ define('text',['module'], function (module) { ...@@ -11180,9 +11181,6 @@ define('text',['module'], function (module) {
// Save the previous value of the `_` variable. // Save the previous value of the `_` variable.
var previousUnderscore = root._; var previousUnderscore = root._;
// Establish the object that gets returned to break out of a loop iteration.
var breaker = {};
// Save bytes in the minified (but not gzipped) version: // Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
...@@ -11190,25 +11188,19 @@ define('text',['module'], function (module) { ...@@ -11190,25 +11188,19 @@ define('text',['module'], function (module) {
var var
push = ArrayProto.push, push = ArrayProto.push,
slice = ArrayProto.slice, slice = ArrayProto.slice,
concat = ArrayProto.concat,
toString = ObjProto.toString, toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty; hasOwnProperty = ObjProto.hasOwnProperty;
// All **ECMAScript 5** native function implementations that we hope to use // All **ECMAScript 5** native function implementations that we hope to use
// are declared here. // are declared here.
var 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, nativeIsArray = Array.isArray,
nativeKeys = Object.keys, nativeKeys = Object.keys,
nativeBind = FuncProto.bind; nativeBind = FuncProto.bind,
nativeCreate = Object.create;
// Naked function reference for surrogate-prototype-swapping.
var Ctor = function(){};
// Create a safe reference to the Underscore object for use below. // Create a safe reference to the Underscore object for use below.
var _ = function(obj) { var _ = function(obj) {
...@@ -11219,8 +11211,7 @@ define('text',['module'], function (module) { ...@@ -11219,8 +11211,7 @@ define('text',['module'], function (module) {
// Export the Underscore object for **Node.js**, with // Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in // backwards-compatibility for the old `require()` API. If we're in
// the browser, add `_` as a global object via a string identifier, // the browser, add `_` as a global object.
// for Closure Compiler "advanced" mode.
if (typeof exports !== 'undefined') { if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) { if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _; exports = module.exports = _;
...@@ -11231,161 +11222,208 @@ define('text',['module'], function (module) { ...@@ -11231,161 +11222,208 @@ define('text',['module'], function (module) {
} }
// Current version. // Current version.
_.VERSION = '1.6.0'; _.VERSION = '1.8.2';
// Internal function that returns an efficient (for current engines) version
// of the passed-in callback, to be repeatedly applied in other Underscore
// functions.
var optimizeCb = function(func, context, argCount) {
if (context === void 0) return func;
switch (argCount == null ? 3 : argCount) {
case 1: return function(value) {
return func.call(context, value);
};
case 2: return function(value, other) {
return func.call(context, value, other);
};
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
};
// A mostly-internal function to generate callbacks that can be applied
// to each element in a collection, returning the desired result — either
// identity, an arbitrary callback, a property matcher, or a property accessor.
var cb = function(value, context, argCount) {
if (value == null) return _.identity;
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
if (_.isObject(value)) return _.matcher(value);
return _.property(value);
};
_.iteratee = function(value, context) {
return cb(value, context, Infinity);
};
// An internal function for creating assigner functions.
var createAssigner = function(keysFunc, undefinedOnly) {
return function(obj) {
var length = arguments.length;
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
};
// An internal function for creating a new object that inherits from another.
var baseCreate = function(prototype) {
if (!_.isObject(prototype)) return {};
if (nativeCreate) return nativeCreate(prototype);
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
// Helper for collection methods to determine whether a collection
// should be iterated as an array or as an object
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var isArrayLike = function(collection) {
var length = collection && collection.length;
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
// Collection Functions // Collection Functions
// -------------------- // --------------------
// The cornerstone, an `each` implementation, aka `forEach`. // The cornerstone, an `each` implementation, aka `forEach`.
// Handles objects with the built-in `forEach`, arrays, and raw objects. // Handles raw objects in addition to array-likes. Treats all
// Delegates to **ECMAScript 5**'s native `forEach` if available. // sparse array-likes as if they were dense.
var each = _.each = _.forEach = function(obj, iterator, context) { _.each = _.forEach = function(obj, iteratee, context) {
if (obj == null) return obj; iteratee = optimizeCb(iteratee, context);
if (nativeForEach && obj.forEach === nativeForEach) { var i, length;
obj.forEach(iterator, context); if (isArrayLike(obj)) {
} else if (obj.length === +obj.length) { for (i = 0, length = obj.length; i < length; i++) {
for (var i = 0, length = obj.length; i < length; i++) { iteratee(obj[i], i, obj);
if (iterator.call(context, obj[i], i, obj) === breaker) return;
} }
} else { } else {
var keys = _.keys(obj); var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) { for (i = 0, length = keys.length; i < length; i++) {
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; iteratee(obj[keys[i]], keys[i], obj);
} }
} }
return obj; return obj;
}; };
// Return the results of applying the iterator to each element. // Return the results of applying the iteratee to each element.
// Delegates to **ECMAScript 5**'s native `map` if available. _.map = _.collect = function(obj, iteratee, context) {
_.map = _.collect = function(obj, iterator, context) { iteratee = cb(iteratee, context);
var results = []; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return results; length = (keys || obj).length,
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); results = Array(length);
each(obj, function(value, index, list) { for (var index = 0; index < length; index++) {
results.push(iterator.call(context, value, index, list)); var currentKey = keys ? keys[index] : index;
}); results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results; return results;
}; };
var reduceError = 'Reduce of empty array with no initial value'; // Create a reducing function iterating left or right.
function createReduce(dir) {
// **Reduce** builds up a single result from a list of values, aka `inject`, // Optimized iterator function as using arguments.length
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. // in the main function will deoptimize the, see #1991.
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { function iterator(obj, iteratee, memo, keys, index, length) {
var initial = arguments.length > 2; for (; index >= 0 && index < length; index += dir) {
if (obj == null) obj = []; var currentKey = keys ? keys[index] : index;
if (nativeReduce && obj.reduce === nativeReduce) { memo = iteratee(memo, obj[currentKey], currentKey, obj);
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
}
each(obj, function(value, index, list) {
if (!initial) {
memo = value;
initial = true;
} else {
memo = iterator.call(context, memo, value, index, list);
} }
});
if (!initial) throw new TypeError(reduceError);
return memo; return memo;
};
// The right-associative version of reduce, also known as `foldr`.
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
var initial = arguments.length > 2;
if (obj == null) obj = [];
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
}
var length = obj.length;
if (length !== +length) {
var keys = _.keys(obj);
length = keys.length;
} }
each(obj, function(value, index, list) {
index = keys ? keys[--length] : --length; return function(obj, iteratee, memo, context) {
if (!initial) { iteratee = optimizeCb(iteratee, context, 4);
memo = obj[index]; var keys = !isArrayLike(obj) && _.keys(obj),
initial = true; length = (keys || obj).length,
} else { index = dir > 0 ? 0 : length - 1;
memo = iterator.call(context, memo, obj[index], index, list); // Determine the initial value if none is provided.
if (arguments.length < 3) {
memo = obj[keys ? keys[index] : index];
index += dir;
} }
}); return iterator(obj, iteratee, memo, keys, index, length);
if (!initial) throw new TypeError(reduceError);
return memo;
}; };
}
// **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`.
_.reduce = _.foldl = _.inject = createReduce(1);
// The right-associative version of reduce, also known as `foldr`.
_.reduceRight = _.foldr = createReduce(-1);
// Return the first value which passes a truth test. Aliased as `detect`. // Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function(obj, predicate, context) { _.find = _.detect = function(obj, predicate, context) {
var result; var key;
any(obj, function(value, index, list) { if (isArrayLike(obj)) {
if (predicate.call(context, value, index, list)) { key = _.findIndex(obj, predicate, context);
result = value; } else {
return true; key = _.findKey(obj, predicate, context);
} }
}); if (key !== void 0 && key !== -1) return obj[key];
return result;
}; };
// Return all the elements that pass a truth test. // Return all the elements that pass a truth test.
// Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`. // Aliased as `select`.
_.filter = _.select = function(obj, predicate, context) { _.filter = _.select = function(obj, predicate, context) {
var results = []; var results = [];
if (obj == null) return results; predicate = cb(predicate, context);
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); _.each(obj, function(value, index, list) {
each(obj, function(value, index, list) { if (predicate(value, index, list)) results.push(value);
if (predicate.call(context, value, index, list)) results.push(value);
}); });
return results; return results;
}; };
// Return all the elements for which a truth test fails. // Return all the elements for which a truth test fails.
_.reject = function(obj, predicate, context) { _.reject = function(obj, predicate, context) {
return _.filter(obj, function(value, index, list) { return _.filter(obj, _.negate(cb(predicate)), context);
return !predicate.call(context, value, index, list);
}, context);
}; };
// Determine whether all of the elements match a truth test. // Determine whether all of the elements match a truth test.
// Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`. // Aliased as `all`.
_.every = _.all = function(obj, predicate, context) { _.every = _.all = function(obj, predicate, context) {
predicate || (predicate = _.identity); predicate = cb(predicate, context);
var result = true; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return result; length = (keys || obj).length;
if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); for (var index = 0; index < length; index++) {
each(obj, function(value, index, list) { var currentKey = keys ? keys[index] : index;
if (!(result = result && predicate.call(context, value, index, list))) return breaker; if (!predicate(obj[currentKey], currentKey, obj)) return false;
}); }
return !!result; return true;
}; };
// Determine if at least one element in the object matches a truth test. // Determine if at least one element in the object matches a truth test.
// Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`. // Aliased as `any`.
var any = _.some = _.any = function(obj, predicate, context) { _.some = _.any = function(obj, predicate, context) {
predicate || (predicate = _.identity); predicate = cb(predicate, context);
var result = false; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return result; length = (keys || obj).length;
if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); for (var index = 0; index < length; index++) {
each(obj, function(value, index, list) { var currentKey = keys ? keys[index] : index;
if (result || (result = predicate.call(context, value, index, list))) return breaker; if (predicate(obj[currentKey], currentKey, obj)) return true;
}); }
return !!result; return false;
}; };
// Determine if the array or object contains a given value (using `===`). // Determine if the array or object contains a given value (using `===`).
// Aliased as `include`. // Aliased as `includes` and `include`.
_.contains = _.include = function(obj, target) { _.contains = _.includes = _.include = function(obj, target, fromIndex) {
if (obj == null) return false; if (!isArrayLike(obj)) obj = _.values(obj);
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; return _.indexOf(obj, target, typeof fromIndex == 'number' && fromIndex) >= 0;
return any(obj, function(value) {
return value === target;
});
}; };
// Invoke a method (with arguments) on every item in a collection. // Invoke a method (with arguments) on every item in a collection.
...@@ -11393,7 +11431,8 @@ define('text',['module'], function (module) { ...@@ -11393,7 +11431,8 @@ define('text',['module'], function (module) {
var args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
var isFunc = _.isFunction(method); var isFunc = _.isFunction(method);
return _.map(obj, function(value) { return _.map(obj, function(value) {
return (isFunc ? method : value[method]).apply(value, args); var func = isFunc ? method : value[method];
return func == null ? func : func.apply(value, args);
}); });
}; };
...@@ -11405,60 +11444,76 @@ define('text',['module'], function (module) { ...@@ -11405,60 +11444,76 @@ define('text',['module'], function (module) {
// Convenience version of a common use case of `filter`: selecting only objects // Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs. // containing specific `key:value` pairs.
_.where = function(obj, attrs) { _.where = function(obj, attrs) {
return _.filter(obj, _.matches(attrs)); return _.filter(obj, _.matcher(attrs));
}; };
// Convenience version of a common use case of `find`: getting the first object // Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs. // containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) { _.findWhere = function(obj, attrs) {
return _.find(obj, _.matches(attrs)); return _.find(obj, _.matcher(attrs));
}; };
// Return the maximum element or (element-based computation). // Return the maximum element (or element-based computation).
// Can't optimize arrays of integers longer than 65,535 elements. _.max = function(obj, iteratee, context) {
// See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) var result = -Infinity, lastComputed = -Infinity,
_.max = function(obj, iterator, context) { value, computed;
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { if (iteratee == null && obj != null) {
return Math.max.apply(Math, obj); obj = isArrayLike(obj) ? obj : _.values(obj);
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value > result) {
result = value;
}
} }
var result = -Infinity, lastComputed = -Infinity; } else {
each(obj, function(value, index, list) { iteratee = cb(iteratee, context);
var computed = iterator ? iterator.call(context, value, index, list) : value; _.each(obj, function(value, index, list) {
if (computed > lastComputed) { computed = iteratee(value, index, list);
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
result = value; result = value;
lastComputed = computed; lastComputed = computed;
} }
}); });
}
return result; return result;
}; };
// Return the minimum element (or element-based computation). // Return the minimum element (or element-based computation).
_.min = function(obj, iterator, context) { _.min = function(obj, iteratee, context) {
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { var result = Infinity, lastComputed = Infinity,
return Math.min.apply(Math, obj); value, computed;
} if (iteratee == null && obj != null) {
var result = Infinity, lastComputed = Infinity; obj = isArrayLike(obj) ? obj : _.values(obj);
each(obj, function(value, index, list) { for (var i = 0, length = obj.length; i < length; i++) {
var computed = iterator ? iterator.call(context, value, index, list) : value; value = obj[i];
if (computed < lastComputed) { if (value < result) {
result = value;
}
}
} else {
iteratee = cb(iteratee, context);
_.each(obj, function(value, index, list) {
computed = iteratee(value, index, list);
if (computed < lastComputed || computed === Infinity && result === Infinity) {
result = value; result = value;
lastComputed = computed; lastComputed = computed;
} }
}); });
}
return result; return result;
}; };
// Shuffle an array, using the modern version of the // Shuffle a collection, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_.shuffle = function(obj) { _.shuffle = function(obj) {
var rand; var set = isArrayLike(obj) ? obj : _.values(obj);
var index = 0; var length = set.length;
var shuffled = []; var shuffled = Array(length);
each(obj, function(value) { for (var index = 0, rand; index < length; index++) {
rand = _.random(index++); rand = _.random(0, index);
shuffled[index - 1] = shuffled[rand]; if (rand !== index) shuffled[index] = shuffled[rand];
shuffled[rand] = value; shuffled[rand] = set[index];
}); }
return shuffled; return shuffled;
}; };
...@@ -11467,27 +11522,20 @@ define('text',['module'], function (module) { ...@@ -11467,27 +11522,20 @@ define('text',['module'], function (module) {
// The internal `guard` argument allows it to work with `map`. // The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) { _.sample = function(obj, n, guard) {
if (n == null || guard) { if (n == null || guard) {
if (obj.length !== +obj.length) obj = _.values(obj); if (!isArrayLike(obj)) obj = _.values(obj);
return obj[_.random(obj.length - 1)]; return obj[_.random(obj.length - 1)];
} }
return _.shuffle(obj).slice(0, Math.max(0, n)); return _.shuffle(obj).slice(0, Math.max(0, n));
}; };
// An internal function to generate lookup iterators. // Sort the object's values by a criterion produced by an iteratee.
var lookupIterator = function(value) { _.sortBy = function(obj, iteratee, context) {
if (value == null) return _.identity; iteratee = cb(iteratee, context);
if (_.isFunction(value)) return value;
return _.property(value);
};
// Sort the object's values by a criterion produced by an iterator.
_.sortBy = function(obj, iterator, context) {
iterator = lookupIterator(iterator);
return _.pluck(_.map(obj, function(value, index, list) { return _.pluck(_.map(obj, function(value, index, list) {
return { return {
value: value, value: value,
index: index, index: index,
criteria: iterator.call(context, value, index, list) criteria: iteratee(value, index, list)
}; };
}).sort(function(left, right) { }).sort(function(left, right) {
var a = left.criteria; var a = left.criteria;
...@@ -11502,12 +11550,12 @@ define('text',['module'], function (module) { ...@@ -11502,12 +11550,12 @@ define('text',['module'], function (module) {
// An internal function used for aggregate "group by" operations. // An internal function used for aggregate "group by" operations.
var group = function(behavior) { var group = function(behavior) {
return function(obj, iterator, context) { return function(obj, iteratee, context) {
var result = {}; var result = {};
iterator = lookupIterator(iterator); iteratee = cb(iteratee, context);
each(obj, function(value, index) { _.each(obj, function(value, index) {
var key = iterator.call(context, value, index, obj); var key = iteratee(value, index, obj);
behavior(result, key, value); behavior(result, value, key);
}); });
return result; return result;
}; };
...@@ -11515,48 +11563,46 @@ define('text',['module'], function (module) { ...@@ -11515,48 +11563,46 @@ define('text',['module'], function (module) {
// Groups the object's values by a criterion. Pass either a string attribute // Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion. // to group by, or a function that returns the criterion.
_.groupBy = group(function(result, key, value) { _.groupBy = group(function(result, value, key) {
_.has(result, key) ? result[key].push(value) : result[key] = [value]; if (_.has(result, key)) result[key].push(value); else result[key] = [value];
}); });
// Indexes the object's values by a criterion, similar to `groupBy`, but for // Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique. // when you know that your index values will be unique.
_.indexBy = group(function(result, key, value) { _.indexBy = group(function(result, value, key) {
result[key] = value; result[key] = value;
}); });
// Counts instances of an object that group by a certain criterion. Pass // Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the // either a string attribute to count by, or a function that returns the
// criterion. // criterion.
_.countBy = group(function(result, key) { _.countBy = group(function(result, value, key) {
_.has(result, key) ? result[key]++ : result[key] = 1; if (_.has(result, key)) result[key]++; else result[key] = 1;
}); });
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iterator, context) {
iterator = lookupIterator(iterator);
var value = iterator.call(context, obj);
var low = 0, high = array.length;
while (low < high) {
var mid = (low + high) >>> 1;
iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
}
return low;
};
// Safely create a real, live array from anything iterable. // Safely create a real, live array from anything iterable.
_.toArray = function(obj) { _.toArray = function(obj) {
if (!obj) return []; if (!obj) return [];
if (_.isArray(obj)) return slice.call(obj); if (_.isArray(obj)) return slice.call(obj);
if (obj.length === +obj.length) return _.map(obj, _.identity); if (isArrayLike(obj)) return _.map(obj, _.identity);
return _.values(obj); return _.values(obj);
}; };
// Return the number of elements in an object. // Return the number of elements in an object.
_.size = function(obj) { _.size = function(obj) {
if (obj == null) return 0; if (obj == null) return 0;
return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; return isArrayLike(obj) ? obj.length : _.keys(obj).length;
};
// Split a collection into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(obj, predicate, context) {
predicate = cb(predicate, context);
var pass = [], fail = [];
_.each(obj, function(value, key, obj) {
(predicate(value, key, obj) ? pass : fail).push(value);
});
return [pass, fail];
}; };
// Array Functions // Array Functions
...@@ -11567,33 +11613,30 @@ define('text',['module'], function (module) { ...@@ -11567,33 +11613,30 @@ define('text',['module'], function (module) {
// allows it to work with `_.map`. // allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) { _.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0; if (array == null) return void 0;
if ((n == null) || guard) return array[0]; if (n == null || guard) return array[0];
if (n < 0) return []; return _.initial(array, array.length - n);
return slice.call(array, 0, n);
}; };
// Returns everything but the last entry of the array. Especially useful on // Returns everything but the last entry of the array. Especially useful on
// the arguments object. Passing **n** will return all the values in // the arguments object. Passing **n** will return all the values in
// the array, excluding the last N. The **guard** check allows it to work with // the array, excluding the last N.
// `_.map`.
_.initial = function(array, n, guard) { _.initial = function(array, n, guard) {
return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
}; };
// Get the last element of an array. Passing **n** will return the last N // Get the last element of an array. Passing **n** will return the last N
// values in the array. The **guard** check allows it to work with `_.map`. // values in the array.
_.last = function(array, n, guard) { _.last = function(array, n, guard) {
if (array == null) return void 0; if (array == null) return void 0;
if ((n == null) || guard) return array[array.length - 1]; if (n == null || guard) return array[array.length - 1];
return slice.call(array, Math.max(array.length - n, 0)); return _.rest(array, Math.max(0, array.length - n));
}; };
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`. // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
// Especially useful on the arguments object. Passing an **n** will return // Especially useful on the arguments object. Passing an **n** will return
// the rest N values in the array. The **guard** // the rest N values in the array.
// check allows it to work with `_.map`.
_.rest = _.tail = _.drop = function(array, n, guard) { _.rest = _.tail = _.drop = function(array, n, guard) {
return slice.call(array, (n == null) || guard ? 1 : n); return slice.call(array, n == null || guard ? 1 : n);
}; };
// Trim out all falsy values from an array. // Trim out all falsy values from an array.
...@@ -11602,23 +11645,28 @@ define('text',['module'], function (module) { ...@@ -11602,23 +11645,28 @@ define('text',['module'], function (module) {
}; };
// Internal implementation of a recursive `flatten` function. // Internal implementation of a recursive `flatten` function.
var flatten = function(input, shallow, output) { var flatten = function(input, shallow, strict, startIndex) {
if (shallow && _.every(input, _.isArray)) { var output = [], idx = 0;
return concat.apply(output, input); for (var i = startIndex || 0, length = input && input.length; i < length; i++) {
var value = input[i];
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
//flatten current level of array or arguments object
if (!shallow) value = flatten(value, shallow, strict);
var j = 0, len = value.length;
output.length += len;
while (j < len) {
output[idx++] = value[j++];
}
} else if (!strict) {
output[idx++] = value;
} }
each(input, function(value) {
if (_.isArray(value) || _.isArguments(value)) {
shallow ? push.apply(output, value) : flatten(value, shallow, output);
} else {
output.push(value);
} }
});
return output; return output;
}; };
// Flatten out an array, either recursively (by default), or just one level. // Flatten out an array, either recursively (by default), or just one level.
_.flatten = function(array, shallow) { _.flatten = function(array, shallow) {
return flatten(array, shallow, []); return flatten(array, shallow, false);
}; };
// Return a version of the array that does not contain the specified value(s). // Return a version of the array that does not contain the specified value(s).
...@@ -11626,79 +11674,93 @@ define('text',['module'], function (module) { ...@@ -11626,79 +11674,93 @@ define('text',['module'], function (module) {
return _.difference(array, slice.call(arguments, 1)); return _.difference(array, slice.call(arguments, 1));
}; };
// Split an array into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(array, predicate) {
var pass = [], fail = [];
each(array, function(elem) {
(predicate(elem) ? pass : fail).push(elem);
});
return [pass, fail];
};
// Produce a duplicate-free version of the array. If the array has already // Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm. // been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`. // Aliased as `unique`.
_.uniq = _.unique = function(array, isSorted, iterator, context) { _.uniq = _.unique = function(array, isSorted, iteratee, context) {
if (_.isFunction(isSorted)) { if (array == null) return [];
context = iterator; if (!_.isBoolean(isSorted)) {
iterator = isSorted; context = iteratee;
iteratee = isSorted;
isSorted = false; isSorted = false;
} }
var initial = iterator ? _.map(array, iterator, context) : array; if (iteratee != null) iteratee = cb(iteratee, context);
var results = []; var result = [];
var seen = []; var seen = [];
each(initial, function(value, index) { for (var i = 0, length = array.length; i < length; i++) {
if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { var value = array[i],
seen.push(value); computed = iteratee ? iteratee(value, i, array) : value;
results.push(array[index]); if (isSorted) {
if (!i || seen !== computed) result.push(value);
seen = computed;
} else if (iteratee) {
if (!_.contains(seen, computed)) {
seen.push(computed);
result.push(value);
} }
}); } else if (!_.contains(result, value)) {
return results; result.push(value);
}
}
return result;
}; };
// Produce an array that contains the union: each distinct element from all of // Produce an array that contains the union: each distinct element from all of
// the passed-in arrays. // the passed-in arrays.
_.union = function() { _.union = function() {
return _.uniq(_.flatten(arguments, true)); return _.uniq(flatten(arguments, true, true));
}; };
// Produce an array that contains every item shared between all the // Produce an array that contains every item shared between all the
// passed-in arrays. // passed-in arrays.
_.intersection = function(array) { _.intersection = function(array) {
var rest = slice.call(arguments, 1); if (array == null) return [];
return _.filter(_.uniq(array), function(item) { var result = [];
return _.every(rest, function(other) { var argsLength = arguments.length;
return _.contains(other, item); for (var i = 0, length = array.length; i < length; i++) {
}); var item = array[i];
}); if (_.contains(result, item)) continue;
for (var j = 1; j < argsLength; j++) {
if (!_.contains(arguments[j], item)) break;
}
if (j === argsLength) result.push(item);
}
return result;
}; };
// Take the difference between one array and a number of other arrays. // Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain. // Only the elements present in just the first array will remain.
_.difference = function(array) { _.difference = function(array) {
var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); var rest = flatten(arguments, true, true, 1);
return _.filter(array, function(value){ return !_.contains(rest, value); }); return _.filter(array, function(value){
return !_.contains(rest, value);
});
}; };
// Zip together multiple lists into a single array -- elements that share // Zip together multiple lists into a single array -- elements that share
// an index go together. // an index go together.
_.zip = function() { _.zip = function() {
var length = _.max(_.pluck(arguments, 'length').concat(0)); return _.unzip(arguments);
var results = new Array(length); };
for (var i = 0; i < length; i++) {
results[i] = _.pluck(arguments, '' + i); // Complement of _.zip. Unzip accepts an array of arrays and groups
// each array's elements on shared indices
_.unzip = function(array) {
var length = array && _.max(array, 'length').length || 0;
var result = Array(length);
for (var index = 0; index < length; index++) {
result[index] = _.pluck(array, index);
} }
return results; return result;
}; };
// Converts lists into objects. Pass either a single array of `[key, value]` // Converts lists into objects. Pass either a single array of `[key, value]`
// pairs, or two parallel arrays of the same length -- one of keys, and one of // pairs, or two parallel arrays of the same length -- one of keys, and one of
// the corresponding values. // the corresponding values.
_.object = function(list, values) { _.object = function(list, values) {
if (list == null) return {};
var result = {}; var result = {};
for (var i = 0, length = list.length; i < length; i++) { for (var i = 0, length = list && list.length; i < length; i++) {
if (values) { if (values) {
result[list[i]] = values[i]; result[list[i]] = values[i];
} else { } else {
...@@ -11708,40 +11770,68 @@ define('text',['module'], function (module) { ...@@ -11708,40 +11770,68 @@ define('text',['module'], function (module) {
return result; return result;
}; };
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), // Return the position of the first occurrence of an item in an array,
// we need this function. Return the position of the first occurrence of an // or -1 if the item is not included in the array.
// item in an array, or -1 if the item is not included in the array.
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
// If the array is large and already in sort order, pass `true` // If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search. // for **isSorted** to use binary search.
_.indexOf = function(array, item, isSorted) { _.indexOf = function(array, item, isSorted) {
if (array == null) return -1; var i = 0, length = array && array.length;
var i = 0, length = array.length;
if (isSorted) {
if (typeof isSorted == 'number') { if (typeof isSorted == 'number') {
i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
} else { } else if (isSorted && length) {
i = _.sortedIndex(array, item); i = _.sortedIndex(array, item);
return array[i] === item ? i : -1; return array[i] === item ? i : -1;
} }
if (item !== item) {
return _.findIndex(slice.call(array, i), _.isNaN);
} }
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
for (; i < length; i++) if (array[i] === item) return i; for (; i < length; i++) if (array[i] === item) return i;
return -1; return -1;
}; };
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
_.lastIndexOf = function(array, item, from) { _.lastIndexOf = function(array, item, from) {
if (array == null) return -1; var idx = array ? array.length : 0;
var hasIndex = from != null; if (typeof from == 'number') {
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); }
if (item !== item) {
return _.findLastIndex(slice.call(array, 0, idx), _.isNaN);
} }
var i = (hasIndex ? from : array.length); while (--idx >= 0) if (array[idx] === item) return idx;
while (i--) if (array[i] === item) return i;
return -1; return -1;
}; };
// Generator function to create the findIndex and findLastIndex functions
function createIndexFinder(dir) {
return function(array, predicate, context) {
predicate = cb(predicate, context);
var length = array != null && array.length;
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
}
// Returns the first index on an array-like that passes a predicate test
_.findIndex = createIndexFinder(1);
_.findLastIndex = createIndexFinder(-1);
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iteratee, context) {
iteratee = cb(iteratee, context, 1);
var value = iteratee(obj);
var low = 0, high = array.length;
while (low < high) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
};
// Generate an integer Array containing an arithmetic progression. A port of // Generate an integer Array containing an arithmetic progression. A port of
// the native Python `range()` function. See // the native Python `range()` function. See
// [the Python documentation](http://docs.python.org/library/functions.html#range). // [the Python documentation](http://docs.python.org/library/functions.html#range).
...@@ -11750,15 +11840,13 @@ define('text',['module'], function (module) { ...@@ -11750,15 +11840,13 @@ define('text',['module'], function (module) {
stop = start || 0; stop = start || 0;
start = 0; start = 0;
} }
step = arguments[2] || 1; step = step || 1;
var length = Math.max(Math.ceil((stop - start) / step), 0); var length = Math.max(Math.ceil((stop - start) / step), 0);
var idx = 0; var range = Array(length);
var range = new Array(length);
while(idx < length) { for (var idx = 0; idx < length; idx++, start += step) {
range[idx++] = start; range[idx] = start;
start += step;
} }
return range; return range;
...@@ -11767,26 +11855,27 @@ define('text',['module'], function (module) { ...@@ -11767,26 +11855,27 @@ define('text',['module'], function (module) {
// Function (ahem) Functions // Function (ahem) Functions
// ------------------ // ------------------
// Reusable constructor function for prototype setting. // Determines whether to execute a function as a constructor
var ctor = function(){}; // or a normal function with the provided arguments
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
var self = baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
if (_.isObject(result)) return result;
return self;
};
// Create a function bound to a given object (assigning `this`, and arguments, // Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
// available. // available.
_.bind = function(func, context) { _.bind = function(func, context) {
var args, bound;
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError; if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
return bound = function() { var bound = function() {
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
ctor.prototype = func.prototype;
var self = new ctor;
ctor.prototype = null;
var result = func.apply(self, args.concat(slice.call(arguments)));
if (Object(result) === result) return result;
return self;
}; };
return bound;
}; };
// Partially apply a function by creating a version that has had some of its // Partially apply a function by creating a version that has had some of its
...@@ -11794,49 +11883,55 @@ define('text',['module'], function (module) { ...@@ -11794,49 +11883,55 @@ define('text',['module'], function (module) {
// as a placeholder, allowing any combination of arguments to be pre-filled. // as a placeholder, allowing any combination of arguments to be pre-filled.
_.partial = function(func) { _.partial = function(func) {
var boundArgs = slice.call(arguments, 1); var boundArgs = slice.call(arguments, 1);
return function() { var bound = function() {
var position = 0; var position = 0, length = boundArgs.length;
var args = boundArgs.slice(); var args = Array(length);
for (var i = 0, length = args.length; i < length; i++) { for (var i = 0; i < length; i++) {
if (args[i] === _) args[i] = arguments[position++]; args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
} }
while (position < arguments.length) args.push(arguments[position++]); while (position < arguments.length) args.push(arguments[position++]);
return func.apply(this, args); return executeBound(func, bound, this, this, args);
}; };
return bound;
}; };
// Bind a number of an object's methods to that object. Remaining arguments // Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks // are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it. // defined on an object belong to it.
_.bindAll = function(obj) { _.bindAll = function(obj) {
var funcs = slice.call(arguments, 1); var i, length = arguments.length, key;
if (funcs.length === 0) throw new Error('bindAll must be passed function names'); if (length <= 1) throw new Error('bindAll must be passed function names');
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); for (i = 1; i < length; i++) {
key = arguments[i];
obj[key] = _.bind(obj[key], obj);
}
return obj; return obj;
}; };
// Memoize an expensive function by storing its results. // Memoize an expensive function by storing its results.
_.memoize = function(func, hasher) { _.memoize = function(func, hasher) {
var memo = {}; var memoize = function(key) {
hasher || (hasher = _.identity); var cache = memoize.cache;
return function() { var address = '' + (hasher ? hasher.apply(this, arguments) : key);
var key = hasher.apply(this, arguments); if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); return cache[address];
}; };
memoize.cache = {};
return memoize;
}; };
// Delays a function for the given number of milliseconds, and then calls // Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied. // it with the arguments supplied.
_.delay = function(func, wait) { _.delay = function(func, wait) {
var args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
return setTimeout(function(){ return func.apply(null, args); }, wait); return setTimeout(function(){
return func.apply(null, args);
}, wait);
}; };
// Defers a function, scheduling it to run after the current call stack has // Defers a function, scheduling it to run after the current call stack has
// cleared. // cleared.
_.defer = function(func) { _.defer = _.partial(_.delay, _, 1);
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
};
// Returns a function, that, when invoked, will only be triggered at most once // Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run // during a given window of time. Normally, the throttled function will run
...@@ -11847,12 +11942,12 @@ define('text',['module'], function (module) { ...@@ -11847,12 +11942,12 @@ define('text',['module'], function (module) {
var context, args, result; var context, args, result;
var timeout = null; var timeout = null;
var previous = 0; var previous = 0;
options || (options = {}); if (!options) options = {};
var later = function() { var later = function() {
previous = options.leading === false ? 0 : _.now(); previous = options.leading === false ? 0 : _.now();
timeout = null; timeout = null;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
}; };
return function() { return function() {
var now = _.now(); var now = _.now();
...@@ -11860,12 +11955,14 @@ define('text',['module'], function (module) { ...@@ -11860,12 +11955,14 @@ define('text',['module'], function (module) {
var remaining = wait - (now - previous); var remaining = wait - (now - previous);
context = this; context = this;
args = arguments; args = arguments;
if (remaining <= 0) { if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout); clearTimeout(timeout);
timeout = null; timeout = null;
}
previous = now; previous = now;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) { } else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining); timeout = setTimeout(later, remaining);
} }
...@@ -11882,13 +11979,14 @@ define('text',['module'], function (module) { ...@@ -11882,13 +11979,14 @@ define('text',['module'], function (module) {
var later = function() { var later = function() {
var last = _.now() - timestamp; var last = _.now() - timestamp;
if (last < wait) {
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last); timeout = setTimeout(later, wait - last);
} else { } else {
timeout = null; timeout = null;
if (!immediate) { if (!immediate) {
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
} }
} }
}; };
...@@ -11898,9 +11996,7 @@ define('text',['module'], function (module) { ...@@ -11898,9 +11996,7 @@ define('text',['module'], function (module) {
args = arguments; args = arguments;
timestamp = _.now(); timestamp = _.now();
var callNow = immediate && !timeout; var callNow = immediate && !timeout;
if (!timeout) { if (!timeout) timeout = setTimeout(later, wait);
timeout = setTimeout(later, wait);
}
if (callNow) { if (callNow) {
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; context = args = null;
...@@ -11910,19 +12006,6 @@ define('text',['module'], function (module) { ...@@ -11910,19 +12006,6 @@ define('text',['module'], function (module) {
}; };
}; };
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
// Returns the first function passed as an argument to the second, // Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and // allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function. // conditionally execute the original function.
...@@ -11930,20 +12013,27 @@ define('text',['module'], function (module) { ...@@ -11930,20 +12013,27 @@ define('text',['module'], function (module) {
return _.partial(wrapper, func); return _.partial(wrapper, func);
}; };
// Returns a negated version of the passed-in predicate.
_.negate = function(predicate) {
return function() {
return !predicate.apply(this, arguments);
};
};
// Returns a function that is the composition of a list of functions, each // Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows. // consuming the return value of the function that follows.
_.compose = function() { _.compose = function() {
var funcs = arguments;
return function() {
var args = arguments; var args = arguments;
for (var i = funcs.length - 1; i >= 0; i--) { var start = args.length - 1;
args = [funcs[i].apply(this, args)]; return function() {
} var i = start;
return args[0]; var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
}; };
}; };
// Returns a function that will only be executed after being called N times. // Returns a function that will only be executed on and after the Nth call.
_.after = function(times, func) { _.after = function(times, func) {
return function() { return function() {
if (--times < 1) { if (--times < 1) {
...@@ -11952,16 +12042,66 @@ define('text',['module'], function (module) { ...@@ -11952,16 +12042,66 @@ define('text',['module'], function (module) {
}; };
}; };
// Returns a function that will only be executed up to (but not including) the Nth call.
_.before = function(times, func) {
var memo;
return function() {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
};
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = _.partial(_.before, 2);
// Object Functions // Object Functions
// ---------------- // ----------------
// Retrieve the names of an object's properties. // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
function collectNonEnumProps(obj, keys) {
var nonEnumIdx = nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
// Constructor is a special case.
var prop = 'constructor';
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
while (nonEnumIdx--) {
prop = nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
keys.push(prop);
}
}
}
// Retrieve the names of an object's own properties.
// Delegates to **ECMAScript 5**'s native `Object.keys` // Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = function(obj) { _.keys = function(obj) {
if (!_.isObject(obj)) return []; if (!_.isObject(obj)) return [];
if (nativeKeys) return nativeKeys(obj); if (nativeKeys) return nativeKeys(obj);
var keys = []; var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key); for (var key in obj) if (_.has(obj, key)) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Retrieve all the property names of an object.
_.allKeys = function(obj) {
if (!_.isObject(obj)) return [];
var keys = [];
for (var key in obj) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys; return keys;
}; };
...@@ -11969,18 +12109,33 @@ define('text',['module'], function (module) { ...@@ -11969,18 +12109,33 @@ define('text',['module'], function (module) {
_.values = function(obj) { _.values = function(obj) {
var keys = _.keys(obj); var keys = _.keys(obj);
var length = keys.length; var length = keys.length;
var values = new Array(length); var values = Array(length);
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]]; values[i] = obj[keys[i]];
} }
return values; return values;
}; };
// Returns the results of applying the iteratee to each element of the object
// In contrast to _.map it returns an object
_.mapObject = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = _.keys(obj),
length = keys.length,
results = {},
currentKey;
for (var index = 0; index < length; index++) {
currentKey = keys[index];
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
// Convert an object into a list of `[key, value]` pairs. // Convert an object into a list of `[key, value]` pairs.
_.pairs = function(obj) { _.pairs = function(obj) {
var keys = _.keys(obj); var keys = _.keys(obj);
var length = keys.length; var length = keys.length;
var pairs = new Array(length); var pairs = Array(length);
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]]; pairs[i] = [keys[i], obj[keys[i]]];
} }
...@@ -12008,48 +12163,57 @@ define('text',['module'], function (module) { ...@@ -12008,48 +12163,57 @@ define('text',['module'], function (module) {
}; };
// Extend a given object with all the properties in passed-in object(s). // Extend a given object with all the properties in passed-in object(s).
_.extend = function(obj) { _.extend = createAssigner(_.allKeys);
each(slice.call(arguments, 1), function(source) {
if (source) { // Assigns a given object with all the own properties in the passed-in object(s)
for (var prop in source) { // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
obj[prop] = source[prop]; _.extendOwn = _.assign = createAssigner(_.keys);
}
// Returns the first key on an object that passes a predicate test
_.findKey = function(obj, predicate, context) {
predicate = cb(predicate, context);
var keys = _.keys(obj), key;
for (var i = 0, length = keys.length; i < length; i++) {
key = keys[i];
if (predicate(obj[key], key, obj)) return key;
} }
});
return obj;
}; };
// Return a copy of the object only containing the whitelisted properties. // Return a copy of the object only containing the whitelisted properties.
_.pick = function(obj) { _.pick = function(object, oiteratee, context) {
var copy = {}; var result = {}, obj = object, iteratee, keys;
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); if (obj == null) return result;
each(keys, function(key) { if (_.isFunction(oiteratee)) {
if (key in obj) copy[key] = obj[key]; keys = _.allKeys(obj);
}); iteratee = optimizeCb(oiteratee, context);
return copy; } else {
keys = flatten(arguments, false, false, 1);
iteratee = function(value, key, obj) { return key in obj; };
obj = Object(obj);
}
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
var value = obj[key];
if (iteratee(value, key, obj)) result[key] = value;
}
return result;
}; };
// Return a copy of the object without the blacklisted properties. // Return a copy of the object without the blacklisted properties.
_.omit = function(obj) { _.omit = function(obj, iteratee, context) {
var copy = {}; if (_.isFunction(iteratee)) {
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); iteratee = _.negate(iteratee);
for (var key in obj) { } else {
if (!_.contains(keys, key)) copy[key] = obj[key]; var keys = _.map(flatten(arguments, false, false, 1), String);
iteratee = function(value, key) {
return !_.contains(keys, key);
};
} }
return copy; return _.pick(obj, iteratee, context);
}; };
// Fill in a given object with default properties. // Fill in a given object with default properties.
_.defaults = function(obj) { _.defaults = createAssigner(_.allKeys, true);
each(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) {
if (obj[prop] === void 0) obj[prop] = source[prop];
}
}
});
return obj;
};
// Create a (shallow-cloned) duplicate of an object. // Create a (shallow-cloned) duplicate of an object.
_.clone = function(obj) { _.clone = function(obj) {
...@@ -12065,11 +12229,24 @@ define('text',['module'], function (module) { ...@@ -12065,11 +12229,24 @@ define('text',['module'], function (module) {
return obj; return obj;
}; };
// Returns whether an object has a given set of `key:value` pairs.
_.isMatch = function(object, attrs) {
var keys = _.keys(attrs), length = keys.length;
if (object == null) return !length;
var obj = Object(object);
for (var i = 0; i < length; i++) {
var key = keys[i];
if (attrs[key] !== obj[key] || !(key in obj)) return false;
}
return true;
};
// Internal recursive comparison function for `isEqual`. // Internal recursive comparison function for `isEqual`.
var eq = function(a, b, aStack, bStack) { var eq = function(a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical. // Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a == 1 / b; if (a === b) return a !== 0 || 1 / a === 1 / b;
// A strict comparison is necessary because `null == undefined`. // A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b; if (a == null || b == null) return a === b;
// Unwrap any wrapped objects. // Unwrap any wrapped objects.
...@@ -12077,98 +12254,98 @@ define('text',['module'], function (module) { ...@@ -12077,98 +12254,98 @@ define('text',['module'], function (module) {
if (b instanceof _) b = b._wrapped; if (b instanceof _) b = b._wrapped;
// Compare `[[Class]]` names. // Compare `[[Class]]` names.
var className = toString.call(a); var className = toString.call(a);
if (className != toString.call(b)) return false; if (className !== toString.call(b)) return false;
switch (className) { switch (className) {
// Strings, numbers, dates, and booleans are compared by value. // Strings, numbers, regular expressions, dates, and booleans are compared by value.
case '[object RegExp]':
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case '[object String]': case '[object String]':
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`. // equivalent to `new String("5")`.
return a == String(b); return '' + a === '' + b;
case '[object Number]': case '[object Number]':
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for // `NaN`s are equivalent, but non-reflexive.
// other numeric values. // Object(NaN) is equivalent to NaN
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); if (+a !== +a) return +b !== +b;
// An `egal` comparison is performed for other numeric values.
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]': case '[object Date]':
case '[object Boolean]': case '[object Boolean]':
// Coerce dates and booleans to numeric primitive values. Dates are compared by their // Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations // millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent. // of `NaN` are not equivalent.
return +a == +b; return +a === +b;
// RegExps are compared by their source patterns and flags.
case '[object RegExp]':
return a.source == b.source &&
a.global == b.global &&
a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase;
} }
var areArrays = className === '[object Array]';
if (!areArrays) {
if (typeof a != 'object' || typeof b != 'object') return false; if (typeof a != 'object' || typeof b != 'object') return false;
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
_.isFunction(bCtor) && bCtor instanceof bCtor)
&& ('constructor' in a && 'constructor' in b)) {
return false;
}
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic // Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
// Initializing stack of traversed objects.
// It's done here since we only need them for objects and arrays comparison.
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length; var length = aStack.length;
while (length--) { while (length--) {
// Linear search. Performance is inversely proportional to the number of // Linear search. Performance is inversely proportional to the number of
// unique nested structures. // unique nested structures.
if (aStack[length] == a) return bStack[length] == b; if (aStack[length] === a) return bStack[length] === b;
}
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
_.isFunction(bCtor) && (bCtor instanceof bCtor))
&& ('constructor' in a && 'constructor' in b)) {
return false;
} }
// Add the first object to the stack of traversed objects. // Add the first object to the stack of traversed objects.
aStack.push(a); aStack.push(a);
bStack.push(b); bStack.push(b);
var size = 0, result = true;
// Recursively compare objects and arrays. // Recursively compare objects and arrays.
if (className == '[object Array]') { if (areArrays) {
// Compare array lengths to determine if a deep comparison is necessary. // Compare array lengths to determine if a deep comparison is necessary.
size = a.length; length = a.length;
result = size == b.length; if (length !== b.length) return false;
if (result) {
// Deep compare the contents, ignoring non-numeric properties. // Deep compare the contents, ignoring non-numeric properties.
while (size--) { while (length--) {
if (!(result = eq(a[size], b[size], aStack, bStack))) break; if (!eq(a[length], b[length], aStack, bStack)) return false;
}
} }
} else { } else {
// Deep compare objects. // Deep compare objects.
for (var key in a) { var keys = _.keys(a), key;
if (_.has(a, key)) { length = keys.length;
// Count the expected number of properties. // Ensure that both objects contain the same number of properties before comparing deep equality.
size++; if (_.keys(b).length !== length) return false;
// Deep compare each member. while (length--) {
if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; // Deep compare each member
} key = keys[length];
} if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
// Ensure that both objects contain the same number of properties.
if (result) {
for (key in b) {
if (_.has(b, key) && !(size--)) break;
}
result = !size;
} }
} }
// Remove the first object from the stack of traversed objects. // Remove the first object from the stack of traversed objects.
aStack.pop(); aStack.pop();
bStack.pop(); bStack.pop();
return result; return true;
}; };
// Perform a deep comparison to check if two objects are equal. // Perform a deep comparison to check if two objects are equal.
_.isEqual = function(a, b) { _.isEqual = function(a, b) {
return eq(a, b, [], []); return eq(a, b);
}; };
// Is a given array, string, or object empty? // Is a given array, string, or object empty?
// An "empty" object has no enumerable own-properties. // An "empty" object has no enumerable own-properties.
_.isEmpty = function(obj) { _.isEmpty = function(obj) {
if (obj == null) return true; if (obj == null) return true;
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
for (var key in obj) if (_.has(obj, key)) return false; return _.keys(obj).length === 0;
return true;
}; };
// Is a given value a DOM element? // Is a given value a DOM element?
...@@ -12179,33 +12356,35 @@ define('text',['module'], function (module) { ...@@ -12179,33 +12356,35 @@ define('text',['module'], function (module) {
// Is a given value an array? // Is a given value an array?
// Delegates to ECMA5's native Array.isArray // Delegates to ECMA5's native Array.isArray
_.isArray = nativeIsArray || function(obj) { _.isArray = nativeIsArray || function(obj) {
return toString.call(obj) == '[object Array]'; return toString.call(obj) === '[object Array]';
}; };
// Is a given variable an object? // Is a given variable an object?
_.isObject = function(obj) { _.isObject = function(obj) {
return obj === Object(obj); var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
}; };
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
_['is' + name] = function(obj) { _['is' + name] = function(obj) {
return toString.call(obj) == '[object ' + name + ']'; return toString.call(obj) === '[object ' + name + ']';
}; };
}); });
// Define a fallback version of the method in browsers (ahem, IE), where // Define a fallback version of the method in browsers (ahem, IE < 9), where
// there isn't any inspectable "Arguments" type. // there isn't any inspectable "Arguments" type.
if (!_.isArguments(arguments)) { if (!_.isArguments(arguments)) {
_.isArguments = function(obj) { _.isArguments = function(obj) {
return !!(obj && _.has(obj, 'callee')); return _.has(obj, 'callee');
}; };
} }
// Optimize `isFunction` if appropriate. // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
if (typeof (/./) !== 'function') { // IE 11 (#1621), and in Safari 8 (#1929).
if (typeof /./ != 'function' && typeof Int8Array != 'object') {
_.isFunction = function(obj) { _.isFunction = function(obj) {
return typeof obj === 'function'; return typeof obj == 'function' || false;
}; };
} }
...@@ -12216,12 +12395,12 @@ define('text',['module'], function (module) { ...@@ -12216,12 +12395,12 @@ define('text',['module'], function (module) {
// Is the given value `NaN`? (NaN is the only number which does not equal itself). // Is the given value `NaN`? (NaN is the only number which does not equal itself).
_.isNaN = function(obj) { _.isNaN = function(obj) {
return _.isNumber(obj) && obj != +obj; return _.isNumber(obj) && obj !== +obj;
}; };
// Is a given value a boolean? // Is a given value a boolean?
_.isBoolean = function(obj) { _.isBoolean = function(obj) {
return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
}; };
// Is a given value equal to null? // Is a given value equal to null?
...@@ -12237,7 +12416,7 @@ define('text',['module'], function (module) { ...@@ -12237,7 +12416,7 @@ define('text',['module'], function (module) {
// Shortcut function for checking if an object has a given property directly // Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype). // on itself (in other words, not on a prototype).
_.has = function(obj, key) { _.has = function(obj, key) {
return hasOwnProperty.call(obj, key); return obj != null && hasOwnProperty.call(obj, key);
}; };
// Utility Functions // Utility Functions
...@@ -12250,39 +12429,47 @@ define('text',['module'], function (module) { ...@@ -12250,39 +12429,47 @@ define('text',['module'], function (module) {
return this; return this;
}; };
// Keep the identity function around for default iterators. // Keep the identity function around for default iteratees.
_.identity = function(value) { _.identity = function(value) {
return value; return value;
}; };
// Predicate-generating functions. Often useful outside of Underscore.
_.constant = function(value) { _.constant = function(value) {
return function () { return function() {
return value; return value;
}; };
}; };
_.noop = function(){};
_.property = function(key) { _.property = function(key) {
return function(obj) { return function(obj) {
return obj == null ? void 0 : obj[key];
};
};
// Generates a function for a given object that returns a given property.
_.propertyOf = function(obj) {
return obj == null ? function(){} : function(key) {
return obj[key]; return obj[key];
}; };
}; };
// Returns a predicate for checking whether an object has a given set of `key:value` pairs. // Returns a predicate for checking whether an object has a given set of
_.matches = function(attrs) { // `key:value` pairs.
_.matcher = _.matches = function(attrs) {
attrs = _.extendOwn({}, attrs);
return function(obj) { return function(obj) {
if (obj === attrs) return true; //avoid comparing an object to itself. return _.isMatch(obj, attrs);
for (var key in attrs) { };
if (attrs[key] !== obj[key])
return false;
}
return true;
}
}; };
// Run a function **n** times. // Run a function **n** times.
_.times = function(n, iterator, context) { _.times = function(n, iteratee, context) {
var accum = Array(Math.max(0, n)); var accum = Array(Math.max(0, n));
for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); iteratee = optimizeCb(iteratee, context, 1);
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
return accum; return accum;
}; };
...@@ -12296,56 +12483,48 @@ define('text',['module'], function (module) { ...@@ -12296,56 +12483,48 @@ define('text',['module'], function (module) {
}; };
// A (possibly faster) way to get the current timestamp as an integer. // A (possibly faster) way to get the current timestamp as an integer.
_.now = Date.now || function() { return new Date().getTime(); }; _.now = Date.now || function() {
return new Date().getTime();
};
// List of HTML entities for escaping. // List of HTML entities for escaping.
var entityMap = { var escapeMap = {
escape: {
'&': '&amp;', '&': '&amp;',
'<': '&lt;', '<': '&lt;',
'>': '&gt;', '>': '&gt;',
'"': '&quot;', '"': '&quot;',
"'": '&#x27;' "'": '&#x27;',
} '`': '&#x60;'
};
entityMap.unescape = _.invert(entityMap.escape);
// Regexes containing the keys and values listed immediately above.
var entityRegexes = {
escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
}; };
var unescapeMap = _.invert(escapeMap);
// Functions for escaping and unescaping strings to/from HTML interpolation. // Functions for escaping and unescaping strings to/from HTML interpolation.
_.each(['escape', 'unescape'], function(method) { var createEscaper = function(map) {
_[method] = function(string) { var escaper = function(match) {
if (string == null) return ''; return map[match];
return ('' + string).replace(entityRegexes[method], function(match) {
return entityMap[method][match];
});
}; };
}); // Regexes for identifying a key that needs to be escaped
var source = '(?:' + _.keys(map).join('|') + ')';
var testRegexp = RegExp(source);
var replaceRegexp = RegExp(source, 'g');
return function(string) {
string = string == null ? '' : '' + string;
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
};
};
_.escape = createEscaper(escapeMap);
_.unescape = createEscaper(unescapeMap);
// If the value of the named `property` is a function then invoke it with the // If the value of the named `property` is a function then invoke it with the
// `object` as context; otherwise, return it. // `object` as context; otherwise, return it.
_.result = function(object, property) { _.result = function(object, property, fallback) {
if (object == null) return void 0; var value = object == null ? void 0 : object[property];
var value = object[property]; if (value === void 0) {
value = fallback;
}
return _.isFunction(value) ? value.call(object) : value; return _.isFunction(value) ? value.call(object) : value;
}; };
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result.call(this, func.apply(_, args));
};
});
};
// Generate a unique integer id (unique within the entire client session). // Generate a unique integer id (unique within the entire client session).
// Useful for temporary DOM ids. // Useful for temporary DOM ids.
var idCounter = 0; var idCounter = 0;
...@@ -12374,22 +12553,26 @@ define('text',['module'], function (module) { ...@@ -12374,22 +12553,26 @@ define('text',['module'], function (module) {
'\\': '\\', '\\': '\\',
'\r': 'r', '\r': 'r',
'\n': 'n', '\n': 'n',
'\t': 't',
'\u2028': 'u2028', '\u2028': 'u2028',
'\u2029': 'u2029' '\u2029': 'u2029'
}; };
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function(match) {
return '\\' + escapes[match];
};
// JavaScript micro-templating, similar to John Resig's implementation. // JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace, // Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code. // and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) { // NB: `oldSettings` only exists for backwards compatibility.
var render; _.template = function(text, settings, oldSettings) {
if (!settings && oldSettings) settings = oldSettings;
settings = _.defaults({}, settings, _.templateSettings); settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation. // Combine delimiters into one regular expression via alternation.
var matcher = new RegExp([ var matcher = RegExp([
(settings.escape || noMatch).source, (settings.escape || noMatch).source,
(settings.interpolate || noMatch).source, (settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source (settings.evaluate || noMatch).source
...@@ -12399,19 +12582,18 @@ define('text',['module'], function (module) { ...@@ -12399,19 +12582,18 @@ define('text',['module'], function (module) {
var index = 0; var index = 0;
var source = "__p+='"; var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset) source += text.slice(index, offset).replace(escaper, escapeChar);
.replace(escaper, function(match) { return '\\' + escapes[match]; }); index = offset + match.length;
if (escape) { if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
} } else if (interpolate) {
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
} } else if (evaluate) {
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='"; source += "';\n" + evaluate + "\n__p+='";
} }
index = offset + match.length;
// Adobe VMs need the match returned to produce the correct offest.
return match; return match;
}); });
source += "';\n"; source += "';\n";
...@@ -12421,29 +12603,31 @@ define('text',['module'], function (module) { ...@@ -12421,29 +12603,31 @@ define('text',['module'], function (module) {
source = "var __t,__p='',__j=Array.prototype.join," + source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" + "print=function(){__p+=__j.call(arguments,'');};\n" +
source + "return __p;\n"; source + 'return __p;\n';
try { try {
render = new Function(settings.variable || 'obj', '_', source); var render = new Function(settings.variable || 'obj', '_', source);
} catch (e) { } catch (e) {
e.source = source; e.source = source;
throw e; throw e;
} }
if (data) return render(data, _);
var template = function(data) { var template = function(data) {
return render.call(this, data, _); return render.call(this, data, _);
}; };
// Provide the compiled function source as a convenience for precompilation. // Provide the compiled source as a convenience for precompilation.
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; var argument = settings.variable || 'obj';
template.source = 'function(' + argument + '){\n' + source + '}';
return template; return template;
}; };
// Add a "chain" function, which will delegate to the wrapper. // Add a "chain" function. Start chaining a wrapped Underscore object.
_.chain = function(obj) { _.chain = function(obj) {
return _(obj).chain(); var instance = _(obj);
instance._chain = true;
return instance;
}; };
// OOP // OOP
...@@ -12453,46 +12637,56 @@ define('text',['module'], function (module) { ...@@ -12453,46 +12637,56 @@ define('text',['module'], function (module) {
// underscore functions. Wrapped objects may be chained. // underscore functions. Wrapped objects may be chained.
// Helper function to continue chaining intermediate results. // Helper function to continue chaining intermediate results.
var result = function(obj) { var result = function(instance, obj) {
return this._chain ? _(obj).chain() : obj; return instance._chain ? _(obj).chain() : obj;
};
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result(this, func.apply(_, args));
};
});
}; };
// Add all of the Underscore functions to the wrapper object. // Add all of the Underscore functions to the wrapper object.
_.mixin(_); _.mixin(_);
// Add all mutator Array functions to the wrapper. // Add all mutator Array functions to the wrapper.
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
var method = ArrayProto[name]; var method = ArrayProto[name];
_.prototype[name] = function() { _.prototype[name] = function() {
var obj = this._wrapped; var obj = this._wrapped;
method.apply(obj, arguments); method.apply(obj, arguments);
if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
return result.call(this, obj); return result(this, obj);
}; };
}); });
// Add all accessor Array functions to the wrapper. // Add all accessor Array functions to the wrapper.
each(['concat', 'join', 'slice'], function(name) { _.each(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name]; var method = ArrayProto[name];
_.prototype[name] = function() { _.prototype[name] = function() {
return result.call(this, method.apply(this._wrapped, arguments)); return result(this, method.apply(this._wrapped, arguments));
}; };
}); });
_.extend(_.prototype, {
// Start chaining a wrapped Underscore object.
chain: function() {
this._chain = true;
return this;
},
// Extracts the result from a wrapped and chained object. // Extracts the result from a wrapped and chained object.
value: function() { _.prototype.value = function() {
return this._wrapped; return this._wrapped;
} };
}); // Provide unwrapping proxy for some methods used in engine operations
// such as arithmetic and JSON stringification.
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
_.prototype.toString = function() {
return '' + this._wrapped;
};
// AMD registration happens at the end for compatibility with AMD loaders // AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general // that may not enforce next-turn semantics on modules. Even though general
...@@ -12506,7 +12700,7 @@ define('text',['module'], function (module) { ...@@ -12506,7 +12700,7 @@ define('text',['module'], function (module) {
return _; return _;
}); });
} }
}).call(this); }.call(this));
// RequireJS UnderscoreJS template plugin // RequireJS UnderscoreJS template plugin
// http://github.com/jfparadis/requirejs-tpl // http://github.com/jfparadis/requirejs-tpl
...@@ -13031,7 +13225,7 @@ var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments ...@@ -13031,7 +13225,7 @@ var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments
with(obj||{}){ with(obj||{}){
__p+='<form id="converse-login" method="post">\n <label>'+ __p+='<form id="converse-login" method="post">\n <label>'+
((__t=(label_username))==null?'':__t)+ ((__t=(label_username))==null?'':__t)+
'</label>\n <input type="username" name="jid" placeholder="user@server">\n <label>'+ '</label>\n <input type="email" name="jid" placeholder="user@server">\n <label>'+
((__t=(label_password))==null?'':__t)+ ((__t=(label_password))==null?'':__t)+
'</label>\n <input type="password" name="password" placeholder="password">\n <input class="submit" type="submit" value="'+ '</label>\n <input type="password" name="password" placeholder="password">\n <input class="submit" type="submit" value="'+
((__t=(label_login))==null?'':__t)+ ((__t=(label_login))==null?'':__t)+
...@@ -13360,7 +13554,9 @@ __p+='<form class="add-chatroom" action="" method="post">\n <label>'+ ...@@ -13360,7 +13554,9 @@ __p+='<form class="add-chatroom" action="" method="post">\n <label>'+
((__t=(label_nickname))==null?'':__t)+ ((__t=(label_nickname))==null?'':__t)+
'</label>\n <input type="text" name="nick" class="new-chatroom-nick"\n placeholder="'+ '</label>\n <input type="text" name="nick" class="new-chatroom-nick"\n placeholder="'+
((__t=(label_nickname))==null?'':__t)+ ((__t=(label_nickname))==null?'':__t)+
'"/>\n <label>'+ '"/>\n <label'+
((__t=(server_label_global_attr))==null?'':__t)+
'>'+
((__t=(label_server))==null?'':__t)+ ((__t=(label_server))==null?'':__t)+
'</label>\n <input type="'+ '</label>\n <input type="'+
((__t=(server_input_type))==null?'':__t)+ ((__t=(server_input_type))==null?'':__t)+
...@@ -13406,9 +13602,13 @@ __p+='<a class="open-chat" title="Name: '+ ...@@ -13406,9 +13602,13 @@ __p+='<a class="open-chat" title="Name: '+
((__t=(desc_status))==null?'':__t)+ ((__t=(desc_status))==null?'':__t)+
'"></span>'+ '"></span>'+
((__t=(fullname))==null?'':__t)+ ((__t=(fullname))==null?'':__t)+
'</a>\n<a class="remove-xmpp-contact icon-remove" title="'+ '</a>\n';
if (allow_contact_removal) {
__p+='\n<a class="remove-xmpp-contact icon-remove" title="'+
((__t=(desc_remove))==null?'':__t)+ ((__t=(desc_remove))==null?'':__t)+
'" href="#"></a>\n'; '" href="#"></a>\n';
}
__p+='\n';
} }
return __p; return __p;
}; }); }; });
...@@ -34610,19 +34810,6 @@ define("converse-dependencies", [ ...@@ -34610,19 +34810,6 @@ define("converse-dependencies", [
return this; return this;
}; };
var playNotification = function () {
var audio;
if (converse.play_sounds && typeof Audio !== "undefined"){
audio = new Audio("sounds/msg_received.ogg");
if (audio.canPlayType('/audio/ogg')) {
audio.play();
} else {
audio = new Audio("/sounds/msg_received.mp3");
audio.play();
}
}
};
var converse = { var converse = {
plugins: {}, plugins: {},
templates: templates, templates: templates,
...@@ -34729,6 +34916,7 @@ define("converse-dependencies", [ ...@@ -34729,6 +34916,7 @@ define("converse-dependencies", [
// Default configuration values // Default configuration values
// ---------------------------- // ----------------------------
this.default_settings = { this.default_settings = {
allow_contact_removal: true,
allow_contact_requests: true, allow_contact_requests: true,
allow_dragresize: true, allow_dragresize: true,
allow_logout: true, allow_logout: true,
...@@ -34843,6 +35031,19 @@ define("converse-dependencies", [ ...@@ -34843,6 +35031,19 @@ define("converse-dependencies", [
// Module-level functions // Module-level functions
// ---------------------- // ----------------------
this.playNotification = function () {
var audio;
if (converse.play_sounds && typeof Audio !== "undefined"){
audio = new Audio("sounds/msg_received.ogg");
if (audio.canPlayType('/audio/ogg')) {
audio.play();
} else {
audio = new Audio("/sounds/msg_received.mp3");
audio.play();
}
}
};
this.giveFeedback = function (message, klass) { this.giveFeedback = function (message, klass) {
$('.conn-feedback').each(function (idx, el) { $('.conn-feedback').each(function (idx, el) {
var $el = $(el); var $el = $(el);
...@@ -34915,7 +35116,6 @@ define("converse-dependencies", [ ...@@ -34915,7 +35116,6 @@ define("converse-dependencies", [
this.reconnect = function () { this.reconnect = function () {
converse.giveFeedback(__('Reconnecting'), 'error'); converse.giveFeedback(__('Reconnecting'), 'error');
converse.emit('reconnect');
if (!converse.prebind) { if (!converse.prebind) {
this.connection.connect( this.connection.connect(
this.connection.jid, this.connection.jid,
...@@ -34927,6 +35127,10 @@ define("converse-dependencies", [ ...@@ -34927,6 +35127,10 @@ define("converse-dependencies", [
this.connection.hold, this.connection.hold,
this.connection.route this.connection.route
); );
} else if (converse.prebind_url) {
this.clearSession();
this._tearDown();
this.startNewBOSHSession();
} }
}; };
...@@ -34963,6 +35167,7 @@ define("converse-dependencies", [ ...@@ -34963,6 +35167,7 @@ define("converse-dependencies", [
converse.giveFeedback(__('Authentication Failed'), 'error'); converse.giveFeedback(__('Authentication Failed'), 'error');
converse.connection.disconnect(__('Authentication Failed')); converse.connection.disconnect(__('Authentication Failed'));
} else if (status === Strophe.Status.DISCONNECTING) { } else if (status === Strophe.Status.DISCONNECTING) {
// FIXME: what about prebind?
if (!converse.connection.connected) { if (!converse.connection.connected) {
converse.renderLoginPanel(); converse.renderLoginPanel();
} }
...@@ -35038,8 +35243,8 @@ define("converse-dependencies", [ ...@@ -35038,8 +35243,8 @@ define("converse-dependencies", [
this.clearSession = function () { this.clearSession = function () {
this.roster.browserStorage._clear(); this.roster.browserStorage._clear();
this.session.browserStorage._clear(); this.session.browserStorage._clear();
// XXX: this should perhaps go into the beforeunload handler var controlbox = converse.chatboxes.get('controlbox');
converse.chatboxes.get('controlbox').save({'connected': false}); controlbox.save({'connected': false});
}; };
this.setSession = function () { this.setSession = function () {
...@@ -36244,6 +36449,7 @@ define("converse-dependencies", [ ...@@ -36244,6 +36449,7 @@ define("converse-dependencies", [
this.$el.html( this.$el.html(
converse.templates.room_panel({ converse.templates.room_panel({
'server_input_type': converse.hide_muc_server && 'hidden' || 'text', 'server_input_type': converse.hide_muc_server && 'hidden' || 'text',
'server_label_global_attr': converse.hide_muc_server && ' hidden' || '',
'label_room_name': __('Room name'), 'label_room_name': __('Room name'),
'label_nickname': __('Nickname'), 'label_nickname': __('Nickname'),
'label_server': __('Server'), 'label_server': __('Server'),
...@@ -37456,7 +37662,7 @@ define("converse-dependencies", [ ...@@ -37456,7 +37662,7 @@ define("converse-dependencies", [
} }
this.model.createMessage($message); this.model.createMessage($message);
if (!delayed && sender !== this.model.get('nick') && (new RegExp("\\b"+this.model.get('nick')+"\\b")).test(body)) { if (!delayed && sender !== this.model.get('nick') && (new RegExp("\\b"+this.model.get('nick')+"\\b")).test(body)) {
playNotification(); converse.playNotification();
} }
if (sender !== this.model.get('nick')) { if (sender !== this.model.get('nick')) {
// We only emit an event if it's not our own message // We only emit an event if it's not our own message
...@@ -37626,7 +37832,7 @@ define("converse-dependencies", [ ...@@ -37626,7 +37832,7 @@ define("converse-dependencies", [
return true; // We already have this message stored. return true; // We already have this message stored.
} }
if (!this.isOnlyChatStateNotification($message) && from !== converse.bare_jid) { if (!this.isOnlyChatStateNotification($message) && from !== converse.bare_jid) {
playNotification(); converse.playNotification();
} }
chatbox.receiveMessage($message); chatbox.receiveMessage($message);
converse.roster.addResource(contact_jid, resource); converse.roster.addResource(contact_jid, resource);
...@@ -38057,7 +38263,8 @@ define("converse-dependencies", [ ...@@ -38057,7 +38263,8 @@ define("converse-dependencies", [
_.extend(item.toJSON(), { _.extend(item.toJSON(), {
'desc_status': STATUSES[chat_status||'offline'], 'desc_status': STATUSES[chat_status||'offline'],
'desc_chat': __('Click to chat with this contact'), 'desc_chat': __('Click to chat with this contact'),
'desc_remove': __('Click to remove this contact') 'desc_remove': __('Click to remove this contact'),
'allow_contact_removal': converse.allow_contact_removal
}) })
)); ));
} }
...@@ -38071,6 +38278,7 @@ define("converse-dependencies", [ ...@@ -38071,6 +38278,7 @@ define("converse-dependencies", [
removeContact: function (ev) { removeContact: function (ev) {
if (ev && ev.preventDefault) { ev.preventDefault(); } if (ev && ev.preventDefault) { ev.preventDefault(); }
if (!converse.allow_contact_removal) { return; }
var result = confirm(__("Are you sure you want to remove this contact?")); var result = confirm(__("Are you sure you want to remove this contact?"));
if (result === true) { if (result === true) {
var bare_jid = this.model.get('jid'); var bare_jid = this.model.get('jid');
...@@ -39771,20 +39979,32 @@ define("converse-dependencies", [ ...@@ -39771,20 +39979,32 @@ define("converse-dependencies", [
} }
}; };
this.startNewBOSHSession = function () {
$.ajax({
url: this.prebind_url,
type: 'GET',
success: function (response) {
this.session.save({rid: response.rid});
this.connection.attach(
response.jid,
response.sid,
response.rid,
this.onConnect
);
}.bind(this),
error: function (response) {
delete this.connection;
this.emit('noResumeableSession');
}.bind(this)
});
};
this.initConnection = function () { this.initConnection = function () {
var rid, sid, jid; var rid, sid, jid;
if (this.connection && this.connection.connected) { if (this.connection && this.connection.connected) {
this.setUpXMLLogging(); this.setUpXMLLogging();
this.onConnected(); this.onConnected();
} else { } else {
// XXX: it's not yet clear what the order of preference should
// be between RID and SID received via the initialize method or
// those received from sessionStorage.
//
// What do you we if we receive values from both avenues?
//
// Also, what do we do when the keepalive session values are
// expired? Do we try to fall back?
if (!this.bosh_service_url && ! this.websocket_url) { if (!this.bosh_service_url && ! this.websocket_url) {
throw("Error: you must supply a value for the bosh_service_url or websocket_url"); throw("Error: you must supply a value for the bosh_service_url or websocket_url");
} }
...@@ -39810,33 +40030,25 @@ define("converse-dependencies", [ ...@@ -39810,33 +40030,25 @@ define("converse-dependencies", [
rid = this.session.get('rid'); rid = this.session.get('rid');
sid = this.session.get('sid'); sid = this.session.get('sid');
jid = this.session.get('jid'); jid = this.session.get('jid');
if (rid && jid && sid) { if (this.prebind) {
// The RID needs to be increased with each request. if (!this.jid) {
this.session.save({rid: rid}); throw("When using 'keepalive' with 'prebind, you must supply the JID of the current user.");
}
if (rid && sid && jid && Strophe.getBareJidFromJid(jid) === Strophe.getBareJidFromJid(this.jid)) {
this.session.save({rid: rid}); // The RID needs to be increased with each request.
this.connection.attach(jid, sid, rid, this.onConnect); this.connection.attach(jid, sid, rid, this.onConnect);
} else if (this.prebind) { } else if (this.prebind_url) {
if (this.prebind_url) { this.startNewBOSHSession();
$.ajax({
url: this.prebind_url,
type: 'GET',
success: function (response) {
this.session.save({rid: rid});
this.connection.attach(
response.jid,
response.sid,
response.rid,
this.onConnect
);
}.bind(this),
error: function (response) {
delete this.connection;
this.emit('noResumeableSession');
}.bind(this)
});
} else { } else {
delete this.connection; delete this.connection;
this.emit('noResumeableSession'); this.emit('noResumeableSession');
} }
} else {
// Non-prebind case.
if (rid && sid && jid) {
this.session.save({rid: rid}); // The RID needs to be increased with each request.
this.connection.attach(jid, sid, rid, this.onConnect);
}
} }
} }
} }
...@@ -39916,6 +40128,14 @@ define("converse-dependencies", [ ...@@ -39916,6 +40128,14 @@ define("converse-dependencies", [
'initialize': function (settings, callback) { 'initialize': function (settings, callback) {
converse.initialize(settings, callback); converse.initialize(settings, callback);
}, },
'disconnect': function () {
converse.connection.disconnect();
},
'account': {
'logout': function () {
converse.logOut();
},
},
'settings': { 'settings': {
'get': function (key) { 'get': function (key) {
if (_.contains(Object.keys(converse.default_settings), key)) { if (_.contains(Object.keys(converse.default_settings), key)) {
...@@ -40221,7 +40441,6 @@ require.config({ ...@@ -40221,7 +40441,6 @@ require.config({
// define module dependencies for modules not using define // define module dependencies for modules not using define
shim: { shim: {
'underscore': { exports: '_' },
'crypto.aes': { deps: ['crypto.cipher-core'] }, 'crypto.aes': { deps: ['crypto.cipher-core'] },
'crypto.cipher-core': { deps: ['crypto.enc-base64', 'crypto.evpkdf'] }, 'crypto.cipher-core': { deps: ['crypto.enc-base64', 'crypto.evpkdf'] },
'crypto.enc-base64': { deps: ['crypto.core'] }, 'crypto.enc-base64': { deps: ['crypto.core'] },
This source diff could not be displayed because it is too large. You can view the blob instead.
/** /**
* @license almond 0.3.0 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license. * Available via the MIT or new BSD license.
* see: http://github.com/jrburke/almond for details * see: http://github.com/jrburke/almond for details
*/ */
...@@ -44,12 +44,6 @@ var requirejs, require, define; ...@@ -44,12 +44,6 @@ var requirejs, require, define;
//otherwise, assume it is a top-level require that will //otherwise, assume it is a top-level require that will
//be relative to baseUrl in the end. //be relative to baseUrl in the end.
if (baseName) { 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('/'); name = name.split('/');
lastIndex = name.length - 1; lastIndex = name.length - 1;
...@@ -58,7 +52,11 @@ var requirejs, require, define; ...@@ -58,7 +52,11 @@ var requirejs, require, define;
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
} }
name = baseParts.concat(name); //Lop off the last part of baseParts, so that . matches the
//"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.
name = baseParts.slice(0, baseParts.length - 1).concat(name);
//start trimDots //start trimDots
for (i = 0; i < name.length; i += 1) { for (i = 0; i < name.length; i += 1) {
...@@ -408,6 +406,9 @@ var requirejs, require, define; ...@@ -408,6 +406,9 @@ var requirejs, require, define;
requirejs._defined = defined; requirejs._defined = defined;
define = function (name, deps, callback) { define = function (name, deps, callback) {
if (typeof name !== 'string') {
throw new Error('See almond README: incorrect module build, no module name');
}
//This module may not have dependencies //This module may not have dependencies
if (!deps.splice) { if (!deps.splice) {
...@@ -830,9 +831,9 @@ define('text',['module'], function (module) { ...@@ -830,9 +831,9 @@ define('text',['module'], function (module) {
return text; return text;
}); });
// Underscore.js 1.6.0 // Underscore.js 1.8.2
// http://underscorejs.org // http://underscorejs.org
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license. // Underscore may be freely distributed under the MIT license.
(function() { (function() {
...@@ -846,9 +847,6 @@ define('text',['module'], function (module) { ...@@ -846,9 +847,6 @@ define('text',['module'], function (module) {
// Save the previous value of the `_` variable. // Save the previous value of the `_` variable.
var previousUnderscore = root._; var previousUnderscore = root._;
// Establish the object that gets returned to break out of a loop iteration.
var breaker = {};
// Save bytes in the minified (but not gzipped) version: // Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
...@@ -856,25 +854,19 @@ define('text',['module'], function (module) { ...@@ -856,25 +854,19 @@ define('text',['module'], function (module) {
var var
push = ArrayProto.push, push = ArrayProto.push,
slice = ArrayProto.slice, slice = ArrayProto.slice,
concat = ArrayProto.concat,
toString = ObjProto.toString, toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty; hasOwnProperty = ObjProto.hasOwnProperty;
// All **ECMAScript 5** native function implementations that we hope to use // All **ECMAScript 5** native function implementations that we hope to use
// are declared here. // are declared here.
var 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, nativeIsArray = Array.isArray,
nativeKeys = Object.keys, nativeKeys = Object.keys,
nativeBind = FuncProto.bind; nativeBind = FuncProto.bind,
nativeCreate = Object.create;
// Naked function reference for surrogate-prototype-swapping.
var Ctor = function(){};
// Create a safe reference to the Underscore object for use below. // Create a safe reference to the Underscore object for use below.
var _ = function(obj) { var _ = function(obj) {
...@@ -885,8 +877,7 @@ define('text',['module'], function (module) { ...@@ -885,8 +877,7 @@ define('text',['module'], function (module) {
// Export the Underscore object for **Node.js**, with // Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in // backwards-compatibility for the old `require()` API. If we're in
// the browser, add `_` as a global object via a string identifier, // the browser, add `_` as a global object.
// for Closure Compiler "advanced" mode.
if (typeof exports !== 'undefined') { if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) { if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _; exports = module.exports = _;
...@@ -897,161 +888,208 @@ define('text',['module'], function (module) { ...@@ -897,161 +888,208 @@ define('text',['module'], function (module) {
} }
// Current version. // Current version.
_.VERSION = '1.6.0'; _.VERSION = '1.8.2';
// Internal function that returns an efficient (for current engines) version
// of the passed-in callback, to be repeatedly applied in other Underscore
// functions.
var optimizeCb = function(func, context, argCount) {
if (context === void 0) return func;
switch (argCount == null ? 3 : argCount) {
case 1: return function(value) {
return func.call(context, value);
};
case 2: return function(value, other) {
return func.call(context, value, other);
};
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
};
// A mostly-internal function to generate callbacks that can be applied
// to each element in a collection, returning the desired result — either
// identity, an arbitrary callback, a property matcher, or a property accessor.
var cb = function(value, context, argCount) {
if (value == null) return _.identity;
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
if (_.isObject(value)) return _.matcher(value);
return _.property(value);
};
_.iteratee = function(value, context) {
return cb(value, context, Infinity);
};
// An internal function for creating assigner functions.
var createAssigner = function(keysFunc, undefinedOnly) {
return function(obj) {
var length = arguments.length;
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
};
// An internal function for creating a new object that inherits from another.
var baseCreate = function(prototype) {
if (!_.isObject(prototype)) return {};
if (nativeCreate) return nativeCreate(prototype);
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
// Helper for collection methods to determine whether a collection
// should be iterated as an array or as an object
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var isArrayLike = function(collection) {
var length = collection && collection.length;
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
// Collection Functions // Collection Functions
// -------------------- // --------------------
// The cornerstone, an `each` implementation, aka `forEach`. // The cornerstone, an `each` implementation, aka `forEach`.
// Handles objects with the built-in `forEach`, arrays, and raw objects. // Handles raw objects in addition to array-likes. Treats all
// Delegates to **ECMAScript 5**'s native `forEach` if available. // sparse array-likes as if they were dense.
var each = _.each = _.forEach = function(obj, iterator, context) { _.each = _.forEach = function(obj, iteratee, context) {
if (obj == null) return obj; iteratee = optimizeCb(iteratee, context);
if (nativeForEach && obj.forEach === nativeForEach) { var i, length;
obj.forEach(iterator, context); if (isArrayLike(obj)) {
} else if (obj.length === +obj.length) { for (i = 0, length = obj.length; i < length; i++) {
for (var i = 0, length = obj.length; i < length; i++) { iteratee(obj[i], i, obj);
if (iterator.call(context, obj[i], i, obj) === breaker) return;
} }
} else { } else {
var keys = _.keys(obj); var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) { for (i = 0, length = keys.length; i < length; i++) {
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; iteratee(obj[keys[i]], keys[i], obj);
} }
} }
return obj; return obj;
}; };
// Return the results of applying the iterator to each element. // Return the results of applying the iteratee to each element.
// Delegates to **ECMAScript 5**'s native `map` if available. _.map = _.collect = function(obj, iteratee, context) {
_.map = _.collect = function(obj, iterator, context) { iteratee = cb(iteratee, context);
var results = []; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return results; length = (keys || obj).length,
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); results = Array(length);
each(obj, function(value, index, list) { for (var index = 0; index < length; index++) {
results.push(iterator.call(context, value, index, list)); var currentKey = keys ? keys[index] : index;
}); results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results; return results;
}; };
var reduceError = 'Reduce of empty array with no initial value'; // Create a reducing function iterating left or right.
function createReduce(dir) {
// **Reduce** builds up a single result from a list of values, aka `inject`, // Optimized iterator function as using arguments.length
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. // in the main function will deoptimize the, see #1991.
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { function iterator(obj, iteratee, memo, keys, index, length) {
var initial = arguments.length > 2; for (; index >= 0 && index < length; index += dir) {
if (obj == null) obj = []; var currentKey = keys ? keys[index] : index;
if (nativeReduce && obj.reduce === nativeReduce) { memo = iteratee(memo, obj[currentKey], currentKey, obj);
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
}
each(obj, function(value, index, list) {
if (!initial) {
memo = value;
initial = true;
} else {
memo = iterator.call(context, memo, value, index, list);
} }
});
if (!initial) throw new TypeError(reduceError);
return memo; return memo;
};
// The right-associative version of reduce, also known as `foldr`.
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
var initial = arguments.length > 2;
if (obj == null) obj = [];
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
}
var length = obj.length;
if (length !== +length) {
var keys = _.keys(obj);
length = keys.length;
} }
each(obj, function(value, index, list) {
index = keys ? keys[--length] : --length; return function(obj, iteratee, memo, context) {
if (!initial) { iteratee = optimizeCb(iteratee, context, 4);
memo = obj[index]; var keys = !isArrayLike(obj) && _.keys(obj),
initial = true; length = (keys || obj).length,
} else { index = dir > 0 ? 0 : length - 1;
memo = iterator.call(context, memo, obj[index], index, list); // Determine the initial value if none is provided.
if (arguments.length < 3) {
memo = obj[keys ? keys[index] : index];
index += dir;
} }
}); return iterator(obj, iteratee, memo, keys, index, length);
if (!initial) throw new TypeError(reduceError);
return memo;
}; };
}
// **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`.
_.reduce = _.foldl = _.inject = createReduce(1);
// The right-associative version of reduce, also known as `foldr`.
_.reduceRight = _.foldr = createReduce(-1);
// Return the first value which passes a truth test. Aliased as `detect`. // Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function(obj, predicate, context) { _.find = _.detect = function(obj, predicate, context) {
var result; var key;
any(obj, function(value, index, list) { if (isArrayLike(obj)) {
if (predicate.call(context, value, index, list)) { key = _.findIndex(obj, predicate, context);
result = value; } else {
return true; key = _.findKey(obj, predicate, context);
} }
}); if (key !== void 0 && key !== -1) return obj[key];
return result;
}; };
// Return all the elements that pass a truth test. // Return all the elements that pass a truth test.
// Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`. // Aliased as `select`.
_.filter = _.select = function(obj, predicate, context) { _.filter = _.select = function(obj, predicate, context) {
var results = []; var results = [];
if (obj == null) return results; predicate = cb(predicate, context);
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); _.each(obj, function(value, index, list) {
each(obj, function(value, index, list) { if (predicate(value, index, list)) results.push(value);
if (predicate.call(context, value, index, list)) results.push(value);
}); });
return results; return results;
}; };
// Return all the elements for which a truth test fails. // Return all the elements for which a truth test fails.
_.reject = function(obj, predicate, context) { _.reject = function(obj, predicate, context) {
return _.filter(obj, function(value, index, list) { return _.filter(obj, _.negate(cb(predicate)), context);
return !predicate.call(context, value, index, list);
}, context);
}; };
// Determine whether all of the elements match a truth test. // Determine whether all of the elements match a truth test.
// Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`. // Aliased as `all`.
_.every = _.all = function(obj, predicate, context) { _.every = _.all = function(obj, predicate, context) {
predicate || (predicate = _.identity); predicate = cb(predicate, context);
var result = true; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return result; length = (keys || obj).length;
if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); for (var index = 0; index < length; index++) {
each(obj, function(value, index, list) { var currentKey = keys ? keys[index] : index;
if (!(result = result && predicate.call(context, value, index, list))) return breaker; if (!predicate(obj[currentKey], currentKey, obj)) return false;
}); }
return !!result; return true;
}; };
// Determine if at least one element in the object matches a truth test. // Determine if at least one element in the object matches a truth test.
// Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`. // Aliased as `any`.
var any = _.some = _.any = function(obj, predicate, context) { _.some = _.any = function(obj, predicate, context) {
predicate || (predicate = _.identity); predicate = cb(predicate, context);
var result = false; var keys = !isArrayLike(obj) && _.keys(obj),
if (obj == null) return result; length = (keys || obj).length;
if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); for (var index = 0; index < length; index++) {
each(obj, function(value, index, list) { var currentKey = keys ? keys[index] : index;
if (result || (result = predicate.call(context, value, index, list))) return breaker; if (predicate(obj[currentKey], currentKey, obj)) return true;
}); }
return !!result; return false;
}; };
// Determine if the array or object contains a given value (using `===`). // Determine if the array or object contains a given value (using `===`).
// Aliased as `include`. // Aliased as `includes` and `include`.
_.contains = _.include = function(obj, target) { _.contains = _.includes = _.include = function(obj, target, fromIndex) {
if (obj == null) return false; if (!isArrayLike(obj)) obj = _.values(obj);
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; return _.indexOf(obj, target, typeof fromIndex == 'number' && fromIndex) >= 0;
return any(obj, function(value) {
return value === target;
});
}; };
// Invoke a method (with arguments) on every item in a collection. // Invoke a method (with arguments) on every item in a collection.
...@@ -1059,7 +1097,8 @@ define('text',['module'], function (module) { ...@@ -1059,7 +1097,8 @@ define('text',['module'], function (module) {
var args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
var isFunc = _.isFunction(method); var isFunc = _.isFunction(method);
return _.map(obj, function(value) { return _.map(obj, function(value) {
return (isFunc ? method : value[method]).apply(value, args); var func = isFunc ? method : value[method];
return func == null ? func : func.apply(value, args);
}); });
}; };
...@@ -1071,60 +1110,76 @@ define('text',['module'], function (module) { ...@@ -1071,60 +1110,76 @@ define('text',['module'], function (module) {
// Convenience version of a common use case of `filter`: selecting only objects // Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs. // containing specific `key:value` pairs.
_.where = function(obj, attrs) { _.where = function(obj, attrs) {
return _.filter(obj, _.matches(attrs)); return _.filter(obj, _.matcher(attrs));
}; };
// Convenience version of a common use case of `find`: getting the first object // Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs. // containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) { _.findWhere = function(obj, attrs) {
return _.find(obj, _.matches(attrs)); return _.find(obj, _.matcher(attrs));
}; };
// Return the maximum element or (element-based computation). // Return the maximum element (or element-based computation).
// Can't optimize arrays of integers longer than 65,535 elements. _.max = function(obj, iteratee, context) {
// See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) var result = -Infinity, lastComputed = -Infinity,
_.max = function(obj, iterator, context) { value, computed;
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { if (iteratee == null && obj != null) {
return Math.max.apply(Math, obj); obj = isArrayLike(obj) ? obj : _.values(obj);
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value > result) {
result = value;
}
} }
var result = -Infinity, lastComputed = -Infinity; } else {
each(obj, function(value, index, list) { iteratee = cb(iteratee, context);
var computed = iterator ? iterator.call(context, value, index, list) : value; _.each(obj, function(value, index, list) {
if (computed > lastComputed) { computed = iteratee(value, index, list);
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
result = value; result = value;
lastComputed = computed; lastComputed = computed;
} }
}); });
}
return result; return result;
}; };
// Return the minimum element (or element-based computation). // Return the minimum element (or element-based computation).
_.min = function(obj, iterator, context) { _.min = function(obj, iteratee, context) {
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { var result = Infinity, lastComputed = Infinity,
return Math.min.apply(Math, obj); value, computed;
} if (iteratee == null && obj != null) {
var result = Infinity, lastComputed = Infinity; obj = isArrayLike(obj) ? obj : _.values(obj);
each(obj, function(value, index, list) { for (var i = 0, length = obj.length; i < length; i++) {
var computed = iterator ? iterator.call(context, value, index, list) : value; value = obj[i];
if (computed < lastComputed) { if (value < result) {
result = value;
}
}
} else {
iteratee = cb(iteratee, context);
_.each(obj, function(value, index, list) {
computed = iteratee(value, index, list);
if (computed < lastComputed || computed === Infinity && result === Infinity) {
result = value; result = value;
lastComputed = computed; lastComputed = computed;
} }
}); });
}
return result; return result;
}; };
// Shuffle an array, using the modern version of the // Shuffle a collection, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_.shuffle = function(obj) { _.shuffle = function(obj) {
var rand; var set = isArrayLike(obj) ? obj : _.values(obj);
var index = 0; var length = set.length;
var shuffled = []; var shuffled = Array(length);
each(obj, function(value) { for (var index = 0, rand; index < length; index++) {
rand = _.random(index++); rand = _.random(0, index);
shuffled[index - 1] = shuffled[rand]; if (rand !== index) shuffled[index] = shuffled[rand];
shuffled[rand] = value; shuffled[rand] = set[index];
}); }
return shuffled; return shuffled;
}; };
...@@ -1133,27 +1188,20 @@ define('text',['module'], function (module) { ...@@ -1133,27 +1188,20 @@ define('text',['module'], function (module) {
// The internal `guard` argument allows it to work with `map`. // The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) { _.sample = function(obj, n, guard) {
if (n == null || guard) { if (n == null || guard) {
if (obj.length !== +obj.length) obj = _.values(obj); if (!isArrayLike(obj)) obj = _.values(obj);
return obj[_.random(obj.length - 1)]; return obj[_.random(obj.length - 1)];
} }
return _.shuffle(obj).slice(0, Math.max(0, n)); return _.shuffle(obj).slice(0, Math.max(0, n));
}; };
// An internal function to generate lookup iterators. // Sort the object's values by a criterion produced by an iteratee.
var lookupIterator = function(value) { _.sortBy = function(obj, iteratee, context) {
if (value == null) return _.identity; iteratee = cb(iteratee, context);
if (_.isFunction(value)) return value;
return _.property(value);
};
// Sort the object's values by a criterion produced by an iterator.
_.sortBy = function(obj, iterator, context) {
iterator = lookupIterator(iterator);
return _.pluck(_.map(obj, function(value, index, list) { return _.pluck(_.map(obj, function(value, index, list) {
return { return {
value: value, value: value,
index: index, index: index,
criteria: iterator.call(context, value, index, list) criteria: iteratee(value, index, list)
}; };
}).sort(function(left, right) { }).sort(function(left, right) {
var a = left.criteria; var a = left.criteria;
...@@ -1168,12 +1216,12 @@ define('text',['module'], function (module) { ...@@ -1168,12 +1216,12 @@ define('text',['module'], function (module) {
// An internal function used for aggregate "group by" operations. // An internal function used for aggregate "group by" operations.
var group = function(behavior) { var group = function(behavior) {
return function(obj, iterator, context) { return function(obj, iteratee, context) {
var result = {}; var result = {};
iterator = lookupIterator(iterator); iteratee = cb(iteratee, context);
each(obj, function(value, index) { _.each(obj, function(value, index) {
var key = iterator.call(context, value, index, obj); var key = iteratee(value, index, obj);
behavior(result, key, value); behavior(result, value, key);
}); });
return result; return result;
}; };
...@@ -1181,48 +1229,46 @@ define('text',['module'], function (module) { ...@@ -1181,48 +1229,46 @@ define('text',['module'], function (module) {
// Groups the object's values by a criterion. Pass either a string attribute // Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion. // to group by, or a function that returns the criterion.
_.groupBy = group(function(result, key, value) { _.groupBy = group(function(result, value, key) {
_.has(result, key) ? result[key].push(value) : result[key] = [value]; if (_.has(result, key)) result[key].push(value); else result[key] = [value];
}); });
// Indexes the object's values by a criterion, similar to `groupBy`, but for // Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique. // when you know that your index values will be unique.
_.indexBy = group(function(result, key, value) { _.indexBy = group(function(result, value, key) {
result[key] = value; result[key] = value;
}); });
// Counts instances of an object that group by a certain criterion. Pass // Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the // either a string attribute to count by, or a function that returns the
// criterion. // criterion.
_.countBy = group(function(result, key) { _.countBy = group(function(result, value, key) {
_.has(result, key) ? result[key]++ : result[key] = 1; if (_.has(result, key)) result[key]++; else result[key] = 1;
}); });
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iterator, context) {
iterator = lookupIterator(iterator);
var value = iterator.call(context, obj);
var low = 0, high = array.length;
while (low < high) {
var mid = (low + high) >>> 1;
iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
}
return low;
};
// Safely create a real, live array from anything iterable. // Safely create a real, live array from anything iterable.
_.toArray = function(obj) { _.toArray = function(obj) {
if (!obj) return []; if (!obj) return [];
if (_.isArray(obj)) return slice.call(obj); if (_.isArray(obj)) return slice.call(obj);
if (obj.length === +obj.length) return _.map(obj, _.identity); if (isArrayLike(obj)) return _.map(obj, _.identity);
return _.values(obj); return _.values(obj);
}; };
// Return the number of elements in an object. // Return the number of elements in an object.
_.size = function(obj) { _.size = function(obj) {
if (obj == null) return 0; if (obj == null) return 0;
return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; return isArrayLike(obj) ? obj.length : _.keys(obj).length;
};
// Split a collection into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(obj, predicate, context) {
predicate = cb(predicate, context);
var pass = [], fail = [];
_.each(obj, function(value, key, obj) {
(predicate(value, key, obj) ? pass : fail).push(value);
});
return [pass, fail];
}; };
// Array Functions // Array Functions
...@@ -1233,33 +1279,30 @@ define('text',['module'], function (module) { ...@@ -1233,33 +1279,30 @@ define('text',['module'], function (module) {
// allows it to work with `_.map`. // allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) { _.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0; if (array == null) return void 0;
if ((n == null) || guard) return array[0]; if (n == null || guard) return array[0];
if (n < 0) return []; return _.initial(array, array.length - n);
return slice.call(array, 0, n);
}; };
// Returns everything but the last entry of the array. Especially useful on // Returns everything but the last entry of the array. Especially useful on
// the arguments object. Passing **n** will return all the values in // the arguments object. Passing **n** will return all the values in
// the array, excluding the last N. The **guard** check allows it to work with // the array, excluding the last N.
// `_.map`.
_.initial = function(array, n, guard) { _.initial = function(array, n, guard) {
return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
}; };
// Get the last element of an array. Passing **n** will return the last N // Get the last element of an array. Passing **n** will return the last N
// values in the array. The **guard** check allows it to work with `_.map`. // values in the array.
_.last = function(array, n, guard) { _.last = function(array, n, guard) {
if (array == null) return void 0; if (array == null) return void 0;
if ((n == null) || guard) return array[array.length - 1]; if (n == null || guard) return array[array.length - 1];
return slice.call(array, Math.max(array.length - n, 0)); return _.rest(array, Math.max(0, array.length - n));
}; };
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`. // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
// Especially useful on the arguments object. Passing an **n** will return // Especially useful on the arguments object. Passing an **n** will return
// the rest N values in the array. The **guard** // the rest N values in the array.
// check allows it to work with `_.map`.
_.rest = _.tail = _.drop = function(array, n, guard) { _.rest = _.tail = _.drop = function(array, n, guard) {
return slice.call(array, (n == null) || guard ? 1 : n); return slice.call(array, n == null || guard ? 1 : n);
}; };
// Trim out all falsy values from an array. // Trim out all falsy values from an array.
...@@ -1268,23 +1311,28 @@ define('text',['module'], function (module) { ...@@ -1268,23 +1311,28 @@ define('text',['module'], function (module) {
}; };
// Internal implementation of a recursive `flatten` function. // Internal implementation of a recursive `flatten` function.
var flatten = function(input, shallow, output) { var flatten = function(input, shallow, strict, startIndex) {
if (shallow && _.every(input, _.isArray)) { var output = [], idx = 0;
return concat.apply(output, input); for (var i = startIndex || 0, length = input && input.length; i < length; i++) {
var value = input[i];
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
//flatten current level of array or arguments object
if (!shallow) value = flatten(value, shallow, strict);
var j = 0, len = value.length;
output.length += len;
while (j < len) {
output[idx++] = value[j++];
}
} else if (!strict) {
output[idx++] = value;
} }
each(input, function(value) {
if (_.isArray(value) || _.isArguments(value)) {
shallow ? push.apply(output, value) : flatten(value, shallow, output);
} else {
output.push(value);
} }
});
return output; return output;
}; };
// Flatten out an array, either recursively (by default), or just one level. // Flatten out an array, either recursively (by default), or just one level.
_.flatten = function(array, shallow) { _.flatten = function(array, shallow) {
return flatten(array, shallow, []); return flatten(array, shallow, false);
}; };
// Return a version of the array that does not contain the specified value(s). // Return a version of the array that does not contain the specified value(s).
...@@ -1292,79 +1340,93 @@ define('text',['module'], function (module) { ...@@ -1292,79 +1340,93 @@ define('text',['module'], function (module) {
return _.difference(array, slice.call(arguments, 1)); return _.difference(array, slice.call(arguments, 1));
}; };
// Split an array into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(array, predicate) {
var pass = [], fail = [];
each(array, function(elem) {
(predicate(elem) ? pass : fail).push(elem);
});
return [pass, fail];
};
// Produce a duplicate-free version of the array. If the array has already // Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm. // been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`. // Aliased as `unique`.
_.uniq = _.unique = function(array, isSorted, iterator, context) { _.uniq = _.unique = function(array, isSorted, iteratee, context) {
if (_.isFunction(isSorted)) { if (array == null) return [];
context = iterator; if (!_.isBoolean(isSorted)) {
iterator = isSorted; context = iteratee;
iteratee = isSorted;
isSorted = false; isSorted = false;
} }
var initial = iterator ? _.map(array, iterator, context) : array; if (iteratee != null) iteratee = cb(iteratee, context);
var results = []; var result = [];
var seen = []; var seen = [];
each(initial, function(value, index) { for (var i = 0, length = array.length; i < length; i++) {
if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { var value = array[i],
seen.push(value); computed = iteratee ? iteratee(value, i, array) : value;
results.push(array[index]); if (isSorted) {
if (!i || seen !== computed) result.push(value);
seen = computed;
} else if (iteratee) {
if (!_.contains(seen, computed)) {
seen.push(computed);
result.push(value);
} }
}); } else if (!_.contains(result, value)) {
return results; result.push(value);
}
}
return result;
}; };
// Produce an array that contains the union: each distinct element from all of // Produce an array that contains the union: each distinct element from all of
// the passed-in arrays. // the passed-in arrays.
_.union = function() { _.union = function() {
return _.uniq(_.flatten(arguments, true)); return _.uniq(flatten(arguments, true, true));
}; };
// Produce an array that contains every item shared between all the // Produce an array that contains every item shared between all the
// passed-in arrays. // passed-in arrays.
_.intersection = function(array) { _.intersection = function(array) {
var rest = slice.call(arguments, 1); if (array == null) return [];
return _.filter(_.uniq(array), function(item) { var result = [];
return _.every(rest, function(other) { var argsLength = arguments.length;
return _.contains(other, item); for (var i = 0, length = array.length; i < length; i++) {
}); var item = array[i];
}); if (_.contains(result, item)) continue;
for (var j = 1; j < argsLength; j++) {
if (!_.contains(arguments[j], item)) break;
}
if (j === argsLength) result.push(item);
}
return result;
}; };
// Take the difference between one array and a number of other arrays. // Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain. // Only the elements present in just the first array will remain.
_.difference = function(array) { _.difference = function(array) {
var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); var rest = flatten(arguments, true, true, 1);
return _.filter(array, function(value){ return !_.contains(rest, value); }); return _.filter(array, function(value){
return !_.contains(rest, value);
});
}; };
// Zip together multiple lists into a single array -- elements that share // Zip together multiple lists into a single array -- elements that share
// an index go together. // an index go together.
_.zip = function() { _.zip = function() {
var length = _.max(_.pluck(arguments, 'length').concat(0)); return _.unzip(arguments);
var results = new Array(length); };
for (var i = 0; i < length; i++) {
results[i] = _.pluck(arguments, '' + i); // Complement of _.zip. Unzip accepts an array of arrays and groups
// each array's elements on shared indices
_.unzip = function(array) {
var length = array && _.max(array, 'length').length || 0;
var result = Array(length);
for (var index = 0; index < length; index++) {
result[index] = _.pluck(array, index);
} }
return results; return result;
}; };
// Converts lists into objects. Pass either a single array of `[key, value]` // Converts lists into objects. Pass either a single array of `[key, value]`
// pairs, or two parallel arrays of the same length -- one of keys, and one of // pairs, or two parallel arrays of the same length -- one of keys, and one of
// the corresponding values. // the corresponding values.
_.object = function(list, values) { _.object = function(list, values) {
if (list == null) return {};
var result = {}; var result = {};
for (var i = 0, length = list.length; i < length; i++) { for (var i = 0, length = list && list.length; i < length; i++) {
if (values) { if (values) {
result[list[i]] = values[i]; result[list[i]] = values[i];
} else { } else {
...@@ -1374,40 +1436,68 @@ define('text',['module'], function (module) { ...@@ -1374,40 +1436,68 @@ define('text',['module'], function (module) {
return result; return result;
}; };
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), // Return the position of the first occurrence of an item in an array,
// we need this function. Return the position of the first occurrence of an // or -1 if the item is not included in the array.
// item in an array, or -1 if the item is not included in the array.
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
// If the array is large and already in sort order, pass `true` // If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search. // for **isSorted** to use binary search.
_.indexOf = function(array, item, isSorted) { _.indexOf = function(array, item, isSorted) {
if (array == null) return -1; var i = 0, length = array && array.length;
var i = 0, length = array.length;
if (isSorted) {
if (typeof isSorted == 'number') { if (typeof isSorted == 'number') {
i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
} else { } else if (isSorted && length) {
i = _.sortedIndex(array, item); i = _.sortedIndex(array, item);
return array[i] === item ? i : -1; return array[i] === item ? i : -1;
} }
if (item !== item) {
return _.findIndex(slice.call(array, i), _.isNaN);
} }
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
for (; i < length; i++) if (array[i] === item) return i; for (; i < length; i++) if (array[i] === item) return i;
return -1; return -1;
}; };
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
_.lastIndexOf = function(array, item, from) { _.lastIndexOf = function(array, item, from) {
if (array == null) return -1; var idx = array ? array.length : 0;
var hasIndex = from != null; if (typeof from == 'number') {
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); }
if (item !== item) {
return _.findLastIndex(slice.call(array, 0, idx), _.isNaN);
} }
var i = (hasIndex ? from : array.length); while (--idx >= 0) if (array[idx] === item) return idx;
while (i--) if (array[i] === item) return i;
return -1; return -1;
}; };
// Generator function to create the findIndex and findLastIndex functions
function createIndexFinder(dir) {
return function(array, predicate, context) {
predicate = cb(predicate, context);
var length = array != null && array.length;
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
}
// Returns the first index on an array-like that passes a predicate test
_.findIndex = createIndexFinder(1);
_.findLastIndex = createIndexFinder(-1);
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iteratee, context) {
iteratee = cb(iteratee, context, 1);
var value = iteratee(obj);
var low = 0, high = array.length;
while (low < high) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
};
// Generate an integer Array containing an arithmetic progression. A port of // Generate an integer Array containing an arithmetic progression. A port of
// the native Python `range()` function. See // the native Python `range()` function. See
// [the Python documentation](http://docs.python.org/library/functions.html#range). // [the Python documentation](http://docs.python.org/library/functions.html#range).
...@@ -1416,15 +1506,13 @@ define('text',['module'], function (module) { ...@@ -1416,15 +1506,13 @@ define('text',['module'], function (module) {
stop = start || 0; stop = start || 0;
start = 0; start = 0;
} }
step = arguments[2] || 1; step = step || 1;
var length = Math.max(Math.ceil((stop - start) / step), 0); var length = Math.max(Math.ceil((stop - start) / step), 0);
var idx = 0; var range = Array(length);
var range = new Array(length);
while(idx < length) { for (var idx = 0; idx < length; idx++, start += step) {
range[idx++] = start; range[idx] = start;
start += step;
} }
return range; return range;
...@@ -1433,26 +1521,27 @@ define('text',['module'], function (module) { ...@@ -1433,26 +1521,27 @@ define('text',['module'], function (module) {
// Function (ahem) Functions // Function (ahem) Functions
// ------------------ // ------------------
// Reusable constructor function for prototype setting. // Determines whether to execute a function as a constructor
var ctor = function(){}; // or a normal function with the provided arguments
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
var self = baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
if (_.isObject(result)) return result;
return self;
};
// Create a function bound to a given object (assigning `this`, and arguments, // Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
// available. // available.
_.bind = function(func, context) { _.bind = function(func, context) {
var args, bound;
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError; if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
return bound = function() { var bound = function() {
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
ctor.prototype = func.prototype;
var self = new ctor;
ctor.prototype = null;
var result = func.apply(self, args.concat(slice.call(arguments)));
if (Object(result) === result) return result;
return self;
}; };
return bound;
}; };
// Partially apply a function by creating a version that has had some of its // Partially apply a function by creating a version that has had some of its
...@@ -1460,49 +1549,55 @@ define('text',['module'], function (module) { ...@@ -1460,49 +1549,55 @@ define('text',['module'], function (module) {
// as a placeholder, allowing any combination of arguments to be pre-filled. // as a placeholder, allowing any combination of arguments to be pre-filled.
_.partial = function(func) { _.partial = function(func) {
var boundArgs = slice.call(arguments, 1); var boundArgs = slice.call(arguments, 1);
return function() { var bound = function() {
var position = 0; var position = 0, length = boundArgs.length;
var args = boundArgs.slice(); var args = Array(length);
for (var i = 0, length = args.length; i < length; i++) { for (var i = 0; i < length; i++) {
if (args[i] === _) args[i] = arguments[position++]; args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
} }
while (position < arguments.length) args.push(arguments[position++]); while (position < arguments.length) args.push(arguments[position++]);
return func.apply(this, args); return executeBound(func, bound, this, this, args);
}; };
return bound;
}; };
// Bind a number of an object's methods to that object. Remaining arguments // Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks // are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it. // defined on an object belong to it.
_.bindAll = function(obj) { _.bindAll = function(obj) {
var funcs = slice.call(arguments, 1); var i, length = arguments.length, key;
if (funcs.length === 0) throw new Error('bindAll must be passed function names'); if (length <= 1) throw new Error('bindAll must be passed function names');
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); for (i = 1; i < length; i++) {
key = arguments[i];
obj[key] = _.bind(obj[key], obj);
}
return obj; return obj;
}; };
// Memoize an expensive function by storing its results. // Memoize an expensive function by storing its results.
_.memoize = function(func, hasher) { _.memoize = function(func, hasher) {
var memo = {}; var memoize = function(key) {
hasher || (hasher = _.identity); var cache = memoize.cache;
return function() { var address = '' + (hasher ? hasher.apply(this, arguments) : key);
var key = hasher.apply(this, arguments); if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); return cache[address];
}; };
memoize.cache = {};
return memoize;
}; };
// Delays a function for the given number of milliseconds, and then calls // Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied. // it with the arguments supplied.
_.delay = function(func, wait) { _.delay = function(func, wait) {
var args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
return setTimeout(function(){ return func.apply(null, args); }, wait); return setTimeout(function(){
return func.apply(null, args);
}, wait);
}; };
// Defers a function, scheduling it to run after the current call stack has // Defers a function, scheduling it to run after the current call stack has
// cleared. // cleared.
_.defer = function(func) { _.defer = _.partial(_.delay, _, 1);
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
};
// Returns a function, that, when invoked, will only be triggered at most once // Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run // during a given window of time. Normally, the throttled function will run
...@@ -1513,12 +1608,12 @@ define('text',['module'], function (module) { ...@@ -1513,12 +1608,12 @@ define('text',['module'], function (module) {
var context, args, result; var context, args, result;
var timeout = null; var timeout = null;
var previous = 0; var previous = 0;
options || (options = {}); if (!options) options = {};
var later = function() { var later = function() {
previous = options.leading === false ? 0 : _.now(); previous = options.leading === false ? 0 : _.now();
timeout = null; timeout = null;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
}; };
return function() { return function() {
var now = _.now(); var now = _.now();
...@@ -1526,12 +1621,14 @@ define('text',['module'], function (module) { ...@@ -1526,12 +1621,14 @@ define('text',['module'], function (module) {
var remaining = wait - (now - previous); var remaining = wait - (now - previous);
context = this; context = this;
args = arguments; args = arguments;
if (remaining <= 0) { if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout); clearTimeout(timeout);
timeout = null; timeout = null;
}
previous = now; previous = now;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) { } else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining); timeout = setTimeout(later, remaining);
} }
...@@ -1548,13 +1645,14 @@ define('text',['module'], function (module) { ...@@ -1548,13 +1645,14 @@ define('text',['module'], function (module) {
var later = function() { var later = function() {
var last = _.now() - timestamp; var last = _.now() - timestamp;
if (last < wait) {
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last); timeout = setTimeout(later, wait - last);
} else { } else {
timeout = null; timeout = null;
if (!immediate) { if (!immediate) {
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; if (!timeout) context = args = null;
} }
} }
}; };
...@@ -1564,9 +1662,7 @@ define('text',['module'], function (module) { ...@@ -1564,9 +1662,7 @@ define('text',['module'], function (module) {
args = arguments; args = arguments;
timestamp = _.now(); timestamp = _.now();
var callNow = immediate && !timeout; var callNow = immediate && !timeout;
if (!timeout) { if (!timeout) timeout = setTimeout(later, wait);
timeout = setTimeout(later, wait);
}
if (callNow) { if (callNow) {
result = func.apply(context, args); result = func.apply(context, args);
context = args = null; context = args = null;
...@@ -1576,19 +1672,6 @@ define('text',['module'], function (module) { ...@@ -1576,19 +1672,6 @@ define('text',['module'], function (module) {
}; };
}; };
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
// Returns the first function passed as an argument to the second, // Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and // allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function. // conditionally execute the original function.
...@@ -1596,20 +1679,27 @@ define('text',['module'], function (module) { ...@@ -1596,20 +1679,27 @@ define('text',['module'], function (module) {
return _.partial(wrapper, func); return _.partial(wrapper, func);
}; };
// Returns a negated version of the passed-in predicate.
_.negate = function(predicate) {
return function() {
return !predicate.apply(this, arguments);
};
};
// Returns a function that is the composition of a list of functions, each // Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows. // consuming the return value of the function that follows.
_.compose = function() { _.compose = function() {
var funcs = arguments;
return function() {
var args = arguments; var args = arguments;
for (var i = funcs.length - 1; i >= 0; i--) { var start = args.length - 1;
args = [funcs[i].apply(this, args)]; return function() {
} var i = start;
return args[0]; var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
}; };
}; };
// Returns a function that will only be executed after being called N times. // Returns a function that will only be executed on and after the Nth call.
_.after = function(times, func) { _.after = function(times, func) {
return function() { return function() {
if (--times < 1) { if (--times < 1) {
...@@ -1618,16 +1708,66 @@ define('text',['module'], function (module) { ...@@ -1618,16 +1708,66 @@ define('text',['module'], function (module) {
}; };
}; };
// Returns a function that will only be executed up to (but not including) the Nth call.
_.before = function(times, func) {
var memo;
return function() {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
};
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = _.partial(_.before, 2);
// Object Functions // Object Functions
// ---------------- // ----------------
// Retrieve the names of an object's properties. // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
function collectNonEnumProps(obj, keys) {
var nonEnumIdx = nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
// Constructor is a special case.
var prop = 'constructor';
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
while (nonEnumIdx--) {
prop = nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
keys.push(prop);
}
}
}
// Retrieve the names of an object's own properties.
// Delegates to **ECMAScript 5**'s native `Object.keys` // Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = function(obj) { _.keys = function(obj) {
if (!_.isObject(obj)) return []; if (!_.isObject(obj)) return [];
if (nativeKeys) return nativeKeys(obj); if (nativeKeys) return nativeKeys(obj);
var keys = []; var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key); for (var key in obj) if (_.has(obj, key)) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Retrieve all the property names of an object.
_.allKeys = function(obj) {
if (!_.isObject(obj)) return [];
var keys = [];
for (var key in obj) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys; return keys;
}; };
...@@ -1635,18 +1775,33 @@ define('text',['module'], function (module) { ...@@ -1635,18 +1775,33 @@ define('text',['module'], function (module) {
_.values = function(obj) { _.values = function(obj) {
var keys = _.keys(obj); var keys = _.keys(obj);
var length = keys.length; var length = keys.length;
var values = new Array(length); var values = Array(length);
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]]; values[i] = obj[keys[i]];
} }
return values; return values;
}; };
// Returns the results of applying the iteratee to each element of the object
// In contrast to _.map it returns an object
_.mapObject = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = _.keys(obj),
length = keys.length,
results = {},
currentKey;
for (var index = 0; index < length; index++) {
currentKey = keys[index];
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
// Convert an object into a list of `[key, value]` pairs. // Convert an object into a list of `[key, value]` pairs.
_.pairs = function(obj) { _.pairs = function(obj) {
var keys = _.keys(obj); var keys = _.keys(obj);
var length = keys.length; var length = keys.length;
var pairs = new Array(length); var pairs = Array(length);
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]]; pairs[i] = [keys[i], obj[keys[i]]];
} }
...@@ -1674,48 +1829,57 @@ define('text',['module'], function (module) { ...@@ -1674,48 +1829,57 @@ define('text',['module'], function (module) {
}; };
// Extend a given object with all the properties in passed-in object(s). // Extend a given object with all the properties in passed-in object(s).
_.extend = function(obj) { _.extend = createAssigner(_.allKeys);
each(slice.call(arguments, 1), function(source) {
if (source) { // Assigns a given object with all the own properties in the passed-in object(s)
for (var prop in source) { // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
obj[prop] = source[prop]; _.extendOwn = _.assign = createAssigner(_.keys);
}
// Returns the first key on an object that passes a predicate test
_.findKey = function(obj, predicate, context) {
predicate = cb(predicate, context);
var keys = _.keys(obj), key;
for (var i = 0, length = keys.length; i < length; i++) {
key = keys[i];
if (predicate(obj[key], key, obj)) return key;
} }
});
return obj;
}; };
// Return a copy of the object only containing the whitelisted properties. // Return a copy of the object only containing the whitelisted properties.
_.pick = function(obj) { _.pick = function(object, oiteratee, context) {
var copy = {}; var result = {}, obj = object, iteratee, keys;
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); if (obj == null) return result;
each(keys, function(key) { if (_.isFunction(oiteratee)) {
if (key in obj) copy[key] = obj[key]; keys = _.allKeys(obj);
}); iteratee = optimizeCb(oiteratee, context);
return copy; } else {
keys = flatten(arguments, false, false, 1);
iteratee = function(value, key, obj) { return key in obj; };
obj = Object(obj);
}
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
var value = obj[key];
if (iteratee(value, key, obj)) result[key] = value;
}
return result;
}; };
// Return a copy of the object without the blacklisted properties. // Return a copy of the object without the blacklisted properties.
_.omit = function(obj) { _.omit = function(obj, iteratee, context) {
var copy = {}; if (_.isFunction(iteratee)) {
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); iteratee = _.negate(iteratee);
for (var key in obj) { } else {
if (!_.contains(keys, key)) copy[key] = obj[key]; var keys = _.map(flatten(arguments, false, false, 1), String);
iteratee = function(value, key) {
return !_.contains(keys, key);
};
} }
return copy; return _.pick(obj, iteratee, context);
}; };
// Fill in a given object with default properties. // Fill in a given object with default properties.
_.defaults = function(obj) { _.defaults = createAssigner(_.allKeys, true);
each(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) {
if (obj[prop] === void 0) obj[prop] = source[prop];
}
}
});
return obj;
};
// Create a (shallow-cloned) duplicate of an object. // Create a (shallow-cloned) duplicate of an object.
_.clone = function(obj) { _.clone = function(obj) {
...@@ -1731,11 +1895,24 @@ define('text',['module'], function (module) { ...@@ -1731,11 +1895,24 @@ define('text',['module'], function (module) {
return obj; return obj;
}; };
// Returns whether an object has a given set of `key:value` pairs.
_.isMatch = function(object, attrs) {
var keys = _.keys(attrs), length = keys.length;
if (object == null) return !length;
var obj = Object(object);
for (var i = 0; i < length; i++) {
var key = keys[i];
if (attrs[key] !== obj[key] || !(key in obj)) return false;
}
return true;
};
// Internal recursive comparison function for `isEqual`. // Internal recursive comparison function for `isEqual`.
var eq = function(a, b, aStack, bStack) { var eq = function(a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical. // Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a == 1 / b; if (a === b) return a !== 0 || 1 / a === 1 / b;
// A strict comparison is necessary because `null == undefined`. // A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b; if (a == null || b == null) return a === b;
// Unwrap any wrapped objects. // Unwrap any wrapped objects.
...@@ -1743,98 +1920,98 @@ define('text',['module'], function (module) { ...@@ -1743,98 +1920,98 @@ define('text',['module'], function (module) {
if (b instanceof _) b = b._wrapped; if (b instanceof _) b = b._wrapped;
// Compare `[[Class]]` names. // Compare `[[Class]]` names.
var className = toString.call(a); var className = toString.call(a);
if (className != toString.call(b)) return false; if (className !== toString.call(b)) return false;
switch (className) { switch (className) {
// Strings, numbers, dates, and booleans are compared by value. // Strings, numbers, regular expressions, dates, and booleans are compared by value.
case '[object RegExp]':
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case '[object String]': case '[object String]':
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`. // equivalent to `new String("5")`.
return a == String(b); return '' + a === '' + b;
case '[object Number]': case '[object Number]':
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for // `NaN`s are equivalent, but non-reflexive.
// other numeric values. // Object(NaN) is equivalent to NaN
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); if (+a !== +a) return +b !== +b;
// An `egal` comparison is performed for other numeric values.
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]': case '[object Date]':
case '[object Boolean]': case '[object Boolean]':
// Coerce dates and booleans to numeric primitive values. Dates are compared by their // Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations // millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent. // of `NaN` are not equivalent.
return +a == +b; return +a === +b;
// RegExps are compared by their source patterns and flags.
case '[object RegExp]':
return a.source == b.source &&
a.global == b.global &&
a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase;
} }
var areArrays = className === '[object Array]';
if (!areArrays) {
if (typeof a != 'object' || typeof b != 'object') return false; if (typeof a != 'object' || typeof b != 'object') return false;
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
_.isFunction(bCtor) && bCtor instanceof bCtor)
&& ('constructor' in a && 'constructor' in b)) {
return false;
}
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic // Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
// Initializing stack of traversed objects.
// It's done here since we only need them for objects and arrays comparison.
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length; var length = aStack.length;
while (length--) { while (length--) {
// Linear search. Performance is inversely proportional to the number of // Linear search. Performance is inversely proportional to the number of
// unique nested structures. // unique nested structures.
if (aStack[length] == a) return bStack[length] == b; if (aStack[length] === a) return bStack[length] === b;
}
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
_.isFunction(bCtor) && (bCtor instanceof bCtor))
&& ('constructor' in a && 'constructor' in b)) {
return false;
} }
// Add the first object to the stack of traversed objects. // Add the first object to the stack of traversed objects.
aStack.push(a); aStack.push(a);
bStack.push(b); bStack.push(b);
var size = 0, result = true;
// Recursively compare objects and arrays. // Recursively compare objects and arrays.
if (className == '[object Array]') { if (areArrays) {
// Compare array lengths to determine if a deep comparison is necessary. // Compare array lengths to determine if a deep comparison is necessary.
size = a.length; length = a.length;
result = size == b.length; if (length !== b.length) return false;
if (result) {
// Deep compare the contents, ignoring non-numeric properties. // Deep compare the contents, ignoring non-numeric properties.
while (size--) { while (length--) {
if (!(result = eq(a[size], b[size], aStack, bStack))) break; if (!eq(a[length], b[length], aStack, bStack)) return false;
}
} }
} else { } else {
// Deep compare objects. // Deep compare objects.
for (var key in a) { var keys = _.keys(a), key;
if (_.has(a, key)) { length = keys.length;
// Count the expected number of properties. // Ensure that both objects contain the same number of properties before comparing deep equality.
size++; if (_.keys(b).length !== length) return false;
// Deep compare each member. while (length--) {
if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; // Deep compare each member
} key = keys[length];
} if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
// Ensure that both objects contain the same number of properties.
if (result) {
for (key in b) {
if (_.has(b, key) && !(size--)) break;
}
result = !size;
} }
} }
// Remove the first object from the stack of traversed objects. // Remove the first object from the stack of traversed objects.
aStack.pop(); aStack.pop();
bStack.pop(); bStack.pop();
return result; return true;
}; };
// Perform a deep comparison to check if two objects are equal. // Perform a deep comparison to check if two objects are equal.
_.isEqual = function(a, b) { _.isEqual = function(a, b) {
return eq(a, b, [], []); return eq(a, b);
}; };
// Is a given array, string, or object empty? // Is a given array, string, or object empty?
// An "empty" object has no enumerable own-properties. // An "empty" object has no enumerable own-properties.
_.isEmpty = function(obj) { _.isEmpty = function(obj) {
if (obj == null) return true; if (obj == null) return true;
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
for (var key in obj) if (_.has(obj, key)) return false; return _.keys(obj).length === 0;
return true;
}; };
// Is a given value a DOM element? // Is a given value a DOM element?
...@@ -1845,33 +2022,35 @@ define('text',['module'], function (module) { ...@@ -1845,33 +2022,35 @@ define('text',['module'], function (module) {
// Is a given value an array? // Is a given value an array?
// Delegates to ECMA5's native Array.isArray // Delegates to ECMA5's native Array.isArray
_.isArray = nativeIsArray || function(obj) { _.isArray = nativeIsArray || function(obj) {
return toString.call(obj) == '[object Array]'; return toString.call(obj) === '[object Array]';
}; };
// Is a given variable an object? // Is a given variable an object?
_.isObject = function(obj) { _.isObject = function(obj) {
return obj === Object(obj); var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
}; };
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
_['is' + name] = function(obj) { _['is' + name] = function(obj) {
return toString.call(obj) == '[object ' + name + ']'; return toString.call(obj) === '[object ' + name + ']';
}; };
}); });
// Define a fallback version of the method in browsers (ahem, IE), where // Define a fallback version of the method in browsers (ahem, IE < 9), where
// there isn't any inspectable "Arguments" type. // there isn't any inspectable "Arguments" type.
if (!_.isArguments(arguments)) { if (!_.isArguments(arguments)) {
_.isArguments = function(obj) { _.isArguments = function(obj) {
return !!(obj && _.has(obj, 'callee')); return _.has(obj, 'callee');
}; };
} }
// Optimize `isFunction` if appropriate. // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
if (typeof (/./) !== 'function') { // IE 11 (#1621), and in Safari 8 (#1929).
if (typeof /./ != 'function' && typeof Int8Array != 'object') {
_.isFunction = function(obj) { _.isFunction = function(obj) {
return typeof obj === 'function'; return typeof obj == 'function' || false;
}; };
} }
...@@ -1882,12 +2061,12 @@ define('text',['module'], function (module) { ...@@ -1882,12 +2061,12 @@ define('text',['module'], function (module) {
// Is the given value `NaN`? (NaN is the only number which does not equal itself). // Is the given value `NaN`? (NaN is the only number which does not equal itself).
_.isNaN = function(obj) { _.isNaN = function(obj) {
return _.isNumber(obj) && obj != +obj; return _.isNumber(obj) && obj !== +obj;
}; };
// Is a given value a boolean? // Is a given value a boolean?
_.isBoolean = function(obj) { _.isBoolean = function(obj) {
return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
}; };
// Is a given value equal to null? // Is a given value equal to null?
...@@ -1903,7 +2082,7 @@ define('text',['module'], function (module) { ...@@ -1903,7 +2082,7 @@ define('text',['module'], function (module) {
// Shortcut function for checking if an object has a given property directly // Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype). // on itself (in other words, not on a prototype).
_.has = function(obj, key) { _.has = function(obj, key) {
return hasOwnProperty.call(obj, key); return obj != null && hasOwnProperty.call(obj, key);
}; };
// Utility Functions // Utility Functions
...@@ -1916,39 +2095,47 @@ define('text',['module'], function (module) { ...@@ -1916,39 +2095,47 @@ define('text',['module'], function (module) {
return this; return this;
}; };
// Keep the identity function around for default iterators. // Keep the identity function around for default iteratees.
_.identity = function(value) { _.identity = function(value) {
return value; return value;
}; };
// Predicate-generating functions. Often useful outside of Underscore.
_.constant = function(value) { _.constant = function(value) {
return function () { return function() {
return value; return value;
}; };
}; };
_.noop = function(){};
_.property = function(key) { _.property = function(key) {
return function(obj) { return function(obj) {
return obj == null ? void 0 : obj[key];
};
};
// Generates a function for a given object that returns a given property.
_.propertyOf = function(obj) {
return obj == null ? function(){} : function(key) {
return obj[key]; return obj[key];
}; };
}; };
// Returns a predicate for checking whether an object has a given set of `key:value` pairs. // Returns a predicate for checking whether an object has a given set of
_.matches = function(attrs) { // `key:value` pairs.
_.matcher = _.matches = function(attrs) {
attrs = _.extendOwn({}, attrs);
return function(obj) { return function(obj) {
if (obj === attrs) return true; //avoid comparing an object to itself. return _.isMatch(obj, attrs);
for (var key in attrs) { };
if (attrs[key] !== obj[key])
return false;
}
return true;
}
}; };
// Run a function **n** times. // Run a function **n** times.
_.times = function(n, iterator, context) { _.times = function(n, iteratee, context) {
var accum = Array(Math.max(0, n)); var accum = Array(Math.max(0, n));
for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); iteratee = optimizeCb(iteratee, context, 1);
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
return accum; return accum;
}; };
...@@ -1962,56 +2149,48 @@ define('text',['module'], function (module) { ...@@ -1962,56 +2149,48 @@ define('text',['module'], function (module) {
}; };
// A (possibly faster) way to get the current timestamp as an integer. // A (possibly faster) way to get the current timestamp as an integer.
_.now = Date.now || function() { return new Date().getTime(); }; _.now = Date.now || function() {
return new Date().getTime();
};
// List of HTML entities for escaping. // List of HTML entities for escaping.
var entityMap = { var escapeMap = {
escape: {
'&': '&amp;', '&': '&amp;',
'<': '&lt;', '<': '&lt;',
'>': '&gt;', '>': '&gt;',
'"': '&quot;', '"': '&quot;',
"'": '&#x27;' "'": '&#x27;',
} '`': '&#x60;'
};
entityMap.unescape = _.invert(entityMap.escape);
// Regexes containing the keys and values listed immediately above.
var entityRegexes = {
escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
}; };
var unescapeMap = _.invert(escapeMap);
// Functions for escaping and unescaping strings to/from HTML interpolation. // Functions for escaping and unescaping strings to/from HTML interpolation.
_.each(['escape', 'unescape'], function(method) { var createEscaper = function(map) {
_[method] = function(string) { var escaper = function(match) {
if (string == null) return ''; return map[match];
return ('' + string).replace(entityRegexes[method], function(match) {
return entityMap[method][match];
});
}; };
}); // Regexes for identifying a key that needs to be escaped
var source = '(?:' + _.keys(map).join('|') + ')';
var testRegexp = RegExp(source);
var replaceRegexp = RegExp(source, 'g');
return function(string) {
string = string == null ? '' : '' + string;
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
};
};
_.escape = createEscaper(escapeMap);
_.unescape = createEscaper(unescapeMap);
// If the value of the named `property` is a function then invoke it with the // If the value of the named `property` is a function then invoke it with the
// `object` as context; otherwise, return it. // `object` as context; otherwise, return it.
_.result = function(object, property) { _.result = function(object, property, fallback) {
if (object == null) return void 0; var value = object == null ? void 0 : object[property];
var value = object[property]; if (value === void 0) {
value = fallback;
}
return _.isFunction(value) ? value.call(object) : value; return _.isFunction(value) ? value.call(object) : value;
}; };
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result.call(this, func.apply(_, args));
};
});
};
// Generate a unique integer id (unique within the entire client session). // Generate a unique integer id (unique within the entire client session).
// Useful for temporary DOM ids. // Useful for temporary DOM ids.
var idCounter = 0; var idCounter = 0;
...@@ -2040,22 +2219,26 @@ define('text',['module'], function (module) { ...@@ -2040,22 +2219,26 @@ define('text',['module'], function (module) {
'\\': '\\', '\\': '\\',
'\r': 'r', '\r': 'r',
'\n': 'n', '\n': 'n',
'\t': 't',
'\u2028': 'u2028', '\u2028': 'u2028',
'\u2029': 'u2029' '\u2029': 'u2029'
}; };
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function(match) {
return '\\' + escapes[match];
};
// JavaScript micro-templating, similar to John Resig's implementation. // JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace, // Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code. // and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) { // NB: `oldSettings` only exists for backwards compatibility.
var render; _.template = function(text, settings, oldSettings) {
if (!settings && oldSettings) settings = oldSettings;
settings = _.defaults({}, settings, _.templateSettings); settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation. // Combine delimiters into one regular expression via alternation.
var matcher = new RegExp([ var matcher = RegExp([
(settings.escape || noMatch).source, (settings.escape || noMatch).source,
(settings.interpolate || noMatch).source, (settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source (settings.evaluate || noMatch).source
...@@ -2065,19 +2248,18 @@ define('text',['module'], function (module) { ...@@ -2065,19 +2248,18 @@ define('text',['module'], function (module) {
var index = 0; var index = 0;
var source = "__p+='"; var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset) source += text.slice(index, offset).replace(escaper, escapeChar);
.replace(escaper, function(match) { return '\\' + escapes[match]; }); index = offset + match.length;
if (escape) { if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
} } else if (interpolate) {
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
} } else if (evaluate) {
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='"; source += "';\n" + evaluate + "\n__p+='";
} }
index = offset + match.length;
// Adobe VMs need the match returned to produce the correct offest.
return match; return match;
}); });
source += "';\n"; source += "';\n";
...@@ -2087,29 +2269,31 @@ define('text',['module'], function (module) { ...@@ -2087,29 +2269,31 @@ define('text',['module'], function (module) {
source = "var __t,__p='',__j=Array.prototype.join," + source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" + "print=function(){__p+=__j.call(arguments,'');};\n" +
source + "return __p;\n"; source + 'return __p;\n';
try { try {
render = new Function(settings.variable || 'obj', '_', source); var render = new Function(settings.variable || 'obj', '_', source);
} catch (e) { } catch (e) {
e.source = source; e.source = source;
throw e; throw e;
} }
if (data) return render(data, _);
var template = function(data) { var template = function(data) {
return render.call(this, data, _); return render.call(this, data, _);
}; };
// Provide the compiled function source as a convenience for precompilation. // Provide the compiled source as a convenience for precompilation.
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; var argument = settings.variable || 'obj';
template.source = 'function(' + argument + '){\n' + source + '}';
return template; return template;
}; };
// Add a "chain" function, which will delegate to the wrapper. // Add a "chain" function. Start chaining a wrapped Underscore object.
_.chain = function(obj) { _.chain = function(obj) {
return _(obj).chain(); var instance = _(obj);
instance._chain = true;
return instance;
}; };
// OOP // OOP
...@@ -2119,46 +2303,56 @@ define('text',['module'], function (module) { ...@@ -2119,46 +2303,56 @@ define('text',['module'], function (module) {
// underscore functions. Wrapped objects may be chained. // underscore functions. Wrapped objects may be chained.
// Helper function to continue chaining intermediate results. // Helper function to continue chaining intermediate results.
var result = function(obj) { var result = function(instance, obj) {
return this._chain ? _(obj).chain() : obj; return instance._chain ? _(obj).chain() : obj;
};
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result(this, func.apply(_, args));
};
});
}; };
// Add all of the Underscore functions to the wrapper object. // Add all of the Underscore functions to the wrapper object.
_.mixin(_); _.mixin(_);
// Add all mutator Array functions to the wrapper. // Add all mutator Array functions to the wrapper.
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
var method = ArrayProto[name]; var method = ArrayProto[name];
_.prototype[name] = function() { _.prototype[name] = function() {
var obj = this._wrapped; var obj = this._wrapped;
method.apply(obj, arguments); method.apply(obj, arguments);
if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
return result.call(this, obj); return result(this, obj);
}; };
}); });
// Add all accessor Array functions to the wrapper. // Add all accessor Array functions to the wrapper.
each(['concat', 'join', 'slice'], function(name) { _.each(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name]; var method = ArrayProto[name];
_.prototype[name] = function() { _.prototype[name] = function() {
return result.call(this, method.apply(this._wrapped, arguments)); return result(this, method.apply(this._wrapped, arguments));
}; };
}); });
_.extend(_.prototype, {
// Start chaining a wrapped Underscore object.
chain: function() {
this._chain = true;
return this;
},
// Extracts the result from a wrapped and chained object. // Extracts the result from a wrapped and chained object.
value: function() { _.prototype.value = function() {
return this._wrapped; return this._wrapped;
} };
}); // Provide unwrapping proxy for some methods used in engine operations
// such as arithmetic and JSON stringification.
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
_.prototype.toString = function() {
return '' + this._wrapped;
};
// AMD registration happens at the end for compatibility with AMD loaders // AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general // that may not enforce next-turn semantics on modules. Even though general
...@@ -2172,7 +2366,7 @@ define('text',['module'], function (module) { ...@@ -2172,7 +2366,7 @@ define('text',['module'], function (module) {
return _; return _;
}); });
} }
}).call(this); }.call(this));
// RequireJS UnderscoreJS template plugin // RequireJS UnderscoreJS template plugin
// http://github.com/jfparadis/requirejs-tpl // http://github.com/jfparadis/requirejs-tpl
...@@ -2697,7 +2891,7 @@ var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments ...@@ -2697,7 +2891,7 @@ var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments
with(obj||{}){ with(obj||{}){
__p+='<form id="converse-login" method="post">\n <label>'+ __p+='<form id="converse-login" method="post">\n <label>'+
((__t=(label_username))==null?'':__t)+ ((__t=(label_username))==null?'':__t)+
'</label>\n <input type="username" name="jid" placeholder="user@server">\n <label>'+ '</label>\n <input type="email" name="jid" placeholder="user@server">\n <label>'+
((__t=(label_password))==null?'':__t)+ ((__t=(label_password))==null?'':__t)+
'</label>\n <input type="password" name="password" placeholder="password">\n <input class="submit" type="submit" value="'+ '</label>\n <input type="password" name="password" placeholder="password">\n <input class="submit" type="submit" value="'+
((__t=(label_login))==null?'':__t)+ ((__t=(label_login))==null?'':__t)+
...@@ -3026,7 +3220,9 @@ __p+='<form class="add-chatroom" action="" method="post">\n <label>'+ ...@@ -3026,7 +3220,9 @@ __p+='<form class="add-chatroom" action="" method="post">\n <label>'+
((__t=(label_nickname))==null?'':__t)+ ((__t=(label_nickname))==null?'':__t)+
'</label>\n <input type="text" name="nick" class="new-chatroom-nick"\n placeholder="'+ '</label>\n <input type="text" name="nick" class="new-chatroom-nick"\n placeholder="'+
((__t=(label_nickname))==null?'':__t)+ ((__t=(label_nickname))==null?'':__t)+
'"/>\n <label>'+ '"/>\n <label'+
((__t=(server_label_global_attr))==null?'':__t)+
'>'+
((__t=(label_server))==null?'':__t)+ ((__t=(label_server))==null?'':__t)+
'</label>\n <input type="'+ '</label>\n <input type="'+
((__t=(server_input_type))==null?'':__t)+ ((__t=(server_input_type))==null?'':__t)+
...@@ -3072,9 +3268,13 @@ __p+='<a class="open-chat" title="Name: '+ ...@@ -3072,9 +3268,13 @@ __p+='<a class="open-chat" title="Name: '+
((__t=(desc_status))==null?'':__t)+ ((__t=(desc_status))==null?'':__t)+
'"></span>'+ '"></span>'+
((__t=(fullname))==null?'':__t)+ ((__t=(fullname))==null?'':__t)+
'</a>\n<a class="remove-xmpp-contact icon-remove" title="'+ '</a>\n';
if (allow_contact_removal) {
__p+='\n<a class="remove-xmpp-contact icon-remove" title="'+
((__t=(desc_remove))==null?'':__t)+ ((__t=(desc_remove))==null?'':__t)+
'" href="#"></a>\n'; '" href="#"></a>\n';
}
__p+='\n';
} }
return __p; return __p;
}; }); }; });
...@@ -24276,19 +24476,6 @@ define("converse-dependencies", [ ...@@ -24276,19 +24476,6 @@ define("converse-dependencies", [
return this; return this;
}; };
var playNotification = function () {
var audio;
if (converse.play_sounds && typeof Audio !== "undefined"){
audio = new Audio("sounds/msg_received.ogg");
if (audio.canPlayType('/audio/ogg')) {
audio.play();
} else {
audio = new Audio("/sounds/msg_received.mp3");
audio.play();
}
}
};
var converse = { var converse = {
plugins: {}, plugins: {},
templates: templates, templates: templates,
...@@ -24395,6 +24582,7 @@ define("converse-dependencies", [ ...@@ -24395,6 +24582,7 @@ define("converse-dependencies", [
// Default configuration values // Default configuration values
// ---------------------------- // ----------------------------
this.default_settings = { this.default_settings = {
allow_contact_removal: true,
allow_contact_requests: true, allow_contact_requests: true,
allow_dragresize: true, allow_dragresize: true,
allow_logout: true, allow_logout: true,
...@@ -24509,6 +24697,19 @@ define("converse-dependencies", [ ...@@ -24509,6 +24697,19 @@ define("converse-dependencies", [
// Module-level functions // Module-level functions
// ---------------------- // ----------------------
this.playNotification = function () {
var audio;
if (converse.play_sounds && typeof Audio !== "undefined"){
audio = new Audio("sounds/msg_received.ogg");
if (audio.canPlayType('/audio/ogg')) {
audio.play();
} else {
audio = new Audio("/sounds/msg_received.mp3");
audio.play();
}
}
};
this.giveFeedback = function (message, klass) { this.giveFeedback = function (message, klass) {
$('.conn-feedback').each(function (idx, el) { $('.conn-feedback').each(function (idx, el) {
var $el = $(el); var $el = $(el);
...@@ -24581,7 +24782,6 @@ define("converse-dependencies", [ ...@@ -24581,7 +24782,6 @@ define("converse-dependencies", [
this.reconnect = function () { this.reconnect = function () {
converse.giveFeedback(__('Reconnecting'), 'error'); converse.giveFeedback(__('Reconnecting'), 'error');
converse.emit('reconnect');
if (!converse.prebind) { if (!converse.prebind) {
this.connection.connect( this.connection.connect(
this.connection.jid, this.connection.jid,
...@@ -24593,6 +24793,10 @@ define("converse-dependencies", [ ...@@ -24593,6 +24793,10 @@ define("converse-dependencies", [
this.connection.hold, this.connection.hold,
this.connection.route this.connection.route
); );
} else if (converse.prebind_url) {
this.clearSession();
this._tearDown();
this.startNewBOSHSession();
} }
}; };
...@@ -24629,6 +24833,7 @@ define("converse-dependencies", [ ...@@ -24629,6 +24833,7 @@ define("converse-dependencies", [
converse.giveFeedback(__('Authentication Failed'), 'error'); converse.giveFeedback(__('Authentication Failed'), 'error');
converse.connection.disconnect(__('Authentication Failed')); converse.connection.disconnect(__('Authentication Failed'));
} else if (status === Strophe.Status.DISCONNECTING) { } else if (status === Strophe.Status.DISCONNECTING) {
// FIXME: what about prebind?
if (!converse.connection.connected) { if (!converse.connection.connected) {
converse.renderLoginPanel(); converse.renderLoginPanel();
} }
...@@ -24704,8 +24909,8 @@ define("converse-dependencies", [ ...@@ -24704,8 +24909,8 @@ define("converse-dependencies", [
this.clearSession = function () { this.clearSession = function () {
this.roster.browserStorage._clear(); this.roster.browserStorage._clear();
this.session.browserStorage._clear(); this.session.browserStorage._clear();
// XXX: this should perhaps go into the beforeunload handler var controlbox = converse.chatboxes.get('controlbox');
converse.chatboxes.get('controlbox').save({'connected': false}); controlbox.save({'connected': false});
}; };
this.setSession = function () { this.setSession = function () {
...@@ -25910,6 +26115,7 @@ define("converse-dependencies", [ ...@@ -25910,6 +26115,7 @@ define("converse-dependencies", [
this.$el.html( this.$el.html(
converse.templates.room_panel({ converse.templates.room_panel({
'server_input_type': converse.hide_muc_server && 'hidden' || 'text', 'server_input_type': converse.hide_muc_server && 'hidden' || 'text',
'server_label_global_attr': converse.hide_muc_server && ' hidden' || '',
'label_room_name': __('Room name'), 'label_room_name': __('Room name'),
'label_nickname': __('Nickname'), 'label_nickname': __('Nickname'),
'label_server': __('Server'), 'label_server': __('Server'),
...@@ -27122,7 +27328,7 @@ define("converse-dependencies", [ ...@@ -27122,7 +27328,7 @@ define("converse-dependencies", [
} }
this.model.createMessage($message); this.model.createMessage($message);
if (!delayed && sender !== this.model.get('nick') && (new RegExp("\\b"+this.model.get('nick')+"\\b")).test(body)) { if (!delayed && sender !== this.model.get('nick') && (new RegExp("\\b"+this.model.get('nick')+"\\b")).test(body)) {
playNotification(); converse.playNotification();
} }
if (sender !== this.model.get('nick')) { if (sender !== this.model.get('nick')) {
// We only emit an event if it's not our own message // We only emit an event if it's not our own message
...@@ -27292,7 +27498,7 @@ define("converse-dependencies", [ ...@@ -27292,7 +27498,7 @@ define("converse-dependencies", [
return true; // We already have this message stored. return true; // We already have this message stored.
} }
if (!this.isOnlyChatStateNotification($message) && from !== converse.bare_jid) { if (!this.isOnlyChatStateNotification($message) && from !== converse.bare_jid) {
playNotification(); converse.playNotification();
} }
chatbox.receiveMessage($message); chatbox.receiveMessage($message);
converse.roster.addResource(contact_jid, resource); converse.roster.addResource(contact_jid, resource);
...@@ -27723,7 +27929,8 @@ define("converse-dependencies", [ ...@@ -27723,7 +27929,8 @@ define("converse-dependencies", [
_.extend(item.toJSON(), { _.extend(item.toJSON(), {
'desc_status': STATUSES[chat_status||'offline'], 'desc_status': STATUSES[chat_status||'offline'],
'desc_chat': __('Click to chat with this contact'), 'desc_chat': __('Click to chat with this contact'),
'desc_remove': __('Click to remove this contact') 'desc_remove': __('Click to remove this contact'),
'allow_contact_removal': converse.allow_contact_removal
}) })
)); ));
} }
...@@ -27737,6 +27944,7 @@ define("converse-dependencies", [ ...@@ -27737,6 +27944,7 @@ define("converse-dependencies", [
removeContact: function (ev) { removeContact: function (ev) {
if (ev && ev.preventDefault) { ev.preventDefault(); } if (ev && ev.preventDefault) { ev.preventDefault(); }
if (!converse.allow_contact_removal) { return; }
var result = confirm(__("Are you sure you want to remove this contact?")); var result = confirm(__("Are you sure you want to remove this contact?"));
if (result === true) { if (result === true) {
var bare_jid = this.model.get('jid'); var bare_jid = this.model.get('jid');
...@@ -29437,20 +29645,32 @@ define("converse-dependencies", [ ...@@ -29437,20 +29645,32 @@ define("converse-dependencies", [
} }
}; };
this.startNewBOSHSession = function () {
$.ajax({
url: this.prebind_url,
type: 'GET',
success: function (response) {
this.session.save({rid: response.rid});
this.connection.attach(
response.jid,
response.sid,
response.rid,
this.onConnect
);
}.bind(this),
error: function (response) {
delete this.connection;
this.emit('noResumeableSession');
}.bind(this)
});
};
this.initConnection = function () { this.initConnection = function () {
var rid, sid, jid; var rid, sid, jid;
if (this.connection && this.connection.connected) { if (this.connection && this.connection.connected) {
this.setUpXMLLogging(); this.setUpXMLLogging();
this.onConnected(); this.onConnected();
} else { } else {
// XXX: it's not yet clear what the order of preference should
// be between RID and SID received via the initialize method or
// those received from sessionStorage.
//
// What do you we if we receive values from both avenues?
//
// Also, what do we do when the keepalive session values are
// expired? Do we try to fall back?
if (!this.bosh_service_url && ! this.websocket_url) { if (!this.bosh_service_url && ! this.websocket_url) {
throw("Error: you must supply a value for the bosh_service_url or websocket_url"); throw("Error: you must supply a value for the bosh_service_url or websocket_url");
} }
...@@ -29476,33 +29696,25 @@ define("converse-dependencies", [ ...@@ -29476,33 +29696,25 @@ define("converse-dependencies", [
rid = this.session.get('rid'); rid = this.session.get('rid');
sid = this.session.get('sid'); sid = this.session.get('sid');
jid = this.session.get('jid'); jid = this.session.get('jid');
if (rid && jid && sid) { if (this.prebind) {
// The RID needs to be increased with each request. if (!this.jid) {
this.session.save({rid: rid}); throw("When using 'keepalive' with 'prebind, you must supply the JID of the current user.");
}
if (rid && sid && jid && Strophe.getBareJidFromJid(jid) === Strophe.getBareJidFromJid(this.jid)) {
this.session.save({rid: rid}); // The RID needs to be increased with each request.
this.connection.attach(jid, sid, rid, this.onConnect); this.connection.attach(jid, sid, rid, this.onConnect);
} else if (this.prebind) { } else if (this.prebind_url) {
if (this.prebind_url) { this.startNewBOSHSession();
$.ajax({
url: this.prebind_url,
type: 'GET',
success: function (response) {
this.session.save({rid: rid});
this.connection.attach(
response.jid,
response.sid,
response.rid,
this.onConnect
);
}.bind(this),
error: function (response) {
delete this.connection;
this.emit('noResumeableSession');
}.bind(this)
});
} else { } else {
delete this.connection; delete this.connection;
this.emit('noResumeableSession'); this.emit('noResumeableSession');
} }
} else {
// Non-prebind case.
if (rid && sid && jid) {
this.session.save({rid: rid}); // The RID needs to be increased with each request.
this.connection.attach(jid, sid, rid, this.onConnect);
}
} }
} }
} }
...@@ -29582,6 +29794,14 @@ define("converse-dependencies", [ ...@@ -29582,6 +29794,14 @@ define("converse-dependencies", [
'initialize': function (settings, callback) { 'initialize': function (settings, callback) {
converse.initialize(settings, callback); converse.initialize(settings, callback);
}, },
'disconnect': function () {
converse.connection.disconnect();
},
'account': {
'logout': function () {
converse.logOut();
},
},
'settings': { 'settings': {
'get': function (key) { 'get': function (key) {
if (_.contains(Object.keys(converse.default_settings), key)) { if (_.contains(Object.keys(converse.default_settings), key)) {
...@@ -29887,7 +30107,6 @@ require.config({ ...@@ -29887,7 +30107,6 @@ require.config({
// define module dependencies for modules not using define // define module dependencies for modules not using define
shim: { shim: {
'underscore': { exports: '_' },
'crypto.aes': { deps: ['crypto.cipher-core'] }, 'crypto.aes': { deps: ['crypto.cipher-core'] },
'crypto.cipher-core': { deps: ['crypto.enc-base64', 'crypto.evpkdf'] }, 'crypto.cipher-core': { deps: ['crypto.enc-base64', 'crypto.evpkdf'] },
'crypto.enc-base64': { deps: ['crypto.core'] }, 'crypto.enc-base64': { deps: ['crypto.core'] },
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -483,7 +483,7 @@ var __t, __p = '', __e = _.escape; ...@@ -483,7 +483,7 @@ var __t, __p = '', __e = _.escape;
with (obj) { with (obj) {
__p += '<form id="converse-login" method="post">\n <label>' + __p += '<form id="converse-login" method="post">\n <label>' +
((__t = (label_username)) == null ? '' : __t) + ((__t = (label_username)) == null ? '' : __t) +
'</label>\n <input type="username" name="jid" placeholder="user@server">\n <label>' + '</label>\n <input type="email" name="jid" placeholder="user@server">\n <label>' +
((__t = (label_password)) == null ? '' : __t) + ((__t = (label_password)) == null ? '' : __t) +
'</label>\n <input type="password" name="password" placeholder="password">\n <input class="submit" type="submit" value="' + '</label>\n <input type="password" name="password" placeholder="password">\n <input class="submit" type="submit" value="' +
((__t = (label_login)) == null ? '' : __t) + ((__t = (label_login)) == null ? '' : __t) +
...@@ -829,7 +829,9 @@ __p += '<form class="add-chatroom" action="" method="post">\n <label>' + ...@@ -829,7 +829,9 @@ __p += '<form class="add-chatroom" action="" method="post">\n <label>' +
((__t = (label_nickname)) == null ? '' : __t) + ((__t = (label_nickname)) == null ? '' : __t) +
'</label>\n <input type="text" name="nick" class="new-chatroom-nick"\n placeholder="' + '</label>\n <input type="text" name="nick" class="new-chatroom-nick"\n placeholder="' +
((__t = (label_nickname)) == null ? '' : __t) + ((__t = (label_nickname)) == null ? '' : __t) +
'"/>\n <label>' + '"/>\n <label' +
((__t = (server_label_global_attr)) == null ? '' : __t) +
'>' +
((__t = (label_server)) == null ? '' : __t) + ((__t = (label_server)) == null ? '' : __t) +
'</label>\n <input type="' + '</label>\n <input type="' +
((__t = (server_input_type)) == null ? '' : __t) + ((__t = (server_input_type)) == null ? '' : __t) +
...@@ -863,7 +865,8 @@ return __p ...@@ -863,7 +865,8 @@ return __p
this["templates"]["roster_item"] = function(obj) { this["templates"]["roster_item"] = function(obj) {
obj || (obj = {}); obj || (obj = {});
var __t, __p = '', __e = _.escape; var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
function print() { __p += __j.call(arguments, '') }
with (obj) { with (obj) {
__p += '<a class="open-chat" title="Name: ' + __p += '<a class="open-chat" title="Name: ' +
((__t = (fullname)) == null ? '' : __t) + ((__t = (fullname)) == null ? '' : __t) +
...@@ -877,9 +880,13 @@ __p += '<a class="open-chat" title="Name: ' + ...@@ -877,9 +880,13 @@ __p += '<a class="open-chat" title="Name: ' +
((__t = (desc_status)) == null ? '' : __t) + ((__t = (desc_status)) == null ? '' : __t) +
'"></span>' + '"></span>' +
((__t = (fullname)) == null ? '' : __t) + ((__t = (fullname)) == null ? '' : __t) +
'</a>\n<a class="remove-xmpp-contact icon-remove" title="' + '</a>\n';
if (allow_contact_removal) { ;
__p += '\n<a class="remove-xmpp-contact icon-remove" title="' +
((__t = (desc_remove)) == null ? '' : __t) + ((__t = (desc_remove)) == null ? '' : __t) +
'" href="#"></a>\n'; '" href="#"></a>\n';
} ;
__p += '\n';
} }
return __p return __p
......
...@@ -9,4 +9,4 @@ ...@@ -9,4 +9,4 @@
* *
* Copyright (c) 2012-2014, JC Brand <jc@opkode.com> * Copyright (c) 2012-2014, JC Brand <jc@opkode.com>
* Licensed under the Mozilla Public License * Licensed under the Mozilla Public License
*/@font-face{font-family:Converse-js;src:url(../fonticons/fonts/icomoon.eot?-mnoxh0);src:url(../fonticons/fonts/icomoon.eot?#iefix-mnoxh0) format("embedded-opentype"),url(../fonticons/fonts/icomoon.woff?-mnoxh0) format("woff"),url(../fonticons/fonts/icomoon.ttf?-mnoxh0) format("truetype"),url(../fonticons/fonts/icomoon.svg?-mnoxh0#icomoon) format("svg");font-weight:400;font-style:normal}.icon-conversejs{font-family:Converse-js;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-conversejs:before{content:"\e600"}#conversejs{color:#6C4C44;font-size:14px;bottom:0;direction:ltr;height:35px;left:0;position:fixed;right:0;z-index:30;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#conversejs ::selection{background-color:#E3C9C1}#conversejs *,#conversejs :after,#conversejs :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@media screen and (max-width:480px){#conversejs{margin:5px 10px}}#conversejs a,#conversejs a:visited{text-decoration:none;color:#436F64;text-shadow:none}#conversejs ul li{height:auto}#conversejs a,#conversejs article,#conversejs aside,#conversejs audio,#conversejs blockquote,#conversejs canvas,#conversejs caption,#conversejs dd,#conversejs details,#conversejs div,#conversejs dl,#conversejs dt,#conversejs em,#conversejs embed,#conversejs fieldset,#conversejs figcaption,#conversejs figure,#conversejs footer,#conversejs form,#conversejs h1,#conversejs h2,#conversejs h3,#conversejs h4,#conversejs h5,#conversejs h6,#conversejs header,#conversejs hgroup,#conversejs img,#conversejs label,#conversejs legend,#conversejs li,#conversejs mark,#conversejs menu,#conversejs nav,#conversejs ol,#conversejs output,#conversejs p,#conversejs pre,#conversejs ruby,#conversejs section,#conversejs span,#conversejs strong,#conversejs summary,#conversejs table,#conversejs tbody,#conversejs td,#conversejs tfoot,#conversejs th,#conversejs thead,#conversejs time,#conversejs tr,#conversejs ul,#conversejs video{margin:0;padding:0;border:0;font:inherit;vertical-align:baseline}#conversejs button,#conversejs input[type=button],#conversejs input[type=password],#conversejs input[type=submit],#conversejs input[type=text],#conversejs textarea{font-size:14px;padding:.25em;min-height:0}#conversejs strong{font-weight:700}#conversejs ol,#conversejs ul{list-style:none}#conversejs li{height:10px}#conversejs dl,#conversejs ol,#conversejs ul{font:inherit;margin:0}#conversejs [data-icon]:before{content:attr(data-icon);font-family:Converse-js;font-variant:normal;font-weight:400;line-height:1;speak:none;text-transform:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#conversejs [class*=" icon-"],#conversejs [class^=icon-]{font-family:Converse-js;font-style:normal;font-variant:normal;font-weight:400;line-height:1;speak:none;text-transform:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#conversejs .icon-address-book:before{content:"\270f"}#conversejs .icon-angry:before{content:"\e03f"}#conversejs .icon-attachment:before{content:"\e032"}#conversejs .icon-away:before{content:"\25fb"}#conversejs .icon-blocked:before{content:"\2718"}#conversejs .icon-bold:before{content:"\e04d"}#conversejs .icon-bubbles-2:before{content:"\e016"}#conversejs .icon-bubbles-3:before{content:"\e017"}#conversejs .icon-bubbles:before{content:"\e015"}#conversejs .icon-camera-2:before{content:"\2616"}#conversejs .icon-camera:before{content:"\e003"}#conversejs .icon-cancel-circle:before{content:"\e058"}#conversejs .icon-checkbox-checked:before{content:"\2611"}#conversejs .icon-checkbox-partial:before{content:"\2b28"}#conversejs .icon-checkbox-unchecked:before{content:"\2b27"}#conversejs .icon-checkmark:before{content:"\2713"}#conversejs .icon-close:before{content:"\2715"}#conversejs .icon-closed:before{content:"\25ba"}#conversejs .icon-cog:before{content:"\e02f"}#conversejs .icon-cogs:before{content:"\e022"}#conversejs .icon-confused:before{content:"\2368"}#conversejs .icon-cool:before{content:"\e040"}#conversejs .icon-dnd:before{content:"\e004"}#conversejs .icon-envelop:before{content:"\2709"}#conversejs .icon-evil:before{content:"\261f"}#conversejs .icon-eye-blocked:before{content:"\e031"}#conversejs .icon-eye:before{content:"\e030"}#conversejs .icon-globe:before{content:"\e033"}#conversejs .icon-grin:before{content:"\e041"}#conversejs .icon-happy:before{content:"\263b"}#conversejs .icon-headphones:before{content:"\266c"}#conversejs .icon-heart:before{content:"\2764"}#conversejs .icon-hide-users:before{content:"\e01c"}#conversejs .icon-home:before{content:"\e000"}#conversejs .icon-image:before{content:"\2b14"}#conversejs .icon-info:before{content:"\2360"}#conversejs .icon-italic:before{content:"\e04f"}#conversejs .icon-key-2:before{content:"\e029"}#conversejs .icon-key:before{content:"\e028"}#conversejs .icon-lock-2:before{content:"\e027"}#conversejs .icon-lock:before{content:"\e026"}#conversejs .icon-logout:before{content:"\e601"}#conversejs .icon-minus:before{content:"\e05a"}#conversejs .icon-music:before{content:"\266b"}#conversejs .icon-new-tab:before{content:"\e053"}#conversejs .icon-newspaper:before{content:"\e001"}#conversejs .icon-notebook:before{content:"\2710"}#conversejs .icon-notification:before{content:"\e01f"}#conversejs .icon-online:before{content:"\25fc"}#conversejs .icon-opened:before{content:"\25bc"}#conversejs .icon-pencil:before{content:"\270e"}#conversejs .icon-phone-hang-up:before{content:"\260e"}#conversejs .icon-phone:before{content:"\260f"}#conversejs .icon-play:before{content:"\25d9"}#conversejs .icon-plus:before{content:"\271a"}#conversejs .icon-pushpin:before{content:"\e012"}#conversejs .icon-quotes-left:before{content:"\e01d"}#conversejs .icon-radio-checked:before{content:"\2b26"}#conversejs .icon-radio-unchecked:before{content:"\2b25"}#conversejs .icon-remove:before{content:"\e02d"}#conversejs .icon-room-info:before{content:"\e059"}#conversejs .icon-sad:before{content:"\2639"}#conversejs .icon-search:before{content:"\e021"}#conversejs .icon-shocked:before{content:"\2364"}#conversejs .icon-show-users:before{content:"\e01e"}#conversejs .icon-smiley:before{content:"\263a"}#conversejs .icon-spell-check:before{content:"\e045"}#conversejs .icon-spinner:before{content:"\231b"}#conversejs .icon-strikethrough:before{content:"\e050"}#conversejs .icon-thumbs-up:before{content:"\261d"}#conversejs .icon-tongue:before{content:"\e038"}#conversejs .icon-underline:before{content:"\e04e"}#conversejs .icon-unlocked:before{content:"\e025"}#conversejs .icon-user:before{content:"\e01a"}#conversejs .icon-users:before{content:"\e01b"}#conversejs .icon-volume-decrease:before{content:"\e04b"}#conversejs .icon-volume-high:before{content:"\e046"}#conversejs .icon-volume-increase:before{content:"\e04c"}#conversejs .icon-volume-low:before{content:"\e048"}#conversejs .icon-volume-medium:before{content:"\e047"}#conversejs .icon-volume-mute-2:before{content:"\e04a"}#conversejs .icon-volume-mute:before{content:"\e049"}#conversejs .icon-warning:before{content:"\26a0"}#conversejs .icon-wink:before{content:"\e03a"}#conversejs .icon-wondering:before{content:"\2369"}#conversejs .icon-wrench:before{content:"\e024"}#conversejs .icon-offline:before,#conversejs .icon-unavailable:before,#conversejs .icon-xa:before{content:"\e002"}#conversejs .icon-youtube:before{content:"\e055"}#conversejs .icon-zoom-in:before{content:"\e02b"}#conversejs .icon-zoom-out:before{content:"\e02a"}#conversejs .no-text-select{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#conversejs .emoticon{font-size:14px}#conversejs .left{float:left}#conversejs .right{float:right}#conversejs .hidden{display:none}#conversejs .locked{padding-right:22px}@-webkit-keyframes spin{from{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-ms-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}@-moz-keyframes spin{from{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-ms-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{from{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-ms-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}#conversejs .spinner:before{font-size:24px;font-family:Converse-js!important;content:"\231b"}#conversejs .spinner{-webkit-animation:spin 2s infinite,linear;-moz-animation:spin 2s infinite,linear;animation:spin 2s infinite,linear;display:block;text-align:center;margin:5px}#conversejs .centered{text-align:center;display:block;margin:5em auto}#conversejs .hor_centered{text-align:center;display:block;margin:0 auto}#conversejs #minimized-chats,#conversejs .toggle-controlbox{border-top-left-radius:4px;border-top-right-radius:4px;float:right;margin:0 7px;font-weight:700}#conversejs .toggle-controlbox{background-color:#436F64;color:#0a0a0a;height:100%;padding:10px 8px 0}#conversejs .toggle-controlbox span{color:#fff}#conversejs .button-group,#conversejs .input-button-group{display:table}#conversejs .button-group{width:100%}#conversejs .input-button-group button,#conversejs .input-button-group input{display:table-cell}#conversejs #minimized-chats{color:#fff;display:none;height:100%;padding:0;width:130px}#conversejs #minimized-chats #toggle-minimized-chats{border-top-left-radius:4px;border-top-right-radius:4px;background-color:ivory;position:relative;padding:10px 0 0;display:block;width:100%;height:100%;text-align:center}#conversejs #minimized-chats .chat-head-message-count,#conversejs #minimized-chats .unread-message-count{font-weight:700;background-color:#f6f6f6;background-image:-webkit-linear-gradient(#f6f6f6 5%,gray 100%);background-image:linear-gradient(#f6f6f6 5%,gray 100%);border:1px solid;text-shadow:1px 1px 0 #FAFAFA;color:#681F2C;border-radius:5px;padding:2px 4px;font-size:16px;text-align:center;position:absolute;right:116px;bottom:10px}#conversejs #minimized-chats .box-flyout{position:absolute;display:block;height:auto;bottom:35px;margin-left:0}#conversejs #minimized-chats .box-flyout .chat-head{font-size:100%;border-radius:4px;padding:3px 0 0 5px;margin:0 0 1px;box-shadow:1px 3px 5px 3px rgba(0,0,0,.4);height:24px;width:130px}#conversejs .chat-body{background-color:#fff;border-bottom-right-radius:4px;border-bottom-left-radius:4px;height:289px;height:-webkit-calc(100% - 44px);height:calc(100% - 44px);border-top:0}#conversejs .chat-body p{font-size:14px;color:#6C4C44;padding:5px;margin:0}#conversejs .tt-highlight{background-color:#00230F}#conversejs .tt-suggestion p{color:#fff;text-shadow:rgba(0,0,0,.51)0 -1px 0;cursor:pointer;font-size:11px}#conversejs .tt-suggestion p:hover{background-color:#00230F}#conversejs .tt-suggestion p:hover .tt-highlight{background:#27774A}#conversejs .tt-dropdown-menu{margin:0 1px;width:96px;max-height:250px;overflow-x:hidden;overflow-y:auto;text-overflow:ellipsis;background:#27774A;border-bottom-right-radius:4px;border-bottom-left-radius:4px}#conversejs .chat-blink{background-color:#176679;border-right:1px solid #176679;border-left:1px solid #176679}#conversejs .chat-content{position:relative;padding:8px;font-size:13px;color:#6C4C44;overflow-y:auto;border:0;background-color:#fff;line-height:1.3em;height:206px;height:calc(100% - 84px)}#conversejs .chat-error{color:#681F2C;font-weight:700}#conversejs .chat-error,#conversejs .chat-info,#conversejs .chat-message{padding:2px 0}#conversejs .chat-message-me,#conversejs .chat-message-room,#conversejs .chat-message-them{font-weight:700;white-space:nowrap;max-width:100px;text-overflow:ellipsis;overflow:hidden;display:inline-block;float:left;padding-right:3px}#conversejs .chat-message-content{word-wrap:break-word}#conversejs .chat-message-room,#conversejs .chat-message-them{color:#4B7003}#conversejs .chat-message-me{color:#436F64}#conversejs .chat-date,#conversejs .chat-event,#conversejs .chat-info{color:gray}#conversejs li.chat-info{padding-left:10px}#conversejs .chat-date{display:inline-block;padding-top:10px}#conversejs .not-implemented{margin-top:3em;margin-left:.3em;color:gray}#conversejs .mentioned{font-weight:700}#conversejs .delayed .chat-message-them{color:#FB5D50}#conversejs .delayed .chat-message-me{color:#7EABBB}#conversejs .error{color:red}#conversejs input.error{border:1px solid red}#conversejs #converse-register .form-errors{color:red;display:none}#conversejs #converse-register .provider-title{font-size:115%}#conversejs #converse-register .provider-score{width:178px;margin-bottom:8px}#conversejs #converse-register .form-help .url{font-weight:700;color:#436F64}#conversejs .reg-feedback{font-size:85%}#conversejs #converse-login .conn-feedback,#conversejs .reg-feedback{display:block;text-align:center;width:100%}#conversejs .chat-message-error{color:#76797C;font-size:90%;font-weight:400}#conversejs .chat-title,#conversejs a.restore-chat{padding:1px 0 1px 5px;color:#fff;font-weight:700;line-height:15px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-shadow:rgba(0,0,0,.51)0 -1px 0}#conversejs a.restore-chat:visited{color:#fff}#conversejs .chat-title a{color:#fff;width:100%;text-overflow:ellipsis;white-space:nowrap}#conversejs .chat-head-chatbox,#conversejs .chat-head-chatroom{height:44px;position:relative;padding:5px}#conversejs .chat-head-chatroom{background-color:#0F592F}#conversejs .chat-head-chatbox{background-color:#436F64}#conversejs .chatroom-topic,#conversejs .user-custom-message{color:#fff;font-size:80%;font-style:italic;height:1.3em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0;padding:1px 0 1px 5px}#conversejs .activated{display:block!important}#conversejs a.subscribe-to-user{padding-left:2em;font-weight:700}#conversejs dl.add-converse-contact{margin:0 .5em .5em}#conversejs .fancy-dropdown{border:1px solid #F1DCD6;height:25px;text-align:left}#conversejs .fancy-dropdown .choose-xmpp-status{width:155px}#conversejs .fancy-dropdown .choose-xmpp-status span{padding-right:5px;padding-left:5px;float:left}#conversejs .fancy-dropdown .choose-xmpp-status,#conversejs .fancy-dropdown .toggle-xmpp-contact-form{text-shadow:0 1px 0 #fff;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline}#conversejs .fancy-dropdown .toggle-xmpp-contact-form span{float:left}#conversejs #fancy-xmpp-status-select a.change-xmpp-status-message{float:right;clear:right;height:22px;width:12px;margin:0 5px 0 0;color:#436F64}#conversejs ul#found-users{padding:10px 0 5px 5px;border:0}#conversejs form.search-xmpp-contact{margin:0;padding:0 0 5px 5px}#conversejs form.search-xmpp-contact input{width:8em}#conversejs a.close-chatbox-button,#conversejs a.configure-chatroom-button,#conversejs a.toggle-chatbox-button{border-radius:6px;border:1px solid #888;color:#fff;cursor:pointer;display:inline-block;float:right;font-size:10px;margin:0 0 0 3px;padding:3px 3px 2px;text-decoration:none}#conversejs a.close-chatbox-button:active,#conversejs a.configure-chatroom-button:active,#conversejs a.toggle-chatbox-button:active{position:relative;top:1px}#conversejs .chatroom-form-container{height:100%;color:#6C4C44;overflow-y:auto;border-bottom-right-radius:4px;border-bottom-left-radius:4px}#conversejs .chatroom-form{padding:1em}#conversejs .chatroom-form .instructions{color:gray;font-size:95%}#conversejs .chatroom-form input{width:100%;padding:5px;text-align:center}#conversejs .chatroom-form legend{font-size:16px;font-weight:700;margin:10px 0 15px}#conversejs .chatroom-form label{display:block;clear:both}#conversejs .chatroom-form label label input,#conversejs .chatroom-form label label select{float:right}#conversejs .requesting-xmpp-contact .request-actions{margin-left:.5em;float:right}#conversejs #converse-roster{text-align:left;width:100%;position:relative;margin:.5em 0 0;height:194px;height:calc(100% - 68px);overflow:hidden}#conversejs #converse-roster .filter-type{display:table-cell;float:right;font-size:14px;height:25px;margin:0 0 .5em -1px;padding:0;width:84px}#conversejs #converse-roster .roster-filter{float:left;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAABNSURBVHjaXI7BDcAwCAMvyQjMyQ6dAbZiKfqoUK34g2zJh1dENIC7M8pMAPYdzAVY3d0ajNz9aypS/b5R6o+ZPdqoKgCq6h80KH3xDgBqNR97p8oAGQAAAABJRU5ErkJggg==) no-repeat right -20px center;border:1px solid #999;font-size:14px;height:25px;margin:0 0 .5em 7px;padding:0;padding:2px;width:103px}#conversejs #converse-roster .roster-filter.x{background-position:right 3px center}#conversejs #converse-roster .roster-filter.onX{cursor:pointer}#conversejs #converse-roster .roster-contacts{margin:0;max-height:195px;max-height:calc(100% - 26px);overflow-x:hidden;overflow-y:auto;padding-bottom:15px}#conversejs #converse-roster .group-toggle{color:#6C4C44;display:block;width:100%}#conversejs #converse-roster dt{display:none}#conversejs #converse-roster dd{line-height:16px;padding:4px 2px 0 4px;height:24px}#conversejs #converse-roster dd a,#conversejs #converse-roster dd span{text-shadow:0 1px 0 #FAFAFA;display:inline-block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-left:3px}#conversejs #converse-roster dd span{padding:0 5px 0 0}#conversejs #converse-roster dd a.decline-xmpp-request{margin-left:5px}#conversejs #converse-roster dd a.remove-xmpp-contact{float:right;width:22px;margin:0;display:none;color:#6C4C44}#conversejs #converse-roster dd:hover a.remove-xmpp-contact{display:inline-block}#conversejs #converse-roster dd.odd{background-color:#DCEAC5}#conversejs #converse-roster dd.current-xmpp-contact span{font-size:16px;float:left;color:#436F64}#conversejs #converse-roster dd a.open-chat,#conversejs #converse-roster span.pending-contact-name{width:80%}#conversejs #converse-roster span.req-contact-name{width:69%;padding:0}#conversejs #available-chatrooms{text-align:left}#conversejs #available-chatrooms dt,#conversejs #converse-roster dt{font-weight:400;color:#6C4C44;border:none;padding:.5em;text-shadow:0 1px 0 #FAFAFA}#conversejs .room-info{font-size:11px;font-style:normal;font-weight:400}#conversejs li.room-info{display:block;margin-left:5px}#conversejs div.room-info{clear:left}#conversejs p.room-info{margin:0;padding:0;display:block;white-space:normal}#conversejs a.room-info{width:15px;display:none;clear:right}#conversejs a.open-room{float:left;white-space:nowrap;text-overflow:ellipsis;overflow-x:hidden}#conversejs dd.available-chatroom{overflow-x:hidden;text-overflow:ellipsis;padding:.25em .5em;white-space:nowrap}#conversejs dd.available-chatroom a.open-room{width:150px}#conversejs dd.available-chatroom:hover a.room-info{display:inline-block;font-size:14px}#conversejs #converse-roster dd,#conversejs dd.available-chatroom{font-weight:700;border:none;display:block;color:#6C4C44;text-shadow:0 1px 0 #FAFAFA;clear:both;overflow-y:hidden}#conversejs #converse-roster dd:hover,#conversejs .roster-group:hover,#conversejs dd.available-chatroom:hover{background-color:#E3C9C1}#conversejs .chatbox,#conversejs .chatroom{height:35px;float:right;margin:0 7px;display:block}@media screen and (max-width:480px){#conversejs .chatbox,#conversejs .chatroom{margin:0}}#conversejs .chatbox{width:200px}@media screen and (max-width:480px){#conversejs .chatbox{width:100%}}#conversejs .chatbox .box-flyout{z-index:1;width:200px}@media screen and (max-width:480px){#conversejs .chatbox .box-flyout{width:100%}}#conversejs .chatbox .dropdown a{width:148px;display:inline-block;line-height:25px}#conversejs .chatbox .dropdown li{list-style:none;padding-left:0}#conversejs .chatbox .dropdown dd ul{padding:0;list-style:none;position:absolute;left:0;top:0;border:1px solid #F1DCD6;width:100%;z-index:21;background-color:#F1E2DD}#conversejs .chatbox .dropdown dd ul li:hover{background-color:#E3C9C1}#conversejs .chatbox .dropdown dd.search-xmpp ul{box-shadow:1px 4px 10px 1px rgba(0,0,0,.4)}#conversejs .chatbox .dropdown dd.search-xmpp ul li:hover{background-color:#F1E2DD}#conversejs .chatbox .dropdown dt a span{cursor:pointer;display:block;padding:4px 7px 0 5px}#conversejs .chatroom,#conversejs .chatroom .box-flyout{width:300px}@media screen and (max-width:480px){#conversejs .chatroom,#conversejs .chatroom .box-flyout{width:100%}}#conversejs .chatroom label{margin-left:2px;font-size:12px}#conversejs .chatroom .participant-list{list-style:none}#conversejs .chatroom .participant-list li{cursor:default;display:block;font-size:12px;font-weight:700;overflow:hidden;padding:2px 5px;text-overflow:ellipsis;white-space:nowrap}#conversejs .chatroom .participant-list li.moderator{color:#8f2831}#conversejs .chatroom .chat-textarea{border-bottom-right-radius:0}#conversejs .chatroom .chat-area{float:left;height:100%;width:200px}#conversejs .chatroom .invited-contact{margin:-1px 0 0 -1px;width:100px;border:1px solid #999}#conversejs .chatroom .invited-contact.tt-input{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkBCjE0uzKkOgAAAidJREFUKM+N0k+IEnEUB/D3cyscdagkWpHV0WGWREXm0AgOGkSJ07kh2UXYU5cOewm6Bp0KXG/tpSCv6hyEFQIhMEaE3yERYfwTOoqKGLQxDAbqYadLgu7J7/XxeY/3ez8EACDLsgljfMfj8ZxUKhXXYDAAnueBoqgyAMipVOovXAuSZdnUaDQeDofDs16vFyUIAjRNUwmCoG02G1AUdZ5IJN7GYrHfm3AvEAjcnUwmX0ajUdRqtV74fL6sruufKYoa6bp+fzabPUMI7ZfL5eImNHk8npNerxc1m80XHMe98fv9H3K5XDkSibxjWfb1arWaYoyPMMbCFqxUKi6CIODw8LDmdDq7oigaAACiKK5omv7KcdylpmlIkiTHFlRVFTRNUxVFqa/ROqIoGoqi5A3DgFartfU4Jp7ngSAI2uVyPZIk6dZmUZKk2w6H4xghBPF4HK7vWLbZbDCdTp+rqvpUkiS0RvV6/bTf7x8wDHMViURqm/AGAMgURZ232+1X1Wr102KxuEwmk3lZlo/7/f7BcrkkSZKs2e12tHXH/x/gHsY4jTE+0jQNGYYBCCFgGOaKJMkfjUaDZximGQ6HXzSbzZ+ZTMbY6oIxFgqFgqPT6YAgCMBxXM1ut6N0Op0fj8chi8XyjWXZ98Fg8DuCHZLNZh+USqWP8/n8idvt/hUKhV7u7QK9Xu8fmqanAJBQVXUfAGY7TQQAKBaLN8fjsdDtdh/run72Dzhf7XLe2UevAAAAAElFTkSuQmCC) no-repeat right 3px center}#conversejs .chatroom .participants{float:right;background-color:#fff;overflow-y:auto;overflow-x:hidden;border-left:1px solid #AAA;border-bottom-right-radius:4px;width:100px;height:100%}#conversejs .chatroom .participants label{font-size:12px;font-style:italic;margin:5px;display:block}#conversejs .chatroom-form,#conversejs .controlbox-pane{background-color:#fff;border-bottom-left-radius:4px;border-bottom-right-radius:4px;border:0;font-size:14px;overflow-y:auto;position:absolute;text-align:center;width:100%;height:289px;height:-webkit-calc(100% - 44px);height:calc(100% - 44px)}#conversejs .controlbox-pane{padding:5px 0;overflow-y:hidden}#conversejs .controlbox-pane dd{margin-left:0;margin-bottom:0}#conversejs .controlbox-pane dd.odd{background-color:#DCEAC5}#conversejs #converse-register .title{font-weight:700}#conversejs #converse-register .info{font-style:italic;color:green;font-size:85%;margin:5px 0}#conversejs #converse-register .instructions,#conversejs .form-help{color:gray;font-size:85%}#conversejs #converse-register .instructions:hover,#conversejs .form-help:hover{color:#6C4C44}#conversejs .form-help{padding-top:5px}#conversejs #converse-login,#conversejs #converse-register{background:#fff;padding:1em}#conversejs #converse-login input,#conversejs #converse-register input{width:100%;height:30px;margin:5px 0 10px;padding-left:.5em}#conversejs #converse-register .input-group{display:table;margin:auto;width:178px}#conversejs #converse-register .input-group input[name=username],#conversejs #converse-register .input-group span{display:table-cell}#conversejs #converse-register .input-group input[name=username]{width:100%}#conversejs .cancel-submit,#conversejs .save-submit{width:45%;margin:5px 3px}#conversejs .cancel,#conversejs .cancel-submit{color:#681F2C}#conversejs .save-submit{color:#436F64}#conversejs #converse-login label,#conversejs #converse-register label,#conversejs .chatroom-form label,#conversejs .controlbox-pane label{font-size:14px;font-weight:700;height:auto;margin:4px}#conversejs #converse-login .login-submit,#conversejs #converse-login .submit,#conversejs #converse-register .login-submit,#conversejs #converse-register .submit{height:30px;padding:0;font-size:14px}#conversejs #converse-login .submit{margin:1em 0}#conversejs form.add-chatroom{background:0 0;padding:.5em}#conversejs form.add-chatroom input[type=button],#conversejs form.add-chatroom input[type=submit],#conversejs form.add-chatroom input[type=text]{margin:0;width:100%;padding:.25em}#conversejs form.add-chatroom input[type=button],#conversejs form.add-chatroom input[type=submit],#conversejs form.add-chatroom span.spinner{margin-top:.5em;display:table-cell;width:auto}#conversejs form.add-chatroom input[type=submit]{color:#436F64}#conversejs select#select-xmpp-status{float:right;margin-right:.5em}#conversejs .chat-head{border-top-left-radius:4px;border-top-right-radius:4px;color:#fff;font-size:100%;margin:0;padding:6px}#conversejs .chat-head.controlbox-head{background-color:#436F64;border-top-left-radius:4px;border-top-right-radius:4px;color:#fff;height:44px;margin:0;padding:6px 6px 6px 0}#conversejs .chat-head .avatar{float:left}#conversejs .chat-head #controlbox-tabs{text-align:center;display:inline;overflow:hidden;font-size:12px;list-style-type:none}#conversejs .chat-head #controlbox-tabs a.current,#conversejs .chat-head #controlbox-tabs a.current:hover{box-shadow:none;border-bottom:0;height:44px;cursor:default;color:#6C4C44}#conversejs .chat-head #controlbox-tabs li{float:left;list-style:none;padding-left:0;text-shadow:#fff 0 1px 0;width:38%}#conversejs .chat-head #controlbox-tabs li a{background-color:#fff;border-bottom:1px solid #CCC;border-top-left-radius:4px;border-top-right-radius:4px;box-shadow:inset 2px -2px 20px rgba(0,0,0,.3);color:#888;display:block;font-size:12px;height:43px;line-height:43px;margin:0;text-align:center;text-decoration:none}#conversejs .chat-head #controlbox-tabs li a:hover{color:#6C4C44}#conversejs div#chatrooms{overflow-y:auto}#conversejs form.sendXMPPMessage{-moz-background-clip:padding;-moz-border-radius:4px;-webkit-background-clip:padding-box;-webkit-border-radius:4px;background:#fff;border-radius:4px;border-top-left-radius:0;border-top-right-radius:0;border:0;margin:0;padding:0;position:relative;height:82px;width:200px}@media screen and (max-width:480px){#conversejs form.sendXMPPMessage{width:100%}}#conversejs form.sendXMPPMessage .chat-textarea{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border:0;height:62px;padding:.5em;width:100%;resize:none}#conversejs .chat-toolbar{font-size:14px;margin:0;padding:0 4px;height:20px;display:block}#conversejs .chat-toolbar a{color:#436F64}#conversejs .chat-toolbar .unencrypted,#conversejs .chat-toolbar .unencrypted a{color:#8f2831}#conversejs .chat-toolbar .unverified,#conversejs .chat-toolbar .unverified a{color:#cf5300}#conversejs .chat-toolbar .private,#conversejs .chat-toolbar .private a{color:#4b7003}#conversejs .chat-toolbar .toggle-clear,#conversejs .chat-toolbar .toggle-otr,#conversejs .chat-toolbar .toggle-participants{float:right}#conversejs .chat-toolbar li{display:inline-block;list-style:none;padding:0 3px;cursor:pointer;margin-top:1px}#conversejs .chat-toolbar li:hover{cursor:pointer}#conversejs .chat-toolbar ul{background:#fff;bottom:100%;box-shadow:0 -1px 2px 0 rgba(0,0,0,.4);display:none;font-size:12px;margin:0 0 1px;position:absolute;right:0}#conversejs .chat-toolbar ul li{cursor:pointer;list-style:none;position:relative}#conversejs .chat-toolbar ul li a:hover{color:#8f2831}#conversejs .chat-toolbar .toggle-smiley{padding-left:5px}#conversejs .chat-toolbar .toggle-smiley ul li{font-size:14px;padding:5px;z-index:98}#conversejs .chat-toolbar .toggle-smiley ul li:hover{background-color:#E3C9C1}#conversejs .chat-toolbar .toggle-otr ul li{background-color:#fff;display:block;z-index:99}#conversejs .chat-toolbar .toggle-otr ul li a{-moz-transition:background-color .2s ease-in-out;-webkit-transition:background-color .2s ease-in-out;transition:background-color .2s ease-in-out;display:block;padding:1px;text-decoration:none}#conversejs .chat-toolbar-text{font-size:12px;padding-right:3px}#conversejs #set-custom-xmpp-status{float:left;padding:0}#conversejs #set-custom-xmpp-status input{height:26px;width:-webkit-calc(100% - 40px);width:calc(100% - 40px);padding:0 0 0 .5em}#conversejs #set-custom-xmpp-status button{height:26px;width:40px;padding:1px}#conversejs .chat-textarea-chatbox-selected{border:1px solid #578308;margin:0}#conversejs .chat-textarea-chatroom-selected{border:2px solid #436F64;margin:0}#conversejs #controlbox{display:none}#conversejs #controlbox div.xmpp-status{display:inline}#conversejs .chatbox .dropdown{background-color:#F1E2DD}#conversejs .chatbox .dropdown dd{position:relative}#conversejs .chatbox .dropdown dd,#conversejs .dropdown dt,#conversejs .dropdown ul{margin:0;padding:0}#conversejs .add-xmpp-contact{background:0 0;padding:5px}#conversejs .add-xmpp-contact input{margin:0 0 1rem;width:100%}#conversejs .add-xmpp-contact button{width:100%}#conversejs .xmpp-status-menu{text-align:left;box-shadow:1px 4px 10px 1px rgba(0,0,0,.4)}#conversejs .xmpp-status-menu li{padding:2px}#conversejs .xmpp-status-menu li a{width:100%;padding:0 8px}#conversejs .xmpp-status-menu li a.logout,#conversejs .xmpp-status-menu li a.logout span{color:#681F2C}#conversejs .set-xmpp-status{background:0 0;padding:.5em}#conversejs .set-xmpp-status .dropdown dd ul{z-index:22}#conversejs .box-flyout,#conversejs .minimized-chats-flyout{border-radius:4px;bottom:6px;box-shadow:1px 3px 5px 3px rgba(0,0,0,.4);display:block;height:400px;position:absolute}@media screen and (max-width:480px){#conversejs .box-flyout,#conversejs .minimized-chats-flyout{height:400px}}#conversejs .minimized-chats-flyout{border-radius:4px;bottom:35px;box-shadow:1px 3px 5px 3px rgba(0,0,0,.4);display:block;position:absolute;height:auto;width:130px}#conversejs .minimized-chats-flyout .chat-head,#conversejs .minimized-chats-flyout .chat-head-chatroom{border-radius:4px;width:130px;height:35px;margin-bottom:1px}#conversejs .minimized-chats-flyout.minimized{height:auto}#conversejs .dragresize{position:absolute;width:200px;height:5px;background:0 0;border:0;top:0;margin-left:0;cursor:n-resize;z-index:20} */@font-face{font-family:Converse-js;src:url(../fonticons/fonts/icomoon.eot?-mnoxh0);src:url(../fonticons/fonts/icomoon.eot?#iefix-mnoxh0) format("embedded-opentype"),url(../fonticons/fonts/icomoon.woff?-mnoxh0) format("woff"),url(../fonticons/fonts/icomoon.ttf?-mnoxh0) format("truetype"),url(../fonticons/fonts/icomoon.svg?-mnoxh0#icomoon) format("svg");font-weight:400;font-style:normal}.icon-conversejs{font-family:Converse-js;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-conversejs:before{content:"\e600"}#conversejs{color:#6C4C44;font-size:14px;bottom:0;direction:ltr;height:35px;left:0;position:fixed;right:0;z-index:30;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#conversejs ::selection{background-color:#E3C9C1}#conversejs *,#conversejs :after,#conversejs :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@media screen and (max-width:480px){#conversejs{margin:5px 10px}}#conversejs a,#conversejs a:visited{text-decoration:none;color:#436F64;text-shadow:none}#conversejs ul li{height:auto}#conversejs a,#conversejs article,#conversejs aside,#conversejs audio,#conversejs blockquote,#conversejs canvas,#conversejs caption,#conversejs dd,#conversejs details,#conversejs div,#conversejs dl,#conversejs dt,#conversejs em,#conversejs embed,#conversejs fieldset,#conversejs figcaption,#conversejs figure,#conversejs footer,#conversejs form,#conversejs h1,#conversejs h2,#conversejs h3,#conversejs h4,#conversejs h5,#conversejs h6,#conversejs header,#conversejs hgroup,#conversejs img,#conversejs label,#conversejs legend,#conversejs li,#conversejs mark,#conversejs menu,#conversejs nav,#conversejs ol,#conversejs output,#conversejs p,#conversejs pre,#conversejs ruby,#conversejs section,#conversejs span,#conversejs strong,#conversejs summary,#conversejs table,#conversejs tbody,#conversejs td,#conversejs tfoot,#conversejs th,#conversejs thead,#conversejs time,#conversejs tr,#conversejs ul,#conversejs video{margin:0;padding:0;border:0;font:inherit;vertical-align:baseline}#conversejs button,#conversejs input[type=button],#conversejs input[type=password],#conversejs input[type=submit],#conversejs input[type=text],#conversejs textarea{font-size:14px;padding:.25em;min-height:0}#conversejs input[type=text]{height:26px}#conversejs strong{font-weight:700}#conversejs ol,#conversejs ul{list-style:none}#conversejs li{height:10px}#conversejs dl,#conversejs ol,#conversejs ul{font:inherit;margin:0}#conversejs [data-icon]:before{content:attr(data-icon);font-family:Converse-js;font-variant:normal;font-weight:400;line-height:1;speak:none;text-transform:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#conversejs [class*=" icon-"],#conversejs [class^=icon-]{background-position:14px 14px;background-image:none;font-family:Converse-js;font-style:normal;font-variant:normal;font-weight:400;width:auto;height:auto;line-height:1;speak:none;text-transform:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#conversejs .icon-address-book:before{content:"\270f"}#conversejs .icon-angry:before{content:"\e03f"}#conversejs .icon-attachment:before{content:"\e032"}#conversejs .icon-away:before{content:"\25fb"}#conversejs .icon-blocked:before{content:"\2718"}#conversejs .icon-bold:before{content:"\e04d"}#conversejs .icon-bubbles-2:before{content:"\e016"}#conversejs .icon-bubbles-3:before{content:"\e017"}#conversejs .icon-bubbles:before{content:"\e015"}#conversejs .icon-camera-2:before{content:"\2616"}#conversejs .icon-camera:before{content:"\e003"}#conversejs .icon-cancel-circle:before{content:"\e058"}#conversejs .icon-checkbox-checked:before{content:"\2611"}#conversejs .icon-checkbox-partial:before{content:"\2b28"}#conversejs .icon-checkbox-unchecked:before{content:"\2b27"}#conversejs .icon-checkmark:before{content:"\2713"}#conversejs .icon-close:before{content:"\2715"}#conversejs .icon-closed:before{content:"\25ba"}#conversejs .icon-cog:before{content:"\e02f"}#conversejs .icon-cogs:before{content:"\e022"}#conversejs .icon-confused:before{content:"\2368"}#conversejs .icon-cool:before{content:"\e040"}#conversejs .icon-dnd:before{content:"\e004"}#conversejs .icon-envelop:before{content:"\2709"}#conversejs .icon-evil:before{content:"\261f"}#conversejs .icon-eye-blocked:before{content:"\e031"}#conversejs .icon-eye:before{content:"\e030"}#conversejs .icon-globe:before{content:"\e033"}#conversejs .icon-grin:before{content:"\e041"}#conversejs .icon-happy:before{content:"\263b"}#conversejs .icon-headphones:before{content:"\266c"}#conversejs .icon-heart:before{content:"\2764"}#conversejs .icon-hide-users:before{content:"\e01c"}#conversejs .icon-home:before{content:"\e000"}#conversejs .icon-image:before{content:"\2b14"}#conversejs .icon-info:before{content:"\2360"}#conversejs .icon-italic:before{content:"\e04f"}#conversejs .icon-key-2:before{content:"\e029"}#conversejs .icon-key:before{content:"\e028"}#conversejs .icon-lock-2:before{content:"\e027"}#conversejs .icon-lock:before{content:"\e026"}#conversejs .icon-logout:before{content:"\e601"}#conversejs .icon-minus:before{content:"\e05a"}#conversejs .icon-music:before{content:"\266b"}#conversejs .icon-new-tab:before{content:"\e053"}#conversejs .icon-newspaper:before{content:"\e001"}#conversejs .icon-notebook:before{content:"\2710"}#conversejs .icon-notification:before{content:"\e01f"}#conversejs .icon-online:before{content:"\25fc"}#conversejs .icon-opened:before{content:"\25bc"}#conversejs .icon-pencil:before{content:"\270e"}#conversejs .icon-phone-hang-up:before{content:"\260e"}#conversejs .icon-phone:before{content:"\260f"}#conversejs .icon-play:before{content:"\25d9"}#conversejs .icon-plus:before{content:"\271a"}#conversejs .icon-pushpin:before{content:"\e012"}#conversejs .icon-quotes-left:before{content:"\e01d"}#conversejs .icon-radio-checked:before{content:"\2b26"}#conversejs .icon-radio-unchecked:before{content:"\2b25"}#conversejs .icon-remove:before{content:"\e02d"}#conversejs .icon-room-info:before{content:"\e059"}#conversejs .icon-sad:before{content:"\2639"}#conversejs .icon-search:before{content:"\e021"}#conversejs .icon-shocked:before{content:"\2364"}#conversejs .icon-show-users:before{content:"\e01e"}#conversejs .icon-smiley:before{content:"\263a"}#conversejs .icon-spell-check:before{content:"\e045"}#conversejs .icon-spinner:before{content:"\231b"}#conversejs .icon-strikethrough:before{content:"\e050"}#conversejs .icon-thumbs-up:before{content:"\261d"}#conversejs .icon-tongue:before{content:"\e038"}#conversejs .icon-underline:before{content:"\e04e"}#conversejs .icon-unlocked:before{content:"\e025"}#conversejs .icon-user:before{content:"\e01a"}#conversejs .icon-users:before{content:"\e01b"}#conversejs .icon-volume-decrease:before{content:"\e04b"}#conversejs .icon-volume-high:before{content:"\e046"}#conversejs .icon-volume-increase:before{content:"\e04c"}#conversejs .icon-volume-low:before{content:"\e048"}#conversejs .icon-volume-medium:before{content:"\e047"}#conversejs .icon-volume-mute-2:before{content:"\e04a"}#conversejs .icon-volume-mute:before{content:"\e049"}#conversejs .icon-warning:before{content:"\26a0"}#conversejs .icon-wink:before{content:"\e03a"}#conversejs .icon-wondering:before{content:"\2369"}#conversejs .icon-wrench:before{content:"\e024"}#conversejs .icon-offline:before,#conversejs .icon-unavailable:before,#conversejs .icon-xa:before{content:"\e002"}#conversejs .icon-youtube:before{content:"\e055"}#conversejs .icon-zoom-in:before{content:"\e02b"}#conversejs .icon-zoom-out:before{content:"\e02a"}#conversejs .no-text-select{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#conversejs .emoticon{font-size:14px}#conversejs .left{float:left}#conversejs .right{float:right}#conversejs .hidden{display:none}#conversejs .locked{padding-right:22px}@-webkit-keyframes spin{from{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(359deg)}}@-moz-keyframes spin{from{-moz-transform:rotate(0deg)}to{-moz-transform:rotate(359deg)}}@keyframes spin{from{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-ms-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}#conversejs .spinner:before{font-size:24px;font-family:Converse-js!important;content:"\231b"}#conversejs .spinner{-webkit-animation:spin 2s infinite,linear;-moz-animation:spin 2s infinite,linear;animation:spin 2s infinite,linear;display:block;text-align:center;margin:5px}#conversejs .centered{text-align:center;display:block;margin:5em auto}#conversejs .hor_centered{text-align:center;display:block;margin:0 auto}#conversejs #minimized-chats,#conversejs .toggle-controlbox{border-top-left-radius:4px;border-top-right-radius:4px;float:right;margin:0 7px;font-weight:700}#conversejs .toggle-controlbox{background-color:#436F64;color:#0a0a0a;height:100%;padding:10px 8px 0}#conversejs .toggle-controlbox span{color:#fff}#conversejs .button-group,#conversejs .input-button-group{display:table}#conversejs .button-group{width:100%}#conversejs .input-button-group button,#conversejs .input-button-group input{display:table-cell}#conversejs #minimized-chats{color:#fff;display:none;height:100%;padding:0;width:130px}#conversejs #minimized-chats #toggle-minimized-chats{border-top-left-radius:4px;border-top-right-radius:4px;background-color:ivory;position:relative;padding:10px 0 0;display:block;width:100%;height:100%;text-align:center}#conversejs #minimized-chats .chat-head-message-count,#conversejs #minimized-chats .unread-message-count{font-weight:700;background-color:#f6f6f6;background-image:-webkit-linear-gradient(#f6f6f6 5%,gray 100%);background-image:linear-gradient(#f6f6f6 5%,gray 100%);border:1px solid;text-shadow:1px 1px 0 #FAFAFA;color:#681F2C;border-radius:5px;padding:2px 4px;font-size:16px;text-align:center;position:absolute;right:116px;bottom:10px}#conversejs #minimized-chats .box-flyout{position:absolute;display:block;height:auto;bottom:35px;margin-left:0}#conversejs #minimized-chats .box-flyout .chat-head{font-size:100%;border-radius:4px;padding:3px 0 0 5px;margin:0 0 1px;box-shadow:1px 3px 5px 3px rgba(0,0,0,.4);height:24px;width:130px}#conversejs .chat-body{background-color:#fff;border-bottom-right-radius:4px;border-bottom-left-radius:4px;height:289px;height:-webkit-calc(100% - 44px);height:calc(100% - 44px);border-top:0}#conversejs .chat-body p{font-size:14px;color:#6C4C44;padding:5px;margin:0}#conversejs .tt-highlight{background-color:#00230F}#conversejs .tt-suggestion p{color:#fff;text-shadow:rgba(0,0,0,.51)0 -1px 0;cursor:pointer;font-size:11px}#conversejs .tt-suggestion p:hover{background-color:#00230F}#conversejs .tt-suggestion p:hover .tt-highlight{background:#27774A}#conversejs .tt-dropdown-menu{margin:0 1px;width:96px;max-height:250px;overflow-x:hidden;overflow-y:auto;text-overflow:ellipsis;background:#27774A;border-bottom-right-radius:4px;border-bottom-left-radius:4px}#conversejs .chat-blink{background-color:#176679;border-right:1px solid #176679;border-left:1px solid #176679}#conversejs .chat-content{position:relative;padding:8px;font-size:13px;color:#6C4C44;overflow-y:auto;border:0;background-color:#fff;line-height:1.3em;height:206px;height:calc(100% - 84px)}#conversejs .chat-error{color:#681F2C;font-weight:700}#conversejs .chat-error,#conversejs .chat-info,#conversejs .chat-message{padding:2px 0}#conversejs .chat-message-me,#conversejs .chat-message-room,#conversejs .chat-message-them{font-weight:700;white-space:nowrap;max-width:100px;text-overflow:ellipsis;overflow:hidden;display:inline-block;float:left;padding-right:3px}#conversejs .chat-message-content{word-wrap:break-word}#conversejs .chat-message-room,#conversejs .chat-message-them{color:#4B7003}#conversejs .chat-message-me{color:#436F64}#conversejs .chat-date,#conversejs .chat-event,#conversejs .chat-info{color:gray}#conversejs li.chat-info{padding-left:10px}#conversejs .chat-date{display:inline-block;padding-top:10px}#conversejs .not-implemented{margin-top:3em;margin-left:.3em;color:gray}#conversejs .mentioned{font-weight:700}#conversejs .delayed .chat-message-them{color:#FB5D50}#conversejs .delayed .chat-message-me{color:#7EABBB}#conversejs .error{color:red}#conversejs input.error{border:1px solid red}#conversejs #converse-register .form-errors{color:red;display:none}#conversejs #converse-register .provider-title{font-size:115%}#conversejs #converse-register .provider-score{width:178px;margin-bottom:8px}#conversejs #converse-register .form-help .url{font-weight:700;color:#436F64}#conversejs .reg-feedback{font-size:85%}#conversejs #converse-login .conn-feedback,#conversejs .reg-feedback{display:block;text-align:center;width:100%}#conversejs .chat-message-error{color:#76797C;font-size:90%;font-weight:400}#conversejs .chat-title,#conversejs a.restore-chat{padding:1px 0 1px 5px;color:#fff;font-weight:700;line-height:15px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-shadow:rgba(0,0,0,.51)0 -1px 0}#conversejs a.restore-chat:visited{color:#fff}#conversejs .chat-title a{color:#fff;width:100%;text-overflow:ellipsis;white-space:nowrap}#conversejs .chat-head-chatbox,#conversejs .chat-head-chatroom{height:44px;position:relative;padding:5px}#conversejs .chat-head-chatroom{background-color:#0F592F}#conversejs .chat-head-chatbox{background-color:#436F64}#conversejs .chatroom-topic,#conversejs .user-custom-message{color:#fff;font-size:80%;font-style:italic;height:1.3em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0;padding:1px 0 1px 5px}#conversejs .activated{display:block!important}#conversejs a.subscribe-to-user{padding-left:2em;font-weight:700}#conversejs dl.add-converse-contact{margin:0 .5em .5em}#conversejs .fancy-dropdown{border:1px solid #F1DCD6;height:25px;text-align:left}#conversejs .fancy-dropdown .choose-xmpp-status{width:155px}#conversejs .fancy-dropdown .choose-xmpp-status span{padding-right:5px;padding-left:5px;float:left}#conversejs .fancy-dropdown .choose-xmpp-status,#conversejs .fancy-dropdown .toggle-xmpp-contact-form{text-shadow:0 1px 0 #fff;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline}#conversejs .fancy-dropdown .toggle-xmpp-contact-form span{float:left}#conversejs #fancy-xmpp-status-select a.change-xmpp-status-message{float:right;clear:right;height:22px;width:12px;margin:0 5px 0 0;color:#436F64}#conversejs ul#found-users{padding:10px 0 5px 5px;border:0}#conversejs form.search-xmpp-contact{margin:0;padding:0 0 5px 5px}#conversejs form.search-xmpp-contact input{width:8em}#conversejs a.close-chatbox-button,#conversejs a.configure-chatroom-button,#conversejs a.toggle-chatbox-button{border-radius:6px;border:1px solid #888;color:#fff;cursor:pointer;display:inline-block;float:right;font-size:10px;margin:0 0 0 3px;padding:3px 3px 2px;text-decoration:none}#conversejs a.close-chatbox-button:active,#conversejs a.configure-chatroom-button:active,#conversejs a.toggle-chatbox-button:active{position:relative;top:1px}#conversejs .chatroom-form-container{height:100%;color:#6C4C44;overflow-y:auto;border-bottom-right-radius:4px;border-bottom-left-radius:4px}#conversejs .chatroom-form{padding:1em}#conversejs .chatroom-form .instructions{color:gray;font-size:95%}#conversejs .chatroom-form input{width:100%;padding:5px;text-align:center}#conversejs .chatroom-form legend{font-size:16px;font-weight:700;margin:10px 0 15px}#conversejs .chatroom-form label{display:block;clear:both}#conversejs .chatroom-form label label input,#conversejs .chatroom-form label label select{float:right}#conversejs .requesting-xmpp-contact .request-actions{margin-left:.5em;float:right}#conversejs #converse-roster{text-align:left;width:100%;position:relative;margin:.5em 0 0;height:194px;height:calc(100% - 68px);overflow:hidden}#conversejs #converse-roster .filter-type{display:table-cell;float:right;font-size:14px;height:25px;margin:0 0 .5em -1px;padding:0;width:84px}#conversejs #converse-roster .roster-filter{float:left;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAABNSURBVHjaXI7BDcAwCAMvyQjMyQ6dAbZiKfqoUK34g2zJh1dENIC7M8pMAPYdzAVY3d0ajNz9aypS/b5R6o+ZPdqoKgCq6h80KH3xDgBqNR97p8oAGQAAAABJRU5ErkJggg==) no-repeat right -20px center;border:1px solid #999;font-size:14px;height:25px;margin:0 0 .5em 7px;padding:0;padding:2px;width:103px}#conversejs #converse-roster .roster-filter.x{background-position:right 3px center}#conversejs #converse-roster .roster-filter.onX{cursor:pointer}#conversejs #converse-roster .roster-contacts{margin:0;max-height:195px;max-height:calc(100% - 26px);overflow-x:hidden;overflow-y:auto;padding-bottom:15px}#conversejs #converse-roster .group-toggle{color:#6C4C44;display:block;width:100%}#conversejs #converse-roster dt{display:none}#conversejs #converse-roster dd{line-height:16px;padding:4px 2px 0 4px;height:24px}#conversejs #converse-roster dd a,#conversejs #converse-roster dd span{text-shadow:0 1px 0 #FAFAFA;display:inline-block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-left:3px}#conversejs #converse-roster dd span{padding:0 5px 0 0}#conversejs #converse-roster dd a.decline-xmpp-request{margin-left:5px}#conversejs #converse-roster dd a.remove-xmpp-contact{float:right;width:22px;margin:0;display:none;color:#6C4C44}#conversejs #converse-roster dd:hover a.remove-xmpp-contact{display:inline-block}#conversejs #converse-roster dd.odd{background-color:#DCEAC5}#conversejs #converse-roster dd.current-xmpp-contact span{font-size:16px;float:left;color:#436F64}#conversejs #converse-roster dd a.open-chat,#conversejs #converse-roster span.pending-contact-name{width:80%}#conversejs #converse-roster span.req-contact-name{width:69%;padding:0}#conversejs #available-chatrooms{text-align:left}#conversejs #available-chatrooms dt,#conversejs #converse-roster dt{font-weight:400;color:#6C4C44;border:none;padding:.5em;text-shadow:0 1px 0 #FAFAFA}#conversejs .room-info{font-size:11px;font-style:normal;font-weight:400}#conversejs li.room-info{display:block;margin-left:5px}#conversejs div.room-info{clear:left}#conversejs p.room-info{margin:0;padding:0;display:block;white-space:normal}#conversejs a.room-info{width:15px;display:none;clear:right}#conversejs a.open-room{float:left;white-space:nowrap;text-overflow:ellipsis;overflow-x:hidden}#conversejs dd.available-chatroom{overflow-x:hidden;text-overflow:ellipsis;padding:.25em .5em;white-space:nowrap}#conversejs dd.available-chatroom a.open-room{width:150px}#conversejs dd.available-chatroom:hover a.room-info{display:inline-block;font-size:14px}#conversejs #converse-roster dd,#conversejs dd.available-chatroom{font-weight:700;border:none;display:block;color:#6C4C44;text-shadow:0 1px 0 #FAFAFA;clear:both;overflow-y:hidden}#conversejs #converse-roster dd:hover,#conversejs .roster-group:hover,#conversejs dd.available-chatroom:hover{background-color:#E3C9C1}#conversejs .chatbox,#conversejs .chatroom{height:35px;float:right;margin:0 7px;display:block}@media screen and (max-width:480px){#conversejs .chatbox,#conversejs .chatroom{margin:0}}#conversejs .chatbox{width:200px}@media screen and (max-width:480px){#conversejs .chatbox{width:100%}}#conversejs .chatbox .box-flyout{z-index:1;width:200px}@media screen and (max-width:480px){#conversejs .chatbox .box-flyout{width:100%}}#conversejs .chatbox .dropdown a{width:148px;display:inline-block;line-height:25px}#conversejs .chatbox .dropdown li{list-style:none;padding-left:0}#conversejs .chatbox .dropdown dd ul{padding:0;list-style:none;position:absolute;left:0;top:0;border:1px solid #F1DCD6;width:100%;z-index:21;background-color:#F1E2DD}#conversejs .chatbox .dropdown dd ul li:hover{background-color:#E3C9C1}#conversejs .chatbox .dropdown dd.search-xmpp ul{box-shadow:1px 4px 10px 1px rgba(0,0,0,.4)}#conversejs .chatbox .dropdown dd.search-xmpp ul li:hover{background-color:#F1E2DD}#conversejs .chatbox .dropdown dt a span{cursor:pointer;display:block;padding:4px 7px 0 5px}#conversejs .chatroom,#conversejs .chatroom .box-flyout{width:300px}@media screen and (max-width:480px){#conversejs .chatroom,#conversejs .chatroom .box-flyout{width:100%}}#conversejs .chatroom label{margin-left:2px;font-size:12px}#conversejs .chatroom .participant-list{list-style:none}#conversejs .chatroom .participant-list li{cursor:default;display:block;font-size:12px;font-weight:700;overflow:hidden;padding:2px 5px;text-overflow:ellipsis;white-space:nowrap}#conversejs .chatroom .participant-list li.moderator{color:#8f2831}#conversejs .chatroom .chat-textarea{border-bottom-right-radius:0}#conversejs .chatroom .chat-area{float:left;height:100%;width:200px}#conversejs .chatroom .invited-contact{margin:-1px 0 0 -1px;width:100px;border:1px solid #999}#conversejs .chatroom .invited-contact.tt-input{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gkBCjE0uzKkOgAAAidJREFUKM+N0k+IEnEUB/D3cyscdagkWpHV0WGWREXm0AgOGkSJ07kh2UXYU5cOewm6Bp0KXG/tpSCv6hyEFQIhMEaE3yERYfwTOoqKGLQxDAbqYadLgu7J7/XxeY/3ez8EACDLsgljfMfj8ZxUKhXXYDAAnueBoqgyAMipVOovXAuSZdnUaDQeDofDs16vFyUIAjRNUwmCoG02G1AUdZ5IJN7GYrHfm3AvEAjcnUwmX0ajUdRqtV74fL6sruufKYoa6bp+fzabPUMI7ZfL5eImNHk8npNerxc1m80XHMe98fv9H3K5XDkSibxjWfb1arWaYoyPMMbCFqxUKi6CIODw8LDmdDq7oigaAACiKK5omv7KcdylpmlIkiTHFlRVFTRNUxVFqa/ROqIoGoqi5A3DgFartfU4Jp7ngSAI2uVyPZIk6dZmUZKk2w6H4xghBPF4HK7vWLbZbDCdTp+rqvpUkiS0RvV6/bTf7x8wDHMViURqm/AGAMgURZ232+1X1Wr102KxuEwmk3lZlo/7/f7BcrkkSZKs2e12tHXH/x/gHsY4jTE+0jQNGYYBCCFgGOaKJMkfjUaDZximGQ6HXzSbzZ+ZTMbY6oIxFgqFgqPT6YAgCMBxXM1ut6N0Op0fj8chi8XyjWXZ98Fg8DuCHZLNZh+USqWP8/n8idvt/hUKhV7u7QK9Xu8fmqanAJBQVXUfAGY7TQQAKBaLN8fjsdDtdh/run72Dzhf7XLe2UevAAAAAElFTkSuQmCC) no-repeat right 3px center}#conversejs .chatroom .participants{float:right;background-color:#fff;overflow-y:auto;overflow-x:hidden;border-left:1px solid #AAA;border-bottom-right-radius:4px;width:100px;height:100%}#conversejs .chatroom .participants label{font-size:12px;font-style:italic;margin:5px;display:block}#conversejs .chatroom-form,#conversejs .controlbox-pane{background-color:#fff;border-bottom-left-radius:4px;border-bottom-right-radius:4px;border:0;font-size:14px;overflow-y:auto;position:absolute;text-align:center;width:100%;height:289px;height:-webkit-calc(100% - 44px);height:calc(100% - 44px)}#conversejs .controlbox-pane{padding:5px 0;overflow-y:hidden}#conversejs .controlbox-pane dd{margin-left:0;margin-bottom:0}#conversejs .controlbox-pane dd.odd{background-color:#DCEAC5}#conversejs #converse-register .title{font-weight:700}#conversejs #converse-register .info{font-style:italic;color:green;font-size:85%;margin:5px 0}#conversejs #converse-register .instructions,#conversejs .form-help{color:gray;font-size:85%}#conversejs #converse-register .instructions:hover,#conversejs .form-help:hover{color:#6C4C44}#conversejs .form-help{padding-top:5px}#conversejs #converse-login,#conversejs #converse-register{background:#fff;padding:1em}#conversejs #converse-login input,#conversejs #converse-register input{width:100%;height:30px;margin:5px 0 10px;padding-left:.5em}#conversejs #converse-register .input-group{display:table;margin:auto;width:178px}#conversejs #converse-register .input-group input[name=username],#conversejs #converse-register .input-group span{display:table-cell}#conversejs #converse-register .input-group input[name=username]{width:100%}#conversejs .cancel-submit,#conversejs .save-submit{width:45%;margin:5px 3px}#conversejs .cancel,#conversejs .cancel-submit{color:#681F2C}#conversejs .save-submit{color:#436F64}#conversejs #converse-login label,#conversejs #converse-register label,#conversejs .chatroom-form label,#conversejs .controlbox-pane label{font-size:14px;font-weight:700;height:auto;margin:4px}#conversejs #converse-login .login-submit,#conversejs #converse-login .submit,#conversejs #converse-register .login-submit,#conversejs #converse-register .submit{height:30px;padding:0;font-size:14px}#conversejs #converse-login .submit{margin:1em 0}#conversejs form.add-chatroom{background:0 0;padding:.5em}#conversejs form.add-chatroom input[type=button],#conversejs form.add-chatroom input[type=submit],#conversejs form.add-chatroom input[type=text]{margin:0;width:100%;padding:.25em}#conversejs form.add-chatroom input[type=button],#conversejs form.add-chatroom input[type=submit],#conversejs form.add-chatroom span.spinner{margin-top:.5em;display:table-cell;width:auto}#conversejs form.add-chatroom input[type=submit]{color:#436F64}#conversejs select#select-xmpp-status{float:right;margin-right:.5em}#conversejs .chat-head{border-top-left-radius:4px;border-top-right-radius:4px;color:#fff;font-size:100%;margin:0;padding:6px}#conversejs .chat-head.controlbox-head{background-color:#436F64;border-top-left-radius:4px;border-top-right-radius:4px;color:#fff;height:44px;margin:0;padding:6px 6px 6px 0}#conversejs .chat-head .avatar{float:left}#conversejs .chat-head #controlbox-tabs{text-align:center;display:inline;overflow:hidden;font-size:12px;list-style-type:none}#conversejs .chat-head #controlbox-tabs a.current,#conversejs .chat-head #controlbox-tabs a.current:hover{box-shadow:none;border-bottom:0;height:44px;cursor:default;color:#6C4C44}#conversejs .chat-head #controlbox-tabs li{float:left;list-style:none;padding-left:0;text-shadow:#fff 0 1px 0;width:38%}#conversejs .chat-head #controlbox-tabs li a{background-color:#fff;border-bottom:1px solid #CCC;border-top-left-radius:4px;border-top-right-radius:4px;box-shadow:inset 2px -2px 20px rgba(0,0,0,.3);color:#888;display:block;font-size:12px;height:43px;line-height:43px;margin:0;text-align:center;text-decoration:none}#conversejs .chat-head #controlbox-tabs li a:hover{color:#6C4C44}#conversejs div#chatrooms{overflow-y:auto}#conversejs form.sendXMPPMessage{-moz-background-clip:padding;-moz-border-radius:4px;-webkit-background-clip:padding-box;-webkit-border-radius:4px;background:#fff;border-radius:4px;border-top-left-radius:0;border-top-right-radius:0;border:0;margin:0;padding:0;position:relative;height:82px;width:200px}@media screen and (max-width:480px){#conversejs form.sendXMPPMessage{width:100%}}#conversejs form.sendXMPPMessage .chat-textarea{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border:0;height:62px;padding:.5em;width:100%;resize:none}#conversejs .chat-toolbar{font-size:14px;margin:0;padding:0 4px;height:20px;display:block}#conversejs .chat-toolbar a{color:#436F64}#conversejs .chat-toolbar .unencrypted,#conversejs .chat-toolbar .unencrypted a{color:#8f2831}#conversejs .chat-toolbar .unverified,#conversejs .chat-toolbar .unverified a{color:#cf5300}#conversejs .chat-toolbar .private,#conversejs .chat-toolbar .private a{color:#4b7003}#conversejs .chat-toolbar .toggle-clear,#conversejs .chat-toolbar .toggle-otr,#conversejs .chat-toolbar .toggle-participants{float:right}#conversejs .chat-toolbar li{display:inline-block;list-style:none;padding:0 3px;cursor:pointer;margin-top:1px}#conversejs .chat-toolbar li:hover{cursor:pointer}#conversejs .chat-toolbar ul{background:#fff;bottom:100%;box-shadow:0 -1px 2px 0 rgba(0,0,0,.4);display:none;font-size:12px;margin:0 0 1px;position:absolute;right:0}#conversejs .chat-toolbar ul li{cursor:pointer;list-style:none;position:relative}#conversejs .chat-toolbar ul li a:hover{color:#8f2831}#conversejs .chat-toolbar .toggle-smiley{padding-left:5px}#conversejs .chat-toolbar .toggle-smiley ul li{font-size:14px;padding:5px;z-index:98}#conversejs .chat-toolbar .toggle-smiley ul li:hover{background-color:#E3C9C1}#conversejs .chat-toolbar .toggle-otr ul li{background-color:#fff;display:block;z-index:99}#conversejs .chat-toolbar .toggle-otr ul li a{-moz-transition:background-color .2s ease-in-out;-webkit-transition:background-color .2s ease-in-out;transition:background-color .2s ease-in-out;display:block;padding:1px;text-decoration:none}#conversejs .chat-toolbar-text{font-size:12px;padding-right:3px}#conversejs #set-custom-xmpp-status{float:left;padding:0}#conversejs #set-custom-xmpp-status input{height:26px;width:-webkit-calc(100% - 40px);width:calc(100% - 40px);padding:0 0 0 .5em}#conversejs #set-custom-xmpp-status button{height:26px;width:40px;padding:1px}#conversejs .chat-textarea-chatbox-selected{border:1px solid #578308;margin:0}#conversejs .chat-textarea-chatroom-selected{border:2px solid #436F64;margin:0}#conversejs #controlbox{display:none}#conversejs #controlbox div.xmpp-status{display:inline}#conversejs .chatbox .dropdown{background-color:#F1E2DD}#conversejs .chatbox .dropdown dd{position:relative}#conversejs .chatbox .dropdown dd,#conversejs .dropdown dt,#conversejs .dropdown ul{margin:0;padding:0}#conversejs .add-xmpp-contact{background:0 0;padding:5px}#conversejs .add-xmpp-contact input{margin:0 0 1rem;width:100%}#conversejs .add-xmpp-contact button{width:100%}#conversejs .xmpp-status-menu{text-align:left;box-shadow:1px 4px 10px 1px rgba(0,0,0,.4)}#conversejs .xmpp-status-menu li{padding:2px}#conversejs .xmpp-status-menu li a{width:100%;padding:0 8px}#conversejs .xmpp-status-menu li a.logout,#conversejs .xmpp-status-menu li a.logout span{color:#681F2C}#conversejs .set-xmpp-status{background:0 0;padding:.5em}#conversejs .set-xmpp-status .dropdown dd ul{z-index:22}#conversejs .box-flyout,#conversejs .minimized-chats-flyout{border-radius:4px;bottom:6px;box-shadow:1px 3px 5px 3px rgba(0,0,0,.4);display:block;height:400px;position:absolute}@media screen and (max-width:480px){#conversejs .box-flyout,#conversejs .minimized-chats-flyout{height:400px}}#conversejs .minimized-chats-flyout{border-radius:4px;bottom:35px;box-shadow:1px 3px 5px 3px rgba(0,0,0,.4);display:block;position:absolute;height:auto;width:130px}#conversejs .minimized-chats-flyout .chat-head,#conversejs .minimized-chats-flyout .chat-head-chatroom{border-radius:4px;width:130px;height:35px;margin-bottom:1px}#conversejs .minimized-chats-flyout.minimized{height:auto}#conversejs .dragresize{position:absolute;width:200px;height:5px;background:0 0;border:0;top:0;margin-left:0;cursor:n-resize;z-index:20}
\ No newline at end of file \ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment