51586fc8cfa664d079dd292d6c1a37de342e54b9
[platform/framework/web/web-ui-fw.git] / libs / js / underscore.js
1 //     Underscore.js 1.1.7
2 //     (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
3 //     Underscore is freely distributable under the MIT license.
4 //     Portions of Underscore are inspired or borrowed from Prototype,
5 //     Oliver Steele's Functional, and John Resig's Micro-Templating.
6 //     For all details and documentation:
7 //     http://documentcloud.github.com/underscore
8
9 (function() {
10
11   // Baseline setup
12   // --------------
13
14   // Establish the root object, `window` in the browser, or `global` on the server.
15   var root = this;
16
17   // Save the previous value of the `_` variable.
18   var previousUnderscore = root._;
19
20   // Establish the object that gets returned to break out of a loop iteration.
21   var breaker = {};
22
23   // Save bytes in the minified (but not gzipped) version:
24   var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
25
26   // Create quick reference variables for speed access to core prototypes.
27   var slice            = ArrayProto.slice,
28       unshift          = ArrayProto.unshift,
29       toString         = ObjProto.toString,
30       hasOwnProperty   = ObjProto.hasOwnProperty;
31
32   // All **ECMAScript 5** native function implementations that we hope to use
33   // are declared here.
34   var
35     nativeForEach      = ArrayProto.forEach,
36     nativeMap          = ArrayProto.map,
37     nativeReduce       = ArrayProto.reduce,
38     nativeReduceRight  = ArrayProto.reduceRight,
39     nativeFilter       = ArrayProto.filter,
40     nativeEvery        = ArrayProto.every,
41     nativeSome         = ArrayProto.some,
42     nativeIndexOf      = ArrayProto.indexOf,
43     nativeLastIndexOf  = ArrayProto.lastIndexOf,
44     nativeIsArray      = Array.isArray,
45     nativeKeys         = Object.keys,
46     nativeBind         = FuncProto.bind;
47
48   // Create a safe reference to the Underscore object for use below.
49   var _ = function(obj) { return new wrapper(obj); };
50
51   // Export the Underscore object for **CommonJS**, with backwards-compatibility
52   // for the old `require()` API. If we're not in CommonJS, add `_` to the
53   // global object.
54   if (typeof module !== 'undefined' && module.exports) {
55     module.exports = _;
56     _._ = _;
57   } else {
58     // Exported as a string, for Closure Compiler "advanced" mode.
59     root['_'] = _;
60   }
61
62   // Current version.
63   _.VERSION = '1.1.7';
64
65   // Collection Functions
66   // --------------------
67
68   // The cornerstone, an `each` implementation, aka `forEach`.
69   // Handles objects with the built-in `forEach`, arrays, and raw objects.
70   // Delegates to **ECMAScript 5**'s native `forEach` if available.
71   var each = _.each = _.forEach = function(obj, iterator, context) {
72     if (obj == null) return;
73     if (nativeForEach && obj.forEach === nativeForEach) {
74       obj.forEach(iterator, context);
75     } else if (obj.length === +obj.length) {
76       for (var i = 0, l = obj.length; i < l; i++) {
77         if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
78       }
79     } else {
80       for (var key in obj) {
81         if (hasOwnProperty.call(obj, key)) {
82           if (iterator.call(context, obj[key], key, obj) === breaker) return;
83         }
84       }
85     }
86   };
87
88   // Return the results of applying the iterator to each element.
89   // Delegates to **ECMAScript 5**'s native `map` if available.
90   _.map = function(obj, iterator, context) {
91     var results = [];
92     if (obj == null) return results;
93     if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
94     each(obj, function(value, index, list) {
95       results[results.length] = iterator.call(context, value, index, list);
96     });
97     return results;
98   };
99
100   // **Reduce** builds up a single result from a list of values, aka `inject`,
101   // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
102   _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
103     var initial = memo !== void 0;
104     if (obj == null) obj = [];
105     if (nativeReduce && obj.reduce === nativeReduce) {
106       if (context) iterator = _.bind(iterator, context);
107       return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
108     }
109     each(obj, function(value, index, list) {
110       if (!initial) {
111         memo = value;
112         initial = true;
113       } else {
114         memo = iterator.call(context, memo, value, index, list);
115       }
116     });
117     if (!initial) throw new TypeError("Reduce of empty array with no initial value");
118     return memo;
119   };
120
121   // The right-associative version of reduce, also known as `foldr`.
122   // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
123   _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
124     if (obj == null) obj = [];
125     if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
126       if (context) iterator = _.bind(iterator, context);
127       return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
128     }
129     var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
130     return _.reduce(reversed, iterator, memo, context);
131   };
132
133   // Return the first value which passes a truth test. Aliased as `detect`.
134   _.find = _.detect = function(obj, iterator, context) {
135     var result;
136     any(obj, function(value, index, list) {
137       if (iterator.call(context, value, index, list)) {
138         result = value;
139         return true;
140       }
141     });
142     return result;
143   };
144
145   // Return all the elements that pass a truth test.
146   // Delegates to **ECMAScript 5**'s native `filter` if available.
147   // Aliased as `select`.
148   _.filter = _.select = function(obj, iterator, context) {
149     var results = [];
150     if (obj == null) return results;
151     if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
152     each(obj, function(value, index, list) {
153       if (iterator.call(context, value, index, list)) results[results.length] = value;
154     });
155     return results;
156   };
157
158   // Return all the elements for which a truth test fails.
159   _.reject = function(obj, iterator, context) {
160     var results = [];
161     if (obj == null) return results;
162     each(obj, function(value, index, list) {
163       if (!iterator.call(context, value, index, list)) results[results.length] = value;
164     });
165     return results;
166   };
167
168   // Determine whether all of the elements match a truth test.
169   // Delegates to **ECMAScript 5**'s native `every` if available.
170   // Aliased as `all`.
171   _.every = _.all = function(obj, iterator, context) {
172     var result = true;
173     if (obj == null) return result;
174     if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
175     each(obj, function(value, index, list) {
176       if (!(result = result && iterator.call(context, value, index, list))) return breaker;
177     });
178     return result;
179   };
180
181   // Determine if at least one element in the object matches a truth test.
182   // Delegates to **ECMAScript 5**'s native `some` if available.
183   // Aliased as `any`.
184   var any = _.some = _.any = function(obj, iterator, context) {
185     iterator = iterator || _.identity;
186     var result = false;
187     if (obj == null) return result;
188     if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
189     each(obj, function(value, index, list) {
190       if (result |= iterator.call(context, value, index, list)) return breaker;
191     });
192     return !!result;
193   };
194
195   // Determine if a given value is included in the array or object using `===`.
196   // Aliased as `contains`.
197   _.include = _.contains = function(obj, target) {
198     var found = false;
199     if (obj == null) return found;
200     if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
201     any(obj, function(value) {
202       if (found = value === target) return true;
203     });
204     return found;
205   };
206
207   // Invoke a method (with arguments) on every item in a collection.
208   _.invoke = function(obj, method) {
209     var args = slice.call(arguments, 2);
210     return _.map(obj, function(value) {
211       return (method.call ? method || value : value[method]).apply(value, args);
212     });
213   };
214
215   // Convenience version of a common use case of `map`: fetching a property.
216   _.pluck = function(obj, key) {
217     return _.map(obj, function(value){ return value[key]; });
218   };
219
220   // Return the maximum element or (element-based computation).
221   _.max = function(obj, iterator, context) {
222     if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
223     var result = {computed : -Infinity};
224     each(obj, function(value, index, list) {
225       var computed = iterator ? iterator.call(context, value, index, list) : value;
226       computed >= result.computed && (result = {value : value, computed : computed});
227     });
228     return result.value;
229   };
230
231   // Return the minimum element (or element-based computation).
232   _.min = function(obj, iterator, context) {
233     if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
234     var result = {computed : Infinity};
235     each(obj, function(value, index, list) {
236       var computed = iterator ? iterator.call(context, value, index, list) : value;
237       computed < result.computed && (result = {value : value, computed : computed});
238     });
239     return result.value;
240   };
241
242   // Sort the object's values by a criterion produced by an iterator.
243   _.sortBy = function(obj, iterator, context) {
244     return _.pluck(_.map(obj, function(value, index, list) {
245       return {
246         value : value,
247         criteria : iterator.call(context, value, index, list)
248       };
249     }).sort(function(left, right) {
250       var a = left.criteria, b = right.criteria;
251       return a < b ? -1 : a > b ? 1 : 0;
252     }), 'value');
253   };
254
255   // Groups the object's values by a criterion produced by an iterator
256   _.groupBy = function(obj, iterator) {
257     var result = {};
258     each(obj, function(value, index) {
259       var key = iterator(value, index);
260       (result[key] || (result[key] = [])).push(value);
261     });
262     return result;
263   };
264
265   // Use a comparator function to figure out at what index an object should
266   // be inserted so as to maintain order. Uses binary search.
267   _.sortedIndex = function(array, obj, iterator) {
268     iterator || (iterator = _.identity);
269     var low = 0, high = array.length;
270     while (low < high) {
271       var mid = (low + high) >> 1;
272       iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
273     }
274     return low;
275   };
276
277   // Safely convert anything iterable into a real, live array.
278   _.toArray = function(iterable) {
279     if (!iterable)                return [];
280     if (iterable.toArray)         return iterable.toArray();
281     if (_.isArray(iterable))      return slice.call(iterable);
282     if (_.isArguments(iterable))  return slice.call(iterable);
283     return _.values(iterable);
284   };
285
286   // Return the number of elements in an object.
287   _.size = function(obj) {
288     return _.toArray(obj).length;
289   };
290
291   // Array Functions
292   // ---------------
293
294   // Get the first element of an array. Passing **n** will return the first N
295   // values in the array. Aliased as `head`. The **guard** check allows it to work
296   // with `_.map`.
297   _.first = _.head = function(array, n, guard) {
298     return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
299   };
300
301   // Returns everything but the first entry of the array. Aliased as `tail`.
302   // Especially useful on the arguments object. Passing an **index** will return
303   // the rest of the values in the array from that index onward. The **guard**
304   // check allows it to work with `_.map`.
305   _.rest = _.tail = function(array, index, guard) {
306     return slice.call(array, (index == null) || guard ? 1 : index);
307   };
308
309   // Get the last element of an array.
310   _.last = function(array) {
311     return array[array.length - 1];
312   };
313
314   // Trim out all falsy values from an array.
315   _.compact = function(array) {
316     return _.filter(array, function(value){ return !!value; });
317   };
318
319   // Return a completely flattened version of an array.
320   _.flatten = function(array) {
321     return _.reduce(array, function(memo, value) {
322       if (_.isArray(value)) return memo.concat(_.flatten(value));
323       memo[memo.length] = value;
324       return memo;
325     }, []);
326   };
327
328   // Return a version of the array that does not contain the specified value(s).
329   _.without = function(array) {
330     return _.difference(array, slice.call(arguments, 1));
331   };
332
333   // Produce a duplicate-free version of the array. If the array has already
334   // been sorted, you have the option of using a faster algorithm.
335   // Aliased as `unique`.
336   _.uniq = _.unique = function(array, isSorted) {
337     return _.reduce(array, function(memo, el, i) {
338       if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el;
339       return memo;
340     }, []);
341   };
342
343   // Produce an array that contains the union: each distinct element from all of
344   // the passed-in arrays.
345   _.union = function() {
346     return _.uniq(_.flatten(arguments));
347   };
348
349   // Produce an array that contains every item shared between all the
350   // passed-in arrays. (Aliased as "intersect" for back-compat.)
351   _.intersection = _.intersect = function(array) {
352     var rest = slice.call(arguments, 1);
353     return _.filter(_.uniq(array), function(item) {
354       return _.every(rest, function(other) {
355         return _.indexOf(other, item) >= 0;
356       });
357     });
358   };
359
360   // Take the difference between one array and another.
361   // Only the elements present in just the first array will remain.
362   _.difference = function(array, other) {
363     return _.filter(array, function(value){ return !_.include(other, value); });
364   };
365
366   // Zip together multiple lists into a single array -- elements that share
367   // an index go together.
368   _.zip = function() {
369     var args = slice.call(arguments);
370     var length = _.max(_.pluck(args, 'length'));
371     var results = new Array(length);
372     for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
373     return results;
374   };
375
376   // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
377   // we need this function. Return the position of the first occurrence of an
378   // item in an array, or -1 if the item is not included in the array.
379   // Delegates to **ECMAScript 5**'s native `indexOf` if available.
380   // If the array is large and already in sort order, pass `true`
381   // for **isSorted** to use binary search.
382   _.indexOf = function(array, item, isSorted) {
383     if (array == null) return -1;
384     var i, l;
385     if (isSorted) {
386       i = _.sortedIndex(array, item);
387       return array[i] === item ? i : -1;
388     }
389     if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
390     for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
391     return -1;
392   };
393
394
395   // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
396   _.lastIndexOf = function(array, item) {
397     if (array == null) return -1;
398     if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
399     var i = array.length;
400     while (i--) if (array[i] === item) return i;
401     return -1;
402   };
403
404   // Generate an integer Array containing an arithmetic progression. A port of
405   // the native Python `range()` function. See
406   // [the Python documentation](http://docs.python.org/library/functions.html#range).
407   _.range = function(start, stop, step) {
408     if (arguments.length <= 1) {
409       stop = start || 0;
410       start = 0;
411     }
412     step = arguments[2] || 1;
413
414     var len = Math.max(Math.ceil((stop - start) / step), 0);
415     var idx = 0;
416     var range = new Array(len);
417
418     while(idx < len) {
419       range[idx++] = start;
420       start += step;
421     }
422
423     return range;
424   };
425
426   // Function (ahem) Functions
427   // ------------------
428
429   // Create a function bound to a given object (assigning `this`, and arguments,
430   // optionally). Binding with arguments is also known as `curry`.
431   // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
432   // We check for `func.bind` first, to fail fast when `func` is undefined.
433   _.bind = function(func, obj) {
434     if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
435     var args = slice.call(arguments, 2);
436     return function() {
437       return func.apply(obj, args.concat(slice.call(arguments)));
438     };
439   };
440
441   // Bind all of an object's methods to that object. Useful for ensuring that
442   // all callbacks defined on an object belong to it.
443   _.bindAll = function(obj) {
444     var funcs = slice.call(arguments, 1);
445     if (funcs.length == 0) funcs = _.functions(obj);
446     each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
447     return obj;
448   };
449
450   // Memoize an expensive function by storing its results.
451   _.memoize = function(func, hasher) {
452     var memo = {};
453     hasher || (hasher = _.identity);
454     return function() {
455       var key = hasher.apply(this, arguments);
456       return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
457     };
458   };
459
460   // Delays a function for the given number of milliseconds, and then calls
461   // it with the arguments supplied.
462   _.delay = function(func, wait) {
463     var args = slice.call(arguments, 2);
464     return setTimeout(function(){ return func.apply(func, args); }, wait);
465   };
466
467   // Defers a function, scheduling it to run after the current call stack has
468   // cleared.
469   _.defer = function(func) {
470     return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
471   };
472
473   // Internal function used to implement `_.throttle` and `_.debounce`.
474   var limit = function(func, wait, debounce) {
475     var timeout;
476     return function() {
477       var context = this, args = arguments;
478       var throttler = function() {
479         timeout = null;
480         func.apply(context, args);
481       };
482       if (debounce) clearTimeout(timeout);
483       if (debounce || !timeout) timeout = setTimeout(throttler, wait);
484     };
485   };
486
487   // Returns a function, that, when invoked, will only be triggered at most once
488   // during a given window of time.
489   _.throttle = function(func, wait) {
490     return limit(func, wait, false);
491   };
492
493   // Returns a function, that, as long as it continues to be invoked, will not
494   // be triggered. The function will be called after it stops being called for
495   // N milliseconds.
496   _.debounce = function(func, wait) {
497     return limit(func, wait, true);
498   };
499
500   // Returns a function that will be executed at most one time, no matter how
501   // often you call it. Useful for lazy initialization.
502   _.once = function(func) {
503     var ran = false, memo;
504     return function() {
505       if (ran) return memo;
506       ran = true;
507       memo = func.apply(this, arguments);
508       return memo;
509     };
510   };
511
512   // Returns the first function passed as an argument to the second,
513   // allowing you to adjust arguments, run code before and after, and
514   // conditionally execute the original function.
515   _.wrap = function(func, wrapper) {
516     return function() {
517       var args = [func].concat(slice.call(arguments));
518       return wrapper.apply(this, args);
519     };
520   };
521
522   // Returns a function that is the composition of a list of functions, each
523   // consuming the return value of the function that follows.
524   _.compose = function() {
525     var funcs = slice.call(arguments);
526     return function() {
527       var args = slice.call(arguments);
528       for (var i = funcs.length - 1; i >= 0; i--) {
529         args = [funcs[i].apply(this, args)];
530       }
531       return args[0];
532     };
533   };
534
535   // Returns a function that will only be executed after being called N times.
536   _.after = function(times, func) {
537     return function() {
538       if (--times < 1) { return func.apply(this, arguments); }
539     };
540   };
541
542
543   // Object Functions
544   // ----------------
545
546   // Retrieve the names of an object's properties.
547   // Delegates to **ECMAScript 5**'s native `Object.keys`
548   _.keys = nativeKeys || function(obj) {
549     if (obj !== Object(obj)) throw new TypeError('Invalid object');
550     var keys = [];
551     for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
552     return keys;
553   };
554
555   // Retrieve the values of an object's properties.
556   _.values = function(obj) {
557     return _.map(obj, _.identity);
558   };
559
560   // Return a sorted list of the function names available on the object.
561   // Aliased as `methods`
562   _.functions = _.methods = function(obj) {
563     var names = [];
564     for (var key in obj) {
565       if (_.isFunction(obj[key])) names.push(key);
566     }
567     return names.sort();
568   };
569
570   // Extend a given object with all the properties in passed-in object(s).
571   _.extend = function(obj) {
572     each(slice.call(arguments, 1), function(source) {
573       for (var prop in source) {
574         if (source[prop] !== void 0) obj[prop] = source[prop];
575       }
576     });
577     return obj;
578   };
579
580   // Fill in a given object with default properties.
581   _.defaults = function(obj) {
582     each(slice.call(arguments, 1), function(source) {
583       for (var prop in source) {
584         if (obj[prop] == null) obj[prop] = source[prop];
585       }
586     });
587     return obj;
588   };
589
590   // Create a (shallow-cloned) duplicate of an object.
591   _.clone = function(obj) {
592     return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
593   };
594
595   // Invokes interceptor with the obj, and then returns obj.
596   // The primary purpose of this method is to "tap into" a method chain, in
597   // order to perform operations on intermediate results within the chain.
598   _.tap = function(obj, interceptor) {
599     interceptor(obj);
600     return obj;
601   };
602
603   // Perform a deep comparison to check if two objects are equal.
604   _.isEqual = function(a, b) {
605     // Check object identity.
606     if (a === b) return true;
607     // Different types?
608     var atype = typeof(a), btype = typeof(b);
609     if (atype != btype) return false;
610     // Basic equality test (watch out for coercions).
611     if (a == b) return true;
612     // One is falsy and the other truthy.
613     if ((!a && b) || (a && !b)) return false;
614     // Unwrap any wrapped objects.
615     if (a._chain) a = a._wrapped;
616     if (b._chain) b = b._wrapped;
617     // One of them implements an isEqual()?
618     if (a.isEqual) return a.isEqual(b);
619     if (b.isEqual) return b.isEqual(a);
620     // Check dates' integer values.
621     if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
622     // Both are NaN?
623     if (_.isNaN(a) && _.isNaN(b)) return false;
624     // Compare regular expressions.
625     if (_.isRegExp(a) && _.isRegExp(b))
626       return a.source     === b.source &&
627              a.global     === b.global &&
628              a.ignoreCase === b.ignoreCase &&
629              a.multiline  === b.multiline;
630     // If a is not an object by this point, we can't handle it.
631     if (atype !== 'object') return false;
632     // Check for different array lengths before comparing contents.
633     if (a.length && (a.length !== b.length)) return false;
634     // Nothing else worked, deep compare the contents.
635     var aKeys = _.keys(a), bKeys = _.keys(b);
636     // Different object sizes?
637     if (aKeys.length != bKeys.length) return false;
638     // Recursive comparison of contents.
639     for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
640     return true;
641   };
642
643   // Is a given array or object empty?
644   _.isEmpty = function(obj) {
645     if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
646     for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
647     return true;
648   };
649
650   // Is a given value a DOM element?
651   _.isElement = function(obj) {
652     return !!(obj && obj.nodeType == 1);
653   };
654
655   // Is a given value an array?
656   // Delegates to ECMA5's native Array.isArray
657   _.isArray = nativeIsArray || function(obj) {
658     return toString.call(obj) === '[object Array]';
659   };
660
661   // Is a given variable an object?
662   _.isObject = function(obj) {
663     return obj === Object(obj);
664   };
665
666   // Is a given variable an arguments object?
667   _.isArguments = function(obj) {
668     return !!(obj && hasOwnProperty.call(obj, 'callee'));
669   };
670
671   // Is a given value a function?
672   _.isFunction = function(obj) {
673     return !!(obj && obj.constructor && obj.call && obj.apply);
674   };
675
676   // Is a given value a string?
677   _.isString = function(obj) {
678     return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
679   };
680
681   // Is a given value a number?
682   _.isNumber = function(obj) {
683     return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
684   };
685
686   // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript
687   // that does not equal itself.
688   _.isNaN = function(obj) {
689     return obj !== obj;
690   };
691
692   // Is a given value a boolean?
693   _.isBoolean = function(obj) {
694     return obj === true || obj === false;
695   };
696
697   // Is a given value a date?
698   _.isDate = function(obj) {
699     return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
700   };
701
702   // Is the given value a regular expression?
703   _.isRegExp = function(obj) {
704     return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
705   };
706
707   // Is a given value equal to null?
708   _.isNull = function(obj) {
709     return obj === null;
710   };
711
712   // Is a given variable undefined?
713   _.isUndefined = function(obj) {
714     return obj === void 0;
715   };
716
717   // Utility Functions
718   // -----------------
719
720   // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
721   // previous owner. Returns a reference to the Underscore object.
722   _.noConflict = function() {
723     root._ = previousUnderscore;
724     return this;
725   };
726
727   // Keep the identity function around for default iterators.
728   _.identity = function(value) {
729     return value;
730   };
731
732   // Run a function **n** times.
733   _.times = function (n, iterator, context) {
734     for (var i = 0; i < n; i++) iterator.call(context, i);
735   };
736
737   // Add your own custom functions to the Underscore object, ensuring that
738   // they're correctly added to the OOP wrapper as well.
739   _.mixin = function(obj) {
740     each(_.functions(obj), function(name){
741       addToWrapper(name, _[name] = obj[name]);
742     });
743   };
744
745   // Generate a unique integer id (unique within the entire client session).
746   // Useful for temporary DOM ids.
747   var idCounter = 0;
748   _.uniqueId = function(prefix) {
749     var id = idCounter++;
750     return prefix ? prefix + id : id;
751   };
752
753   // By default, Underscore uses ERB-style template delimiters, change the
754   // following template settings to use alternative delimiters.
755   _.templateSettings = {
756     evaluate    : /<%([\s\S]+?)%>/g,
757     interpolate : /<%=([\s\S]+?)%>/g
758   };
759
760   // JavaScript micro-templating, similar to John Resig's implementation.
761   // Underscore templating handles arbitrary delimiters, preserves whitespace,
762   // and correctly escapes quotes within interpolated code.
763   _.template = function(str, data) {
764     var c  = _.templateSettings;
765     var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
766       'with(obj||{}){__p.push(\'' +
767       str.replace(/\\/g, '\\\\')
768          .replace(/'/g, "\\'")
769          .replace(c.interpolate, function(match, code) {
770            return "'," + code.replace(/\\'/g, "'") + ",'";
771          })
772          .replace(c.evaluate || null, function(match, code) {
773            return "');" + code.replace(/\\'/g, "'")
774                               .replace(/[\r\n\t]/g, ' ') + "__p.push('";
775          })
776          .replace(/\r/g, '\\r')
777          .replace(/\n/g, '\\n')
778          .replace(/\t/g, '\\t')
779          + "');}return __p.join('');";
780     var func = new Function('obj', tmpl);
781     return data ? func(data) : func;
782   };
783
784   // The OOP Wrapper
785   // ---------------
786
787   // If Underscore is called as a function, it returns a wrapped object that
788   // can be used OO-style. This wrapper holds altered versions of all the
789   // underscore functions. Wrapped objects may be chained.
790   var wrapper = function(obj) { this._wrapped = obj; };
791
792   // Expose `wrapper.prototype` as `_.prototype`
793   _.prototype = wrapper.prototype;
794
795   // Helper function to continue chaining intermediate results.
796   var result = function(obj, chain) {
797     return chain ? _(obj).chain() : obj;
798   };
799
800   // A method to easily add functions to the OOP wrapper.
801   var addToWrapper = function(name, func) {
802     wrapper.prototype[name] = function() {
803       var args = slice.call(arguments);
804       unshift.call(args, this._wrapped);
805       return result(func.apply(_, args), this._chain);
806     };
807   };
808
809   // Add all of the Underscore functions to the wrapper object.
810   _.mixin(_);
811
812   // Add all mutator Array functions to the wrapper.
813   each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
814     var method = ArrayProto[name];
815     wrapper.prototype[name] = function() {
816       method.apply(this._wrapped, arguments);
817       return result(this._wrapped, this._chain);
818     };
819   });
820
821   // Add all accessor Array functions to the wrapper.
822   each(['concat', 'join', 'slice'], function(name) {
823     var method = ArrayProto[name];
824     wrapper.prototype[name] = function() {
825       return result(method.apply(this._wrapped, arguments), this._chain);
826     };
827   });
828
829   // Start chaining a wrapped Underscore object.
830   wrapper.prototype.chain = function() {
831     this._chain = true;
832     return this;
833   };
834
835   // Extracts the result from a wrapped and chained object.
836   wrapper.prototype.value = function() {
837     return this._wrapped;
838   };
839
840 })();