aboutsummaryrefslogtreecommitdiffstats
path: root/lib/underscore/underscore.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/underscore/underscore.js')
-rw-r--r--lib/underscore/underscore.js105
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);
};
});