app/assets/javascripts/ultimate/underscore/underscore.js in ultimate-helpers-0.1.0.1 vs app/assets/javascripts/ultimate/underscore/underscore.js in ultimate-helpers-0.2.0

- old
+ new

@@ -1,15 +1,16 @@ -// Underscore.js 1.4.2 -// http://underscorejs.org -// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. -// Underscore may be freely distributed under the MIT license. +// Underscore.js 1.4.4 +// =================== +// > http://underscorejs.org +// > (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. +// > Underscore may be freely distributed under the MIT license. + +// Baseline setup +// -------------- (function() { - // Baseline setup - // -------------- - // Establish the root object, `window` in the browser, or `global` on the server. var root = this; // Save the previous value of the `_` variable. var previousUnderscore = root._; @@ -22,11 +23,10 @@ // Create quick reference variables for speed access to core prototypes. var push = ArrayProto.push, slice = ArrayProto.slice, concat = ArrayProto.concat, - unshift = ArrayProto.unshift, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty; // All **ECMAScript 5** native function implementations that we hope to use // are declared here. @@ -59,15 +59,15 @@ if (typeof module !== 'undefined' && module.exports) { exports = module.exports = _; } exports._ = _; } else { - root['_'] = _; + root._ = _; } // Current version. - _.VERSION = '1.4.2'; + _.VERSION = '1.4.4'; // Collection Functions // -------------------- // The cornerstone, an `each` implementation, aka `forEach`. @@ -100,10 +100,12 @@ results[results.length] = iterator.call(context, value, index, list); }); return results; }; + var reduceError = 'Reduce of empty array with no initial value'; + // **Reduce** builds up a single result from a list of values, aka `inject`, // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { var initial = arguments.length > 2; if (obj == null) obj = []; @@ -117,22 +119,22 @@ initial = true; } else { memo = iterator.call(context, memo, value, index, list); } }); - if (!initial) throw new TypeError('Reduce of empty array with no initial value'); + if (!initial) throw new TypeError(reduceError); 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 arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); } var length = obj.length; if (length !== +length) { var keys = _.keys(obj); length = keys.length; @@ -144,11 +146,11 @@ initial = true; } else { memo = iterator.call(context, memo, obj[index], index, list); } }); - if (!initial) throw new TypeError('Reduce of empty array with no initial value'); + if (!initial) throw new TypeError(reduceError); return memo; }; // Return the first value which passes a truth test. Aliased as `detect`. _.find = _.detect = function(obj, iterator, context) { @@ -175,16 +177,13 @@ return results; }; // Return all the elements for which a truth test fails. _.reject = function(obj, iterator, context) { - var results = []; - if (obj == null) return results; - each(obj, function(value, index, list) { - if (!iterator.call(context, value, index, list)) results[results.length] = value; - }); - return results; + return _.filter(obj, function(value, index, list) { + return !iterator.call(context, value, index, list); + }, context); }; // Determine whether all of the elements match a truth test. // Delegates to **ECMAScript 5**'s native `every` if available. // Aliased as `all`. @@ -214,53 +213,58 @@ }; // Determine if the array or object contains a given value (using `===`). // Aliased as `include`. _.contains = _.include = function(obj, target) { - var found = false; - if (obj == null) return found; + if (obj == null) return false; if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; - found = any(obj, function(value) { + return any(obj, function(value) { return value === target; }); - return found; }; // Invoke a method (with arguments) on every item in a collection. _.invoke = function(obj, method) { var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); return _.map(obj, function(value) { - return (_.isFunction(method) ? method : value[method]).apply(value, args); + return (isFunc ? method : value[method]).apply(value, args); }); }; // Convenience version of a common use case of `map`: fetching a property. _.pluck = function(obj, key) { return _.map(obj, function(value){ return value[key]; }); }; // Convenience version of a common use case of `filter`: selecting only objects - // with specific `key:value` pairs. - _.where = function(obj, attrs) { - if (_.isEmpty(attrs)) return []; - return _.filter(obj, function(value) { + // containing specific `key:value` pairs. + _.where = function(obj, attrs, first) { + if (_.isEmpty(attrs)) return first ? null : []; + return _[first ? 'find' : 'filter'](obj, function(value) { for (var key in attrs) { if (attrs[key] !== value[key]) return false; } return true; }); }; + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.where(obj, attrs, true); + }; + // Return the maximum element or (element-based computation). // Can't optimize arrays of integers longer than 65,535 elements. // See: https://bugs.webkit.org/show_bug.cgi?id=80797 _.max = function(obj, iterator, context) { if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { return Math.max.apply(Math, obj); } if (!iterator && _.isEmpty(obj)) return -Infinity; - var result = {computed : -Infinity}; + var result = {computed : -Infinity, value: -Infinity}; each(obj, function(value, index, list) { var computed = iterator ? iterator.call(context, value, index, list) : value; computed >= result.computed && (result = {value : value, computed : computed}); }); return result.value; @@ -270,11 +274,11 @@ _.min = function(obj, iterator, context) { if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { return Math.min.apply(Math, obj); } if (!iterator && _.isEmpty(obj)) return Infinity; - var result = {computed : Infinity}; + var result = {computed : Infinity, value: Infinity}; each(obj, function(value, index, list) { var computed = iterator ? iterator.call(context, value, index, list) : value; computed < result.computed && (result = {value : value, computed : computed}); }); return result.value; @@ -319,11 +323,11 @@ }; // An internal function used for aggregate "group by" operations. var group = function(obj, value, context, behavior) { var result = {}; - var iterator = lookupIterator(value); + var iterator = lookupIterator(value || _.identity); each(obj, function(value, index) { var key = iterator.call(context, value, index, obj); behavior(result, key, value); }); return result; @@ -339,11 +343,11 @@ // 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 // criterion. _.countBy = function(obj, value, context) { - return group(obj, value, context, function(result, key, value) { + return group(obj, value, context, function(result, key) { if (!_.has(result, key)) result[key] = 0; result[key]++; }); }; @@ -361,11 +365,12 @@ }; // Safely convert anything iterable into a real, live array. _.toArray = function(obj) { if (!obj) return []; - if (obj.length === +obj.length) return slice.call(obj); + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); return _.values(obj); }; // Return the number of elements in an object. _.size = function(obj) { @@ -411,11 +416,11 @@ return slice.call(array, (n == null) || guard ? 1 : n); }; // Trim out all falsy values from an array. _.compact = function(array) { - return _.filter(array, function(value){ return !!value; }); + return _.filter(array, _.identity); }; // Internal implementation of a recursive `flatten` function. var flatten = function(input, shallow, output) { each(input, function(value) { @@ -440,10 +445,15 @@ // Produce a duplicate-free version of the array. If the array has already // been sorted, you have the option of using a faster algorithm. // Aliased as `unique`. _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } var initial = iterator ? _.map(array, iterator, context) : array; var results = []; var seen = []; each(initial, function(value, index) { if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { @@ -563,37 +573,35 @@ }; // Function (ahem) Functions // ------------------ - // Reusable constructor function for prototype setting. - var ctor = function(){}; - // Create a function bound to a given object (assigning `this`, and arguments, - // optionally). Binding with arguments is also known as `curry`. - // Delegates to **ECMAScript 5**'s native `Function.bind` if available. - // We check for `func.bind` first, to fail fast when `func` is undefined. - _.bind = function bind(func, context) { - var bound, args; + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - if (!_.isFunction(func)) throw new TypeError; - args = slice.call(arguments, 2); - return bound = function() { - if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); - ctor.prototype = func.prototype; - var self = new ctor; - var result = func.apply(self, args.concat(slice.call(arguments))); - if (Object(result) === result) return result; - return self; + var args = slice.call(arguments, 2); + return function() { + return func.apply(context, args.concat(slice.call(arguments))); }; }; + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. + _.partial = function(func) { + var args = slice.call(arguments, 1); + return function() { + return func.apply(this, args.concat(slice.call(arguments))); + }; + }; + // Bind all of an object's methods to that object. Useful for ensuring that // all callbacks defined on an object belong to it. _.bindAll = function(obj) { var funcs = slice.call(arguments, 1); - if (funcs.length == 0) funcs = _.functions(obj); + if (funcs.length === 0) funcs = _.functions(obj); each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); return obj; }; // Memoize an expensive function by storing its results. @@ -620,29 +628,30 @@ }; // Returns a function, that, when invoked, will only be triggered at most once // during a given window of time. _.throttle = function(func, wait) { - var context, args, timeout, throttling, more, result; - var whenDone = _.debounce(function(){ more = throttling = false; }, wait); + var context, args, timeout, result; + var previous = 0; + var later = function() { + previous = new Date; + timeout = null; + result = func.apply(context, args); + }; return function() { - context = this; args = arguments; - var later = function() { + var now = new Date; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); timeout = null; - if (more) { - result = func.apply(context, args); - } - whenDone(); - }; - if (!timeout) timeout = setTimeout(later, wait); - if (throttling) { - more = true; - } else { - throttling = true; + previous = now; result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); } - whenDone(); return result; }; }; // Returns a function, that, as long as it continues to be invoked, will not @@ -756,12 +765,14 @@ }; // Extend a given object with all the properties in passed-in object(s). _.extend = function(obj) { each(slice.call(arguments, 1), function(source) { - for (var prop in source) { - obj[prop] = source[prop]; + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } } }); return obj; }; @@ -786,12 +797,14 @@ }; // Fill in a given object with default properties. _.defaults = function(obj) { each(slice.call(arguments, 1), function(source) { - for (var prop in source) { - if (obj[prop] == null) obj[prop] = source[prop]; + if (source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } } }); return obj; }; @@ -952,11 +965,11 @@ }; } // Is a given object a finite number? _.isFinite = function(obj) { - return _.isNumber(obj) && isFinite(obj); + return isFinite(obj) && !isNaN(parseFloat(obj)); }; // Is the given value `NaN`? (NaN is the only number which does not equal itself). _.isNaN = function(obj) { return _.isNumber(obj) && obj != +obj; @@ -998,20 +1011,22 @@ return value; }; // Run a function **n** times. _.times = function(n, iterator, context) { - for (var i = 0; i < n; i++) iterator.call(context, i); + var accum = Array(n); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; }; // Return a random integer between min and max (inclusive). _.random = function(min, max) { if (max == null) { max = min; min = 0; } - return min + (0 | Math.random() * (max - min + 1)); + return min + Math.floor(Math.random() * (max - min + 1)); }; // List of HTML entities for escaping. var entityMap = { escape: { @@ -1063,11 +1078,11 @@ // Generate a unique integer id (unique within the entire client session). // Useful for temporary DOM ids. var idCounter = 0; _.uniqueId = function(prefix) { - var id = idCounter++; + var id = ++idCounter + ''; return prefix ? prefix + id : id; }; // By default, Underscore uses ERB-style template delimiters, change the // following template settings to use alternative delimiters. @@ -1098,10 +1113,11 @@ // JavaScript micro-templating, similar to John Resig's implementation. // Underscore templating handles arbitrary delimiters, preserves whitespace, // and correctly escapes quotes within interpolated code. _.template = function(text, data, settings) { + var render; settings = _.defaults({}, settings, _.templateSettings); // Combine delimiters into one regular expression via alternation. var matcher = new RegExp([ (settings.escape || noMatch).source, @@ -1113,15 +1129,22 @@ var index = 0; var source = "__p+='"; text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { source += text.slice(index, offset) .replace(escaper, function(match) { return '\\' + escapes[match]; }); - source += - escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" : - interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" : - evaluate ? "';\n" + evaluate + "\n__p+='" : ''; + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } index = offset + match.length; + return match; }); source += "';\n"; // If a variable is not specified, place data values in local scope. if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; @@ -1129,10 +1152,10 @@ source = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n" + source + "return __p;\n"; try { - var render = new Function(settings.variable || 'obj', '_', source); + render = new Function(settings.variable || 'obj', '_', source); } catch (e) { e.source = source; throw e; }