PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs//1.4.0/underscore.js

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