PageRenderTime 64ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/assets/js/libs/_.js

https://bitbucket.org/miselmipoivre/bclock
JavaScript | 1064 lines | 770 code | 96 blank | 198 comment | 229 complexity | 5b3969a421a7610ad23c076d5c7e7d77 MD5 | raw file
  1. // Underscore.js 1.3.3
  2. // (c) 2009-2012 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. (function() {
  9. // Baseline setup
  10. // --------------
  11. // Establish the root object, `window` in the browser, or `global` on the server.
  12. var root = this;
  13. // Save the previous value of the `_` variable.
  14. var previousUnderscore = root._;
  15. // Establish the object that gets returned to break out of a loop iteration.
  16. var breaker = {};
  17. // Save bytes in the minified (but not gzipped) version:
  18. var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
  19. // Create quick reference variables for speed access to core prototypes.
  20. var slice = ArrayProto.slice,
  21. unshift = ArrayProto.unshift,
  22. toString = ObjProto.toString,
  23. hasOwnProperty = ObjProto.hasOwnProperty;
  24. // All **ECMAScript 5** native function implementations that we hope to use
  25. // are declared here.
  26. var
  27. nativeForEach = ArrayProto.forEach,
  28. nativeMap = ArrayProto.map,
  29. nativeReduce = ArrayProto.reduce,
  30. nativeReduceRight = ArrayProto.reduceRight,
  31. nativeFilter = ArrayProto.filter,
  32. nativeEvery = ArrayProto.every,
  33. nativeSome = ArrayProto.some,
  34. nativeIndexOf = ArrayProto.indexOf,
  35. nativeLastIndexOf = ArrayProto.lastIndexOf,
  36. nativeIsArray = Array.isArray,
  37. nativeKeys = Object.keys,
  38. nativeBind = FuncProto.bind;
  39. // Create a safe reference to the Underscore object for use below.
  40. var _ = function(obj) { return new wrapper(obj); };
  41. // Export the Underscore object for **Node.js**, with
  42. // backwards-compatibility for the old `require()` API. If we're in
  43. // the browser, add `_` as a global object via a string identifier,
  44. // for Closure Compiler "advanced" mode.
  45. if (typeof exports !== 'undefined') {
  46. if (typeof module !== 'undefined' && module.exports) {
  47. exports = module.exports = _;
  48. }
  49. exports._ = _;
  50. } else {
  51. root['_'] = _;
  52. }
  53. // Current version.
  54. _.VERSION = '1.3.3';
  55. // Collection Functions
  56. // --------------------
  57. // The cornerstone, an `each` implementation, aka `forEach`.
  58. // Handles objects with the built-in `forEach`, arrays, and raw objects.
  59. // Delegates to **ECMAScript 5**'s native `forEach` if available.
  60. var each = _.each = _.forEach = function(obj, iterator, context) {
  61. if (obj == null) return;
  62. if (nativeForEach && obj.forEach === nativeForEach) {
  63. obj.forEach(iterator, context);
  64. } else if (obj.length === +obj.length) {
  65. for (var i = 0, l = obj.length; i < l; i++) {
  66. if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
  67. }
  68. } else {
  69. for (var key in obj) {
  70. if (_.has(obj, key)) {
  71. if (iterator.call(context, obj[key], key, obj) === breaker) return;
  72. }
  73. }
  74. }
  75. };
  76. // Return the results of applying the iterator to each element.
  77. // Delegates to **ECMAScript 5**'s native `map` if available.
  78. _.map = _.collect = function(obj, iterator, context) {
  79. var results = [];
  80. if (obj == null) return results;
  81. if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
  82. each(obj, function(value, index, list) {
  83. results[results.length] = iterator.call(context, value, index, list);
  84. });
  85. if (obj.length === +obj.length) results.length = obj.length;
  86. return results;
  87. };
  88. // **Reduce** builds up a single result from a list of values, aka `inject`,
  89. // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
  90. _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
  91. var initial = arguments.length > 2;
  92. if (obj == null) obj = [];
  93. if (nativeReduce && obj.reduce === nativeReduce) {
  94. if (context) iterator = _.bind(iterator, context);
  95. return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
  96. }
  97. each(obj, function(value, index, list) {
  98. if (!initial) {
  99. memo = value;
  100. initial = true;
  101. } else {
  102. memo = iterator.call(context, memo, value, index, list);
  103. }
  104. });
  105. if (!initial) throw new TypeError('Reduce of empty array with no initial value');
  106. return memo;
  107. };
  108. // The right-associative version of reduce, also known as `foldr`.
  109. // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
  110. _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
  111. var initial = arguments.length > 2;
  112. if (obj == null) obj = [];
  113. if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
  114. if (context) iterator = _.bind(iterator, context);
  115. return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
  116. }
  117. var reversed = _.toArray(obj).reverse();
  118. if (context && !initial) iterator = _.bind(iterator, context);
  119. return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
  120. };
  121. // Return the first value which passes a truth test. Aliased as `detect`.
  122. _.find = _.detect = function(obj, iterator, context) {
  123. var result;
  124. any(obj, function(value, index, list) {
  125. if (iterator.call(context, value, index, list)) {
  126. result = value;
  127. return true;
  128. }
  129. });
  130. return result;
  131. };
  132. // Return all the elements that pass a truth test.
  133. // Delegates to **ECMAScript 5**'s native `filter` if available.
  134. // Aliased as `select`.
  135. _.filter = _.select = function(obj, iterator, context) {
  136. var results = [];
  137. if (obj == null) return results;
  138. if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
  139. each(obj, function(value, index, list) {
  140. if (iterator.call(context, value, index, list)) results[results.length] = value;
  141. });
  142. return results;
  143. };
  144. // Return all the elements for which a truth test fails.
  145. _.reject = function(obj, iterator, context) {
  146. var results = [];
  147. if (obj == null) return results;
  148. each(obj, function(value, index, list) {
  149. if (!iterator.call(context, value, index, list)) results[results.length] = value;
  150. });
  151. return results;
  152. };
  153. // Determine whether all of the elements match a truth test.
  154. // Delegates to **ECMAScript 5**'s native `every` if available.
  155. // Aliased as `all`.
  156. _.every = _.all = function(obj, iterator, context) {
  157. var result = true;
  158. if (obj == null) return result;
  159. if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
  160. each(obj, function(value, index, list) {
  161. if (!(result = result && iterator.call(context, value, index, list))) return breaker;
  162. });
  163. return !!result;
  164. };
  165. // Determine if at least one element in the object matches a truth test.
  166. // Delegates to **ECMAScript 5**'s native `some` if available.
  167. // Aliased as `any`.
  168. var any = _.some = _.any = function(obj, iterator, context) {
  169. iterator || (iterator = _.identity);
  170. var result = false;
  171. if (obj == null) return result;
  172. if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
  173. each(obj, function(value, index, list) {
  174. if (result || (result = iterator.call(context, value, index, list))) return breaker;
  175. });
  176. return !!result;
  177. };
  178. // Determine if a given value is included in the array or object using `===`.
  179. // Aliased as `contains`.
  180. _.include = _.contains = function(obj, target) {
  181. var found = false;
  182. if (obj == null) return found;
  183. if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
  184. found = any(obj, function(value) {
  185. return value === target;
  186. });
  187. return found;
  188. };
  189. // Invoke a method (with arguments) on every item in a collection.
  190. _.invoke = function(obj, method) {
  191. var args = slice.call(arguments, 2);
  192. return _.map(obj, function(value) {
  193. return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
  194. });
  195. };
  196. // Convenience version of a common use case of `map`: fetching a property.
  197. _.pluck = function(obj, key) {
  198. return _.map(obj, function(value){ return value[key]; });
  199. };
  200. // Return the maximum element or (element-based computation).
  201. _.max = function(obj, iterator, context) {
  202. if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.max.apply(Math, obj);
  203. if (!iterator && _.isEmpty(obj)) return -Infinity;
  204. var result = {computed : -Infinity};
  205. each(obj, function(value, index, list) {
  206. var computed = iterator ? iterator.call(context, value, index, list) : value;
  207. computed >= result.computed && (result = {value : value, computed : computed});
  208. });
  209. return result.value;
  210. };
  211. // Return the minimum element (or element-based computation).
  212. _.min = function(obj, iterator, context) {
  213. if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.min.apply(Math, obj);
  214. if (!iterator && _.isEmpty(obj)) return Infinity;
  215. var result = {computed : Infinity};
  216. each(obj, function(value, index, list) {
  217. var computed = iterator ? iterator.call(context, value, index, list) : value;
  218. computed < result.computed && (result = {value : value, computed : computed});
  219. });
  220. return result.value;
  221. };
  222. // Shuffle an array.
  223. _.shuffle = function(obj) {
  224. var shuffled = [], rand;
  225. each(obj, function(value, index, list) {
  226. rand = Math.floor(Math.random() * (index + 1));
  227. shuffled[index] = shuffled[rand];
  228. shuffled[rand] = value;
  229. });
  230. return shuffled;
  231. };
  232. // Sort the object's values by a criterion produced by an iterator.
  233. _.sortBy = function(obj, val, context) {
  234. var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
  235. return _.pluck(_.map(obj, function(value, index, list) {
  236. return {
  237. value : value,
  238. criteria : iterator.call(context, value, index, list)
  239. };
  240. }).sort(function(left, right) {
  241. var a = left.criteria, b = right.criteria;
  242. if (a === void 0) return 1;
  243. if (b === void 0) return -1;
  244. return a < b ? -1 : a > b ? 1 : 0;
  245. }), 'value');
  246. };
  247. // Groups the object's values by a criterion. Pass either a string attribute
  248. // to group by, or a function that returns the criterion.
  249. _.groupBy = function(obj, val) {
  250. var result = {};
  251. var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
  252. each(obj, function(value, index) {
  253. var key = iterator(value, index);
  254. (result[key] || (result[key] = [])).push(value);
  255. });
  256. return result;
  257. };
  258. // Use a comparator function to figure out at what index an object should
  259. // be inserted so as to maintain order. Uses binary search.
  260. _.sortedIndex = function(array, obj, iterator) {
  261. iterator || (iterator = _.identity);
  262. var low = 0, high = array.length;
  263. while (low < high) {
  264. var mid = (low + high) >> 1;
  265. iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
  266. }
  267. return low;
  268. };
  269. // Safely convert anything iterable into a real, live array.
  270. _.toArray = function(obj) {
  271. if (!obj) return [];
  272. if (_.isArray(obj)) return slice.call(obj);
  273. if (_.isArguments(obj)) return slice.call(obj);
  274. if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray();
  275. return _.values(obj);
  276. };
  277. // Return the number of elements in an object.
  278. _.size = function(obj) {
  279. return _.isArray(obj) ? obj.length : _.keys(obj).length;
  280. };
  281. // Array Functions
  282. // ---------------
  283. // Get the first element of an array. Passing **n** will return the first N
  284. // values in the array. Aliased as `head` and `take`. The **guard** check
  285. // allows it to work with `_.map`.
  286. _.first = _.head = _.take = function(array, n, guard) {
  287. return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
  288. };
  289. // Returns everything but the last entry of the array. Especcialy useful on
  290. // the arguments object. Passing **n** will return all the values in
  291. // the array, excluding the last N. The **guard** check allows it to work with
  292. // `_.map`.
  293. _.initial = function(array, n, guard) {
  294. return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
  295. };
  296. // Get the last element of an array. Passing **n** will return the last N
  297. // values in the array. The **guard** check allows it to work with `_.map`.
  298. _.last = function(array, n, guard) {
  299. if ((n != null) && !guard) {
  300. return slice.call(array, Math.max(array.length - n, 0));
  301. } else {
  302. return array[array.length - 1];
  303. }
  304. };
  305. // Returns everything but the first entry of the array. Aliased as `tail`.
  306. // Especially useful on the arguments object. Passing an **index** will return
  307. // the rest of the values in the array from that index onward. The **guard**
  308. // check allows it to work with `_.map`.
  309. _.rest = _.tail = function(array, index, guard) {
  310. return slice.call(array, (index == null) || guard ? 1 : index);
  311. };
  312. // Trim out all falsy values from an array.
  313. _.compact = function(array) {
  314. return _.filter(array, function(value){ return !!value; });
  315. };
  316. // Return a completely flattened version of an array.
  317. _.flatten = function(array, shallow) {
  318. return _.reduce(array, function(memo, value) {
  319. if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
  320. memo[memo.length] = value;
  321. return memo;
  322. }, []);
  323. };
  324. // Return a version of the array that does not contain the specified value(s).
  325. _.without = function(array) {
  326. return _.difference(array, slice.call(arguments, 1));
  327. };
  328. // Produce a duplicate-free version of the array. If the array has already
  329. // been sorted, you have the option of using a faster algorithm.
  330. // Aliased as `unique`.
  331. _.uniq = _.unique = function(array, isSorted, iterator) {
  332. var initial = iterator ? _.map(array, iterator) : array;
  333. var results = [];
  334. // The `isSorted` flag is irrelevant if the array only contains two elements.
  335. if (array.length < 3) isSorted = true;
  336. _.reduce(initial, function (memo, value, index) {
  337. if (isSorted ? _.last(memo) !== value || !memo.length : !_.include(memo, value)) {
  338. memo.push(value);
  339. results.push(array[index]);
  340. }
  341. return memo;
  342. }, []);
  343. return results;
  344. };
  345. // Produce an array that contains the union: each distinct element from all of
  346. // the passed-in arrays.
  347. _.union = function() {
  348. return _.uniq(_.flatten(arguments, true));
  349. };
  350. // Produce an array that contains every item shared between all the
  351. // passed-in arrays. (Aliased as "intersect" for back-compat.)
  352. _.intersection = _.intersect = function(array) {
  353. var rest = slice.call(arguments, 1);
  354. return _.filter(_.uniq(array), function(item) {
  355. return _.every(rest, function(other) {
  356. return _.indexOf(other, item) >= 0;
  357. });
  358. });
  359. };
  360. // Take the difference between one array and a number of other arrays.
  361. // Only the elements present in just the first array will remain.
  362. _.difference = function(array) {
  363. var rest = _.flatten(slice.call(arguments, 1), true);
  364. return _.filter(array, function(value){ return !_.include(rest, value); });
  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. // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
  376. // we need this function. Return the position of the first occurrence of an
  377. // item in an array, or -1 if the item is not included in the array.
  378. // Delegates to **ECMAScript 5**'s native `indexOf` if available.
  379. // If the array is large and already in sort order, pass `true`
  380. // for **isSorted** to use binary search.
  381. _.indexOf = function(array, item, isSorted) {
  382. if (array == null) return -1;
  383. var i, l;
  384. if (isSorted) {
  385. i = _.sortedIndex(array, item);
  386. return array[i] === item ? i : -1;
  387. }
  388. if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
  389. for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
  390. return -1;
  391. };
  392. // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
  393. _.lastIndexOf = function(array, item) {
  394. if (array == null) return -1;
  395. if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
  396. var i = array.length;
  397. while (i--) if (i in array && array[i] === item) return i;
  398. return -1;
  399. };
  400. // Generate an integer Array containing an arithmetic progression. A port of
  401. // the native Python `range()` function. See
  402. // [the Python documentation](http://docs.python.org/library/functions.html#range).
  403. _.range = function(start, stop, step) {
  404. if (arguments.length <= 1) {
  405. stop = start || 0;
  406. start = 0;
  407. }
  408. step = arguments[2] || 1;
  409. var len = Math.max(Math.ceil((stop - start) / step), 0);
  410. var idx = 0;
  411. var range = new Array(len);
  412. while(idx < len) {
  413. range[idx++] = start;
  414. start += step;
  415. }
  416. return range;
  417. };
  418. // Function (ahem) Functions
  419. // ------------------
  420. // Reusable constructor function for prototype setting.
  421. var ctor = function(){};
  422. // Create a function bound to a given object (assigning `this`, and arguments,
  423. // optionally). Binding with arguments is also known as `curry`.
  424. // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
  425. // We check for `func.bind` first, to fail fast when `func` is undefined.
  426. _.bind = function bind(func, context) {
  427. var bound, args;
  428. if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
  429. if (!_.isFunction(func)) throw new TypeError;
  430. args = slice.call(arguments, 2);
  431. return bound = function() {
  432. if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
  433. ctor.prototype = func.prototype;
  434. var self = new ctor;
  435. var result = func.apply(self, args.concat(slice.call(arguments)));
  436. if (Object(result) === result) return result;
  437. return self;
  438. };
  439. };
  440. // Bind all of an object's methods to that object. Useful for ensuring that
  441. // all callbacks defined on an object belong to it.
  442. _.bindAll = function(obj) {
  443. var funcs = slice.call(arguments, 1);
  444. if (funcs.length == 0) funcs = _.functions(obj);
  445. each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
  446. return obj;
  447. };
  448. // Memoize an expensive function by storing its results.
  449. _.memoize = function(func, hasher) {
  450. var memo = {};
  451. hasher || (hasher = _.identity);
  452. return function() {
  453. var key = hasher.apply(this, arguments);
  454. return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
  455. };
  456. };
  457. // Delays a function for the given number of milliseconds, and then calls
  458. // it with the arguments supplied.
  459. _.delay = function(func, wait) {
  460. var args = slice.call(arguments, 2);
  461. return setTimeout(function(){ return func.apply(null, args); }, wait);
  462. };
  463. // Defers a function, scheduling it to run after the current call stack has
  464. // cleared.
  465. _.defer = function(func) {
  466. return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
  467. };
  468. // Returns a function, that, when invoked, will only be triggered at most once
  469. // during a given window of time.
  470. _.throttle = function(func, wait) {
  471. var context, args, timeout, throttling, more, result;
  472. var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
  473. return function() {
  474. context = this; args = arguments;
  475. var later = function() {
  476. timeout = null;
  477. if (more) func.apply(context, args);
  478. whenDone();
  479. };
  480. if (!timeout) timeout = setTimeout(later, wait);
  481. if (throttling) {
  482. more = true;
  483. } else {
  484. result = func.apply(context, args);
  485. }
  486. whenDone();
  487. throttling = true;
  488. return result;
  489. };
  490. };
  491. // Returns a function, that, as long as it continues to be invoked, will not
  492. // be triggered. The function will be called after it stops being called for
  493. // N milliseconds. If `immediate` is passed, trigger the function on the
  494. // leading edge, instead of the trailing.
  495. _.debounce = function(func, wait, immediate) {
  496. var timeout;
  497. return function() {
  498. var context = this, args = arguments;
  499. var later = function() {
  500. timeout = null;
  501. if (!immediate) func.apply(context, args);
  502. };
  503. if (immediate && !timeout) func.apply(context, args);
  504. clearTimeout(timeout);
  505. timeout = setTimeout(later, wait);
  506. };
  507. };
  508. // Returns a function that will be executed at most one time, no matter how
  509. // often you call it. Useful for lazy initialization.
  510. _.once = function(func) {
  511. var ran = false, memo;
  512. return function() {
  513. if (ran) return memo;
  514. ran = true;
  515. return memo = func.apply(this, arguments);
  516. };
  517. };
  518. // Returns the first function passed as an argument to the second,
  519. // allowing you to adjust arguments, run code before and after, and
  520. // conditionally execute the original function.
  521. _.wrap = function(func, wrapper) {
  522. return function() {
  523. var args = [func].concat(slice.call(arguments, 0));
  524. return wrapper.apply(this, args);
  525. };
  526. };
  527. // Returns a function that is the composition of a list of functions, each
  528. // consuming the return value of the function that follows.
  529. _.compose = function() {
  530. var funcs = arguments;
  531. return function() {
  532. var args = arguments;
  533. for (var i = funcs.length - 1; i >= 0; i--) {
  534. args = [funcs[i].apply(this, args)];
  535. }
  536. return args[0];
  537. };
  538. };
  539. // Returns a function that will only be executed after being called N times.
  540. _.after = function(times, func) {
  541. if (times <= 0) return func();
  542. return function() {
  543. if (--times < 1) { return func.apply(this, arguments); }
  544. };
  545. };
  546. // Object Functions
  547. // ----------------
  548. // Retrieve the names of an object's properties.
  549. // Delegates to **ECMAScript 5**'s native `Object.keys`
  550. _.keys = nativeKeys || function(obj) {
  551. if (obj !== Object(obj)) throw new TypeError('Invalid object');
  552. var keys = [];
  553. for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
  554. return keys;
  555. };
  556. // Retrieve the values of an object's properties.
  557. _.values = function(obj) {
  558. return _.map(obj, _.identity);
  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. // Extend a given object with all the properties in passed-in object(s).
  570. _.extend = function(obj) {
  571. each(slice.call(arguments, 1), function(source) {
  572. for (var prop in source) {
  573. obj[prop] = source[prop];
  574. }
  575. });
  576. return obj;
  577. };
  578. // Return a copy of the object only containing the whitelisted properties.
  579. _.pick = function(obj) {
  580. var result = {};
  581. each(_.flatten(slice.call(arguments, 1)), function(key) {
  582. if (key in obj) result[key] = obj[key];
  583. });
  584. return result;
  585. };
  586. // Fill in a given object with default properties.
  587. _.defaults = function(obj) {
  588. each(slice.call(arguments, 1), function(source) {
  589. for (var prop in source) {
  590. if (obj[prop] == null) obj[prop] = source[prop];
  591. }
  592. });
  593. return obj;
  594. };
  595. // Create a (shallow-cloned) duplicate of an object.
  596. _.clone = function(obj) {
  597. if (!_.isObject(obj)) return obj;
  598. return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
  599. };
  600. // Invokes interceptor with the obj, and then returns obj.
  601. // The primary purpose of this method is to "tap into" a method chain, in
  602. // order to perform operations on intermediate results within the chain.
  603. _.tap = function(obj, interceptor) {
  604. interceptor(obj);
  605. return obj;
  606. };
  607. // Internal recursive comparison function.
  608. function eq(a, b, stack) {
  609. // Identical objects are equal. `0 === -0`, but they aren't identical.
  610. // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
  611. if (a === b) return a !== 0 || 1 / a == 1 / b;
  612. // A strict comparison is necessary because `null == undefined`.
  613. if (a == null || b == null) return a === b;
  614. // Unwrap any wrapped objects.
  615. if (a._chain) a = a._wrapped;
  616. if (b._chain) b = b._wrapped;
  617. // Invoke a custom `isEqual` method if one is provided.
  618. if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
  619. if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
  620. // Compare `[[Class]]` names.
  621. var className = toString.call(a);
  622. if (className != toString.call(b)) return false;
  623. switch (className) {
  624. // Strings, numbers, dates, and booleans are compared by value.
  625. case '[object String]':
  626. // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
  627. // equivalent to `new String("5")`.
  628. return a == String(b);
  629. case '[object Number]':
  630. // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
  631. // other numeric values.
  632. return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
  633. case '[object Date]':
  634. case '[object Boolean]':
  635. // Coerce dates and booleans to numeric primitive values. Dates are compared by their
  636. // millisecond representations. Note that invalid dates with millisecond representations
  637. // of `NaN` are not equivalent.
  638. return +a == +b;
  639. // RegExps are compared by their source patterns and flags.
  640. case '[object RegExp]':
  641. return a.source == b.source &&
  642. a.global == b.global &&
  643. a.multiline == b.multiline &&
  644. a.ignoreCase == b.ignoreCase;
  645. }
  646. if (typeof a != 'object' || typeof b != 'object') return false;
  647. // Assume equality for cyclic structures. The algorithm for detecting cyclic
  648. // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
  649. var length = stack.length;
  650. while (length--) {
  651. // Linear search. Performance is inversely proportional to the number of
  652. // unique nested structures.
  653. if (stack[length] == a) return true;
  654. }
  655. // Add the first object to the stack of traversed objects.
  656. stack.push(a);
  657. var size = 0, result = true;
  658. // Recursively compare objects and arrays.
  659. if (className == '[object Array]') {
  660. // Compare array lengths to determine if a deep comparison is necessary.
  661. size = a.length;
  662. result = size == b.length;
  663. if (result) {
  664. // Deep compare the contents, ignoring non-numeric properties.
  665. while (size--) {
  666. // Ensure commutative equality for sparse arrays.
  667. if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
  668. }
  669. }
  670. } else {
  671. // Objects with different constructors are not equivalent.
  672. if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
  673. // Deep compare objects.
  674. for (var key in a) {
  675. if (_.has(a, key)) {
  676. // Count the expected number of properties.
  677. size++;
  678. // Deep compare each member.
  679. if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
  680. }
  681. }
  682. // Ensure that both objects contain the same number of properties.
  683. if (result) {
  684. for (key in b) {
  685. if (_.has(b, key) && !(size--)) break;
  686. }
  687. result = !size;
  688. }
  689. }
  690. // Remove the first object from the stack of traversed objects.
  691. stack.pop();
  692. return result;
  693. }
  694. // Perform a deep comparison to check if two objects are equal.
  695. _.isEqual = function(a, b) {
  696. return eq(a, b, []);
  697. };
  698. // Is a given array, string, or object empty?
  699. // An "empty" object has no enumerable own-properties.
  700. _.isEmpty = function(obj) {
  701. if (obj == null) return true;
  702. if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
  703. for (var key in obj) if (_.has(obj, key)) return false;
  704. return true;
  705. };
  706. // Is a given value a DOM element?
  707. _.isElement = function(obj) {
  708. return !!(obj && obj.nodeType == 1);
  709. };
  710. // Is a given value an array?
  711. // Delegates to ECMA5's native Array.isArray
  712. _.isArray = nativeIsArray || function(obj) {
  713. return toString.call(obj) == '[object Array]';
  714. };
  715. // Is a given variable an object?
  716. _.isObject = function(obj) {
  717. return obj === Object(obj);
  718. };
  719. // Is a given variable an arguments object?
  720. _.isArguments = function(obj) {
  721. return toString.call(obj) == '[object Arguments]';
  722. };
  723. if (!_.isArguments(arguments)) {
  724. _.isArguments = function(obj) {
  725. return !!(obj && _.has(obj, 'callee'));
  726. };
  727. }
  728. // Is a given value a function?
  729. _.isFunction = function(obj) {
  730. return toString.call(obj) == '[object Function]';
  731. };
  732. // Is a given value a string?
  733. _.isString = function(obj) {
  734. return toString.call(obj) == '[object String]';
  735. };
  736. // Is a given value a number?
  737. _.isNumber = function(obj) {
  738. return toString.call(obj) == '[object Number]';
  739. };
  740. // Is a given object a finite number?
  741. _.isFinite = function(obj) {
  742. return _.isNumber(obj) && isFinite(obj);
  743. };
  744. // Is the given value `NaN`?
  745. _.isNaN = function(obj) {
  746. // `NaN` is the only value for which `===` is not reflexive.
  747. return obj !== obj;
  748. };
  749. // Is a given value a boolean?
  750. _.isBoolean = function(obj) {
  751. return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
  752. };
  753. // Is a given value a date?
  754. _.isDate = function(obj) {
  755. return toString.call(obj) == '[object Date]';
  756. };
  757. // Is the given value a regular expression?
  758. _.isRegExp = function(obj) {
  759. return toString.call(obj) == '[object RegExp]';
  760. };
  761. // Is a given value equal to null?
  762. _.isNull = function(obj) {
  763. return obj === null;
  764. };
  765. // Is a given variable undefined?
  766. _.isUndefined = function(obj) {
  767. return obj === void 0;
  768. };
  769. // Has own property?
  770. _.has = function(obj, key) {
  771. return hasOwnProperty.call(obj, key);
  772. };
  773. // Utility Functions
  774. // -----------------
  775. // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
  776. // previous owner. Returns a reference to the Underscore object.
  777. _.noConflict = function() {
  778. root._ = previousUnderscore;
  779. return this;
  780. };
  781. // Keep the identity function around for default iterators.
  782. _.identity = function(value) {
  783. return value;
  784. };
  785. // Run a function **n** times.
  786. _.times = function (n, iterator, context) {
  787. for (var i = 0; i < n; i++) iterator.call(context, i);
  788. };
  789. // Escape a string for HTML interpolation.
  790. _.escape = function(string) {
  791. return (''+string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
  792. };
  793. // If the value of the named property is a function then invoke it;
  794. // otherwise, return it.
  795. _.result = function(object, property) {
  796. if (object == null) return null;
  797. var value = object[property];
  798. return _.isFunction(value) ? value.call(object) : value;
  799. };
  800. // Add your own custom functions to the Underscore object, ensuring that
  801. // they're correctly added to the OOP wrapper as well.
  802. _.mixin = function(obj) {
  803. each(_.functions(obj), function(name){
  804. addToWrapper(name, _[name] = obj[name]);
  805. });
  806. };
  807. // Generate a unique integer id (unique within the entire client session).
  808. // Useful for temporary DOM ids.
  809. var idCounter = 0;
  810. _.uniqueId = function(prefix) {
  811. var id = idCounter++;
  812. return prefix ? prefix + id : id;
  813. };
  814. // By default, Underscore uses ERB-style template delimiters, change the
  815. // following template settings to use alternative delimiters.
  816. _.templateSettings = {
  817. evaluate : /<%([\s\S]+?)%>/g,
  818. interpolate : /<%=([\s\S]+?)%>/g,
  819. escape : /<%-([\s\S]+?)%>/g
  820. };
  821. // When customizing `templateSettings`, if you don't want to define an
  822. // interpolation, evaluation or escaping regex, we need one that is
  823. // guaranteed not to match.
  824. var noMatch = /.^/;
  825. // Certain characters need to be escaped so that they can be put into a
  826. // string literal.
  827. var escapes = {
  828. '\\': '\\',
  829. "'": "'",
  830. 'r': '\r',
  831. 'n': '\n',
  832. 't': '\t',
  833. 'u2028': '\u2028',
  834. 'u2029': '\u2029'
  835. };
  836. for (var p in escapes) escapes[escapes[p]] = p;
  837. var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
  838. var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
  839. // Within an interpolation, evaluation, or escaping, remove HTML escaping
  840. // that had been previously added.
  841. var unescape = function(code) {
  842. return code.replace(unescaper, function(match, escape) {
  843. return escapes[escape];
  844. });
  845. };
  846. // JavaScript micro-templating, similar to John Resig's implementation.
  847. // Underscore templating handles arbitrary delimiters, preserves whitespace,
  848. // and correctly escapes quotes within interpolated code.
  849. _.template = function(text, data, settings) {
  850. settings = _.defaults(settings || {}, _.templateSettings);
  851. // Compile the template source, taking care to escape characters that
  852. // cannot be included in a string literal and then unescape them in code
  853. // blocks.
  854. var source = "__p+='" + text
  855. .replace(escaper, function(match) {
  856. return '\\' + escapes[match];
  857. })
  858. .replace(settings.escape || noMatch, function(match, code) {
  859. return "'+\n_.escape(" + unescape(code) + ")+\n'";
  860. })
  861. .replace(settings.interpolate || noMatch, function(match, code) {
  862. return "'+\n(" + unescape(code) + ")+\n'";
  863. })
  864. .replace(settings.evaluate || noMatch, function(match, code) {
  865. return "';\n" + unescape(code) + "\n;__p+='";
  866. }) + "';\n";
  867. // If a variable is not specified, place data values in local scope.
  868. if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
  869. source = "var __p='';" +
  870. "var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" +
  871. source + "return __p;\n";
  872. var render = new Function(settings.variable || 'obj', '_', source);
  873. if (data) return render(data, _);
  874. var template = function(data) {
  875. return render.call(this, data, _);
  876. };
  877. // Provide the compiled function source as a convenience for build time
  878. // precompilation.
  879. template.source = 'function(' + (settings.variable || 'obj') + '){\n' +
  880. source + '}';
  881. return template;
  882. };
  883. // Add a "chain" function, which will delegate to the wrapper.
  884. _.chain = function(obj) {
  885. return _(obj).chain();
  886. };
  887. // The OOP Wrapper
  888. // ---------------
  889. // If Underscore is called as a function, it returns a wrapped object that
  890. // can be used OO-style. This wrapper holds altered versions of all the
  891. // underscore functions. Wrapped objects may be chained.
  892. var wrapper = function(obj) { this._wrapped = obj; };
  893. // Expose `wrapper.prototype` as `_.prototype`
  894. _.prototype = wrapper.prototype;
  895. // Helper function to continue chaining intermediate results.
  896. var result = function(obj, chain) {
  897. return chain ? _(obj).chain() : obj;
  898. };
  899. // A method to easily add functions to the OOP wrapper.
  900. var addToWrapper = function(name, func) {
  901. wrapper.prototype[name] = function() {
  902. var args = slice.call(arguments);
  903. unshift.call(args, this._wrapped);
  904. return result(func.apply(_, args), this._chain);
  905. };
  906. };
  907. // Add all of the Underscore functions to the wrapper object.
  908. _.mixin(_);
  909. // Add all mutator Array functions to the wrapper.
  910. each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
  911. var method = ArrayProto[name];
  912. wrapper.prototype[name] = function() {
  913. var wrapped = this._wrapped;
  914. method.apply(wrapped, arguments);
  915. var length = wrapped.length;
  916. if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
  917. return result(wrapped, this._chain);
  918. };
  919. });
  920. // Add all accessor Array functions to the wrapper.
  921. each(['concat', 'join', 'slice'], function(name) {
  922. var method = ArrayProto[name];
  923. wrapper.prototype[name] = function() {
  924. return result(method.apply(this._wrapped, arguments), this._chain);
  925. };
  926. });
  927. // Start chaining a wrapped Underscore object.
  928. wrapper.prototype.chain = function() {
  929. this._chain = true;
  930. return this;
  931. };
  932. // Extracts the result from a wrapped and chained object.
  933. wrapper.prototype.value = function() {
  934. return this._wrapped;
  935. };
  936. }).call(this);
  937. _.templateSettings = {
  938. interpolate : /\{\{(.+?)\}\}/g
  939. };