diff options
Diffstat (limited to 'lib/underscore/underscore.js')
| -rw-r--r-- | lib/underscore/underscore.js | 105 |
1 files changed, 71 insertions, 34 deletions
diff --git a/lib/underscore/underscore.js b/lib/underscore/underscore.js index 047f01c5..7006910e 100644 --- a/lib/underscore/underscore.js +++ b/lib/underscore/underscore.js @@ -1,14 +1,14 @@ // Underscore.js -// (c) 2009 Jeremy Ashkenas, DocumentCloud Inc. +// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc. // Underscore is freely distributable under the terms of the MIT license. // Portions of Underscore are inspired by or borrowed from Prototype.js, // Oliver Steele's Functional, and John Resig's Micro-Templating. // For all details and documentation: -// http://documentcloud.github.com/underscore/ +// http://documentcloud.github.com/underscore (function() { - /*------------------------- Baseline setup ---------------------------------*/ + // ------------------------- Baseline setup --------------------------------- // Establish the root object, "window" in the browser, or "global" on the server. var root = this; @@ -38,9 +38,9 @@ propertyIsEnumerable = Object.prototype.propertyIsEnumerable; // Current version. - _.VERSION = '0.5.1'; + _.VERSION = '0.5.7'; - /*------------------------ Collection Functions: ---------------------------*/ + // ------------------------ Collection Functions: --------------------------- // The cornerstone, an each implementation. // Handles objects implementing forEach, arrays, and raw objects. @@ -226,7 +226,7 @@ if (iterable.toArray) return iterable.toArray(); if (_.isArray(iterable)) return iterable; if (_.isArguments(iterable)) return slice.call(iterable); - return _.map(iterable, function(val){ return val; }); + return _.values(iterable); }; // Return the number of elements in an object. @@ -234,7 +234,7 @@ return _.toArray(obj).length; }; - /*-------------------------- Array Functions: ------------------------------*/ + // -------------------------- Array Functions: ------------------------------ // Get the first element of an array. Passing "n" will return the first N // values in the array. Aliased as "head". The "guard" check allows it to work @@ -340,7 +340,7 @@ } }; - /* ----------------------- Function Functions: -----------------------------*/ + // ----------------------- Function Functions: ------------------------------ // Create a function bound to a given object (assigning 'this', and arguments, // optionally). Binding with arguments is also known as 'curry'. @@ -396,7 +396,7 @@ }; }; - /* ------------------------- Object Functions: ---------------------------- */ + // ------------------------- Object Functions: ------------------------------ // Retrieve the names of an object's properties. _.keys = function(obj) { @@ -428,6 +428,13 @@ return _.extend({}, obj); }; + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + // Perform a deep comparison to check if two objects are equal. _.isEqual = function(a, b) { // Check object identity. @@ -474,9 +481,39 @@ return !!(obj && obj.nodeType == 1); }; + // Is a given value an array? + _.isArray = function(obj) { + return !!(obj && obj.concat && obj.unshift); + }; + // Is a given variable an arguments object? _.isArguments = function(obj) { - return obj && _.isNumber(obj.length) && !_.isArray(obj) && !propertyIsEnumerable.call(obj, 'length'); + return obj && _.isNumber(obj.length) && !obj.concat && !obj.substr && !obj.apply && !propertyIsEnumerable.call(obj, 'length'); + }; + + // Is a given value a function? + _.isFunction = function(obj) { + return !!(obj && obj.constructor && obj.call && obj.apply); + }; + + // Is a given value a string? + _.isString = function(obj) { + return !!(obj === '' || (obj && obj.charCodeAt && obj.substr)); + }; + + // Is a given value a number? + _.isNumber = function(obj) { + return (obj === +obj) || (toString.call(obj) === '[object Number]'); + }; + + // Is a given value a date? + _.isDate = function(obj) { + return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear); + }; + + // Is the given value a regular expression? + _.isRegExp = function(obj) { + return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false)); }; // Is the given value NaN -- this one is interesting. NaN != NaN, and @@ -495,17 +532,7 @@ return typeof obj == 'undefined'; }; - // Define the isArray, isDate, isFunction, isNumber, isRegExp, and isString - // functions based on their toString identifiers. - var types = ['Array', 'Date', 'Function', 'Number', 'RegExp', 'String']; - for (var i=0, l=types.length; i<l; i++) { - (function() { - var identifier = '[object ' + types[i] + ']'; - _['is' + types[i]] = function(obj) { return toString.call(obj) == identifier; }; - })(); - } - - /* -------------------------- Utility Functions: -------------------------- */ + // -------------------------- Utility Functions: ---------------------------- // Run Underscore.js in noConflict mode, returning the '_' variable to its // previous owner. Returns a reference to the Underscore object. @@ -532,25 +559,34 @@ return prefix ? prefix + id : id; }; + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + start : '<%', + end : '%>', + interpolate : /<%=(.+?)%>/g + }; + // JavaScript templating a-la ERB, pilfered from John Resig's // "Secrets of the JavaScript Ninja", page 83. + // Single-quote fix from Rick Strahl's version. _.template = function(str, data) { + var c = _.templateSettings; var fn = new Function('obj', 'var p=[],print=function(){p.push.apply(p,arguments);};' + 'with(obj){p.push(\'' + - str - .replace(/[\r\t\n]/g, " ") - .split("<%").join("\t") - .replace(/((^|%>)[^\t]*)'/g, "$1\r") - .replace(/\t=(.*?)%>/g, "',$1,'") - .split("\t").join("');") - .split("%>").join("p.push('") - .split("\r").join("\\'") - + "');}return p.join('');"); + str.replace(/[\r\t\n]/g, " ") + .replace(new RegExp("'(?=[^"+c.end[0]+"]*"+c.end+")","g"),"\t") + .split("'").join("\\'") + .split("\t").join("'") + .replace(c.interpolate, "',$1,'") + .split(c.start).join("');") + .split(c.end).join("p.push('") + + "');}return p.join('');"); return data ? fn(data) : fn; }; - /*------------------------------- Aliases ----------------------------------*/ + // ------------------------------- Aliases ---------------------------------- _.forEach = _.each; _.foldl = _.inject = _.reduce; @@ -562,7 +598,7 @@ _.tail = _.rest; _.methods = _.functions; - /*------------------------ Setup the OOP Wrapper: --------------------------*/ + // ------------------------ Setup the OOP Wrapper: -------------------------- // Helper function to continue chaining intermediate results. var result = function(obj, chain) { @@ -573,8 +609,9 @@ _.each(_.functions(_), function(name) { var method = _[name]; wrapper.prototype[name] = function() { - unshift.call(arguments, this._wrapped); - return result(method.apply(_, arguments), this._chain); + var args = _.toArray(arguments); + unshift.call(args, this._wrapped); + return result(method.apply(_, args), this._chain); }; }); |
