PageRenderTime 39ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs//1.4.1/underscore.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 1189 lines | 878 code | 103 blank | 208 comment | 221 complexity | c626b0cd3e76b80f1d228892f41aa658 MD5 | raw file
  1. // Underscore.js 1.4.1
  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.1';
  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, from) {
  466. var hasIndex = from != null;
  467. if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
  468. return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
  469. }
  470. var i = (hasIndex ? from : array.length);
  471. while (i--) if (array[i] === item) return i;
  472. return -1;
  473. };
  474. // Generate an integer Array containing an arithmetic progression. A port of
  475. // the native Python `range()` function. See
  476. // [the Python documentation](http://docs.python.org/library/functions.html#range).
  477. _.range = function(start, stop, step) {
  478. if (arguments.length <= 1) {
  479. stop = start || 0;
  480. start = 0;
  481. }
  482. step = arguments[2] || 1;
  483. var len = Math.max(Math.ceil((stop - start) / step), 0);
  484. var idx = 0;
  485. var range = new Array(len);
  486. while(idx < len) {
  487. range[idx++] = start;
  488. start += step;
  489. }
  490. return range;
  491. };
  492. // Function (ahem) Functions
  493. // ------------------
  494. // Reusable constructor function for prototype setting.
  495. var ctor = function(){};
  496. // Create a function bound to a given object (assigning `this`, and arguments,
  497. // optionally). Binding with arguments is also known as `curry`.
  498. // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
  499. // We check for `func.bind` first, to fail fast when `func` is undefined.
  500. _.bind = function bind(func, context) {
  501. var bound, args;
  502. if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
  503. if (!_.isFunction(func)) throw new TypeError;
  504. args = slice.call(arguments, 2);
  505. return bound = function() {
  506. if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
  507. ctor.prototype = func.prototype;
  508. var self = new ctor;
  509. var result = func.apply(self, args.concat(slice.call(arguments)));
  510. if (Object(result) === result) return result;
  511. return self;
  512. };
  513. };
  514. // Bind all of an object's methods to that object. Useful for ensuring that
  515. // all callbacks defined on an object belong to it.
  516. _.bindAll = function(obj) {
  517. var funcs = slice.call(arguments, 1);
  518. if (funcs.length == 0) funcs = _.functions(obj);
  519. each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
  520. return obj;
  521. };
  522. // Memoize an expensive function by storing its results.
  523. _.memoize = function(func, hasher) {
  524. var memo = {};
  525. hasher || (hasher = _.identity);
  526. return function() {
  527. var key = hasher.apply(this, arguments);
  528. return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
  529. };
  530. };
  531. // Delays a function for the given number of milliseconds, and then calls
  532. // it with the arguments supplied.
  533. _.delay = function(func, wait) {
  534. var args = slice.call(arguments, 2);
  535. return setTimeout(function(){ return func.apply(null, args); }, wait);
  536. };
  537. // Defers a function, scheduling it to run after the current call stack has
  538. // cleared.
  539. _.defer = function(func) {
  540. return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
  541. };
  542. // Returns a function, that, when invoked, will only be triggered at most once
  543. // during a given window of time.
  544. _.throttle = function(func, wait) {
  545. var context, args, timeout, throttling, more, result;
  546. var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
  547. return function() {
  548. context = this; args = arguments;
  549. var later = function() {
  550. timeout = null;
  551. if (more) {
  552. result = func.apply(context, args);
  553. }
  554. whenDone();
  555. };
  556. if (!timeout) timeout = setTimeout(later, wait);
  557. if (throttling) {
  558. more = true;
  559. } else {
  560. throttling = true;
  561. result = func.apply(context, args);
  562. }
  563. whenDone();
  564. return result;
  565. };
  566. };
  567. // Returns a function, that, as long as it continues to be invoked, will not
  568. // be triggered. The function will be called after it stops being called for
  569. // N milliseconds. If `immediate` is passed, trigger the function on the
  570. // leading edge, instead of the trailing.
  571. _.debounce = function(func, wait, immediate) {
  572. var timeout, result;
  573. return function() {
  574. var context = this, args = arguments;
  575. var later = function() {
  576. timeout = null;
  577. if (!immediate) result = func.apply(context, args);
  578. };
  579. var callNow = immediate && !timeout;
  580. clearTimeout(timeout);
  581. timeout = setTimeout(later, wait);
  582. if (callNow) result = func.apply(context, args);
  583. return result;
  584. };
  585. };
  586. // Returns a function that will be executed at most one time, no matter how
  587. // often you call it. Useful for lazy initialization.
  588. _.once = function(func) {
  589. var ran = false, memo;
  590. return function() {
  591. if (ran) return memo;
  592. ran = true;
  593. memo = func.apply(this, arguments);
  594. func = null;
  595. return memo;
  596. };
  597. };
  598. // Returns the first function passed as an argument to the second,
  599. // allowing you to adjust arguments, run code before and after, and
  600. // conditionally execute the original function.
  601. _.wrap = function(func, wrapper) {
  602. return function() {
  603. var args = [func];
  604. push.apply(args, arguments);
  605. return wrapper.apply(this, args);
  606. };
  607. };
  608. // Returns a function that is the composition of a list of functions, each
  609. // consuming the return value of the function that follows.
  610. _.compose = function() {
  611. var funcs = arguments;
  612. return function() {
  613. var args = arguments;
  614. for (var i = funcs.length - 1; i >= 0; i--) {
  615. args = [funcs[i].apply(this, args)];
  616. }
  617. return args[0];
  618. };
  619. };
  620. // Returns a function that will only be executed after being called N times.
  621. _.after = function(times, func) {
  622. if (times <= 0) return func();
  623. return function() {
  624. if (--times < 1) {
  625. return func.apply(this, arguments);
  626. }
  627. };
  628. };
  629. // Object Functions
  630. // ----------------
  631. // Retrieve the names of an object's properties.
  632. // Delegates to **ECMAScript 5**'s native `Object.keys`
  633. _.keys = nativeKeys || function(obj) {
  634. if (obj !== Object(obj)) throw new TypeError('Invalid object');
  635. var keys = [];
  636. for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
  637. return keys;
  638. };
  639. // Retrieve the values of an object's properties.
  640. _.values = function(obj) {
  641. var values = [];
  642. for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
  643. return values;
  644. };
  645. // Convert an object into a list of `[key, value]` pairs.
  646. _.pairs = function(obj) {
  647. var pairs = [];
  648. for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
  649. return pairs;
  650. };
  651. // Invert the keys and values of an object. The values must be serializable.
  652. _.invert = function(obj) {
  653. var result = {};
  654. for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
  655. return result;
  656. };
  657. // Return a sorted list of the function names available on the object.
  658. // Aliased as `methods`
  659. _.functions = _.methods = function(obj) {
  660. var names = [];
  661. for (var key in obj) {
  662. if (_.isFunction(obj[key])) names.push(key);
  663. }
  664. return names.sort();
  665. };
  666. // Extend a given object with all the properties in passed-in object(s).
  667. _.extend = function(obj) {
  668. each(slice.call(arguments, 1), function(source) {
  669. for (var prop in source) {
  670. obj[prop] = source[prop];
  671. }
  672. });
  673. return obj;
  674. };
  675. // Return a copy of the object only containing the whitelisted properties.
  676. _.pick = function(obj) {
  677. var copy = {};
  678. var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
  679. each(keys, function(key) {
  680. if (key in obj) copy[key] = obj[key];
  681. });
  682. return copy;
  683. };
  684. // Return a copy of the object without the blacklisted properties.
  685. _.omit = function(obj) {
  686. var copy = {};
  687. var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
  688. for (var key in obj) {
  689. if (!_.contains(keys, key)) copy[key] = obj[key];
  690. }
  691. return copy;
  692. };
  693. // Fill in a given object with default properties.
  694. _.defaults = function(obj) {
  695. each(slice.call(arguments, 1), function(source) {
  696. for (var prop in source) {
  697. if (obj[prop] == null) obj[prop] = source[prop];
  698. }
  699. });
  700. return obj;
  701. };
  702. // Create a (shallow-cloned) duplicate of an object.
  703. _.clone = function(obj) {
  704. if (!_.isObject(obj)) return obj;
  705. return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
  706. };
  707. // Invokes interceptor with the obj, and then returns obj.
  708. // The primary purpose of this method is to "tap into" a method chain, in
  709. // order to perform operations on intermediate results within the chain.
  710. _.tap = function(obj, interceptor) {
  711. interceptor(obj);
  712. return obj;
  713. };
  714. // Internal recursive comparison function for `isEqual`.
  715. var eq = function(a, b, aStack, bStack) {
  716. // Identical objects are equal. `0 === -0`, but they aren't identical.
  717. // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
  718. if (a === b) return a !== 0 || 1 / a == 1 / b;
  719. // A strict comparison is necessary because `null == undefined`.
  720. if (a == null || b == null) return a === b;
  721. // Unwrap any wrapped objects.
  722. if (a instanceof _) a = a._wrapped;
  723. if (b instanceof _) b = b._wrapped;
  724. // Compare `[[Class]]` names.
  725. var className = toString.call(a);
  726. if (className != toString.call(b)) return false;
  727. switch (className) {
  728. // Strings, numbers, dates, and booleans are compared by value.
  729. case '[object String]':
  730. // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
  731. // equivalent to `new String("5")`.
  732. return a == String(b);
  733. case '[object Number]':
  734. // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
  735. // other numeric values.
  736. return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
  737. case '[object Date]':
  738. case '[object Boolean]':
  739. // Coerce dates and booleans to numeric primitive values. Dates are compared by their
  740. // millisecond representations. Note that invalid dates with millisecond representations
  741. // of `NaN` are not equivalent.
  742. return +a == +b;
  743. // RegExps are compared by their source patterns and flags.
  744. case '[object RegExp]':
  745. return a.source == b.source &&
  746. a.global == b.global &&
  747. a.multiline == b.multiline &&
  748. a.ignoreCase == b.ignoreCase;
  749. }
  750. if (typeof a != 'object' || typeof b != 'object') return false;
  751. // Assume equality for cyclic structures. The algorithm for detecting cyclic
  752. // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
  753. var length = aStack.length;
  754. while (length--) {
  755. // Linear search. Performance is inversely proportional to the number of
  756. // unique nested structures.
  757. if (aStack[length] == a) return bStack[length] == b;
  758. }
  759. // Add the first object to the stack of traversed objects.
  760. aStack.push(a);
  761. bStack.push(b);
  762. var size = 0, result = true;
  763. // Recursively compare objects and arrays.
  764. if (className == '[object Array]') {
  765. // Compare array lengths to determine if a deep comparison is necessary.
  766. size = a.length;
  767. result = size == b.length;
  768. if (result) {
  769. // Deep compare the contents, ignoring non-numeric properties.
  770. while (size--) {
  771. if (!(result = eq(a[size], b[size], aStack, bStack))) break;
  772. }
  773. }
  774. } else {
  775. // Objects with different constructors are not equivalent, but `Object`s
  776. // from different frames are.
  777. var aCtor = a.constructor, bCtor = b.constructor;
  778. if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
  779. _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
  780. return false;
  781. }
  782. // Deep compare objects.
  783. for (var key in a) {
  784. if (_.has(a, key)) {
  785. // Count the expected number of properties.
  786. size++;
  787. // Deep compare each member.
  788. if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
  789. }
  790. }
  791. // Ensure that both objects contain the same number of properties.
  792. if (result) {
  793. for (key in b) {
  794. if (_.has(b, key) && !(size--)) break;
  795. }
  796. result = !size;
  797. }
  798. }
  799. // Remove the first object from the stack of traversed objects.
  800. aStack.pop();
  801. bStack.pop();
  802. return result;
  803. };
  804. // Perform a deep comparison to check if two objects are equal.
  805. _.isEqual = function(a, b) {
  806. return eq(a, b, [], []);
  807. };
  808. // Is a given array, string, or object empty?
  809. // An "empty" object has no enumerable own-properties.
  810. _.isEmpty = function(obj) {
  811. if (obj == null) return true;
  812. if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
  813. for (var key in obj) if (_.has(obj, key)) return false;
  814. return true;
  815. };
  816. // Is a given value a DOM element?
  817. _.isElement = function(obj) {
  818. return !!(obj && obj.nodeType === 1);
  819. };
  820. // Is a given value an array?
  821. // Delegates to ECMA5's native Array.isArray
  822. _.isArray = nativeIsArray || function(obj) {
  823. return toString.call(obj) == '[object Array]';
  824. };
  825. // Is a given variable an object?
  826. _.isObject = function(obj) {
  827. return obj === Object(obj);
  828. };
  829. // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
  830. each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
  831. _['is' + name] = function(obj) {
  832. return toString.call(obj) == '[object ' + name + ']';
  833. };
  834. });
  835. // Define a fallback version of the method in browsers (ahem, IE), where
  836. // there isn't any inspectable "Arguments" type.
  837. if (!_.isArguments(arguments)) {
  838. _.isArguments = function(obj) {
  839. return !!(obj && _.has(obj, 'callee'));
  840. };
  841. }
  842. // Optimize `isFunction` if appropriate.
  843. if (typeof (/./) !== 'function') {
  844. _.isFunction = function(obj) {
  845. return typeof obj === 'function';
  846. };
  847. }
  848. // Is a given object a finite number?
  849. _.isFinite = function(obj) {
  850. return _.isNumber(obj) && isFinite(obj);
  851. };
  852. // Is the given value `NaN`? (NaN is the only number which does not equal itself).
  853. _.isNaN = function(obj) {
  854. return _.isNumber(obj) && obj != +obj;
  855. };
  856. // Is a given value a boolean?
  857. _.isBoolean = function(obj) {
  858. return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
  859. };
  860. // Is a given value equal to null?
  861. _.isNull = function(obj) {
  862. return obj === null;
  863. };
  864. // Is a given variable undefined?
  865. _.isUndefined = function(obj) {
  866. return obj === void 0;
  867. };
  868. // Shortcut function for checking if an object has a given property directly
  869. // on itself (in other words, not on a prototype).
  870. _.has = function(obj, key) {
  871. return hasOwnProperty.call(obj, key);
  872. };
  873. // Utility Functions
  874. // -----------------
  875. // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
  876. // previous owner. Returns a reference to the Underscore object.
  877. _.noConflict = function() {
  878. root._ = previousUnderscore;
  879. return this;
  880. };
  881. // Keep the identity function around for default iterators.
  882. _.identity = function(value) {
  883. return value;
  884. };
  885. // Run a function **n** times.
  886. _.times = function(n, iterator, context) {
  887. for (var i = 0; i < n; i++) iterator.call(context, i);
  888. };
  889. // Return a random integer between min and max (inclusive).
  890. _.random = function(min, max) {
  891. if (max == null) {
  892. max = min;
  893. min = 0;
  894. }
  895. return min + (0 | Math.random() * (max - min + 1));
  896. };
  897. // List of HTML entities for escaping.
  898. var entityMap = {
  899. escape: {
  900. '&': '&amp;',
  901. '<': '&lt;',
  902. '>': '&gt;',
  903. '"': '&quot;',
  904. "'": '&#x27;',
  905. '/': '&#x2F;'
  906. }
  907. };
  908. entityMap.unescape = _.invert(entityMap.escape);
  909. // Regexes containing the keys and values listed immediately above.
  910. var entityRegexes = {
  911. escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
  912. unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
  913. };
  914. // Functions for escaping and unescaping strings to/from HTML interpolation.
  915. _.each(['escape', 'unescape'], function(method) {
  916. _[method] = function(string) {
  917. if (string == null) return '';
  918. return ('' + string).replace(entityRegexes[method], function(match) {
  919. return entityMap[method][match];
  920. });
  921. };
  922. });
  923. // If the value of the named property is a function then invoke it;
  924. // otherwise, return it.
  925. _.result = function(object, property) {
  926. if (object == null) return null;
  927. var value = object[property];
  928. return _.isFunction(value) ? value.call(object) : value;
  929. };
  930. // Add your own custom functions to the Underscore object.
  931. _.mixin = function(obj) {
  932. each(_.functions(obj), function(name){
  933. var func = _[name] = obj[name];
  934. _.prototype[name] = function() {
  935. var args = [this._wrapped];
  936. push.apply(args, arguments);
  937. return result.call(this, func.apply(_, args));
  938. };
  939. });
  940. };
  941. // Generate a unique integer id (unique within the entire client session).
  942. // Useful for temporary DOM ids.
  943. var idCounter = 0;
  944. _.uniqueId = function(prefix) {
  945. var id = idCounter++;
  946. return prefix ? prefix + id : id;
  947. };
  948. // By default, Underscore uses ERB-style template delimiters, change the
  949. // following template settings to use alternative delimiters.
  950. _.templateSettings = {
  951. evaluate : /<%([\s\S]+?)%>/g,
  952. interpolate : /<%=([\s\S]+?)%>/g,
  953. escape : /<%-([\s\S]+?)%>/g
  954. };
  955. // When customizing `templateSettings`, if you don't want to define an
  956. // interpolation, evaluation or escaping regex, we need one that is
  957. // guaranteed not to match.
  958. var noMatch = /(.)^/;
  959. // Certain characters need to be escaped so that they can be put into a
  960. // string literal.
  961. var escapes = {
  962. "'": "'",
  963. '\\': '\\',
  964. '\r': 'r',
  965. '\n': 'n',
  966. '\t': 't',
  967. '\u2028': 'u2028',
  968. '\u2029': 'u2029'
  969. };
  970. var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
  971. // JavaScript micro-templating, similar to John Resig's implementation.
  972. // Underscore templating handles arbitrary delimiters, preserves whitespace,
  973. // and correctly escapes quotes within interpolated code.
  974. _.template = function(text, data, settings) {
  975. settings = _.defaults({}, settings, _.templateSettings);
  976. // Combine delimiters into one regular expression via alternation.
  977. var matcher = new RegExp([
  978. (settings.escape || noMatch).source,
  979. (settings.interpolate || noMatch).source,
  980. (settings.evaluate || noMatch).source
  981. ].join('|') + '|$', 'g');
  982. // Compile the template source, escaping string literals appropriately.
  983. var index = 0;
  984. var source = "__p+='";
  985. text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
  986. source += text.slice(index, offset)
  987. .replace(escaper, function(match) { return '\\' + escapes[match]; });
  988. source +=
  989. escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" :
  990. interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" :
  991. evaluate ? "';\n" + evaluate + "\n__p+='" : '';
  992. index = offset + match.length;
  993. });
  994. source += "';\n";
  995. // If a variable is not specified, place data values in local scope.
  996. if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
  997. source = "var __t,__p='',__j=Array.prototype.join," +
  998. "print=function(){__p+=__j.call(arguments,'');};\n" +
  999. source + "return __p;\n";
  1000. try {
  1001. var render = new Function(settings.variable || 'obj', '_', source);
  1002. } catch (e) {
  1003. e.source = source;
  1004. throw e;
  1005. }
  1006. if (data) return render(data, _);
  1007. var template = function(data) {
  1008. return render.call(this, data, _);
  1009. };
  1010. // Provide the compiled function source as a convenience for precompilation.
  1011. template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
  1012. return template;
  1013. };
  1014. // Add a "chain" function, which will delegate to the wrapper.
  1015. _.chain = function(obj) {
  1016. return _(obj).chain();
  1017. };
  1018. // OOP
  1019. // ---------------
  1020. // If Underscore is called as a function, it returns a wrapped object that
  1021. // can be used OO-style. This wrapper holds altered versions of all the
  1022. // underscore functions. Wrapped objects may be chained.
  1023. // Helper function to continue chaining intermediate results.
  1024. var result = function(obj) {
  1025. return this._chain ? _(obj).chain() : obj;
  1026. };
  1027. // Add all of the Underscore functions to the wrapper object.
  1028. _.mixin(_);
  1029. // Add all mutator Array functions to the wrapper.
  1030. each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
  1031. var method = ArrayProto[name];
  1032. _.prototype[name] = function() {
  1033. var obj = this._wrapped;
  1034. method.apply(obj, arguments);
  1035. if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
  1036. return result.call(this, obj);
  1037. };
  1038. });
  1039. // Add all accessor Array functions to the wrapper.
  1040. each(['concat', 'join', 'slice'], function(name) {
  1041. var method = ArrayProto[name];
  1042. _.prototype[name] = function() {
  1043. return result.call(this, method.apply(this._wrapped, arguments));
  1044. };
  1045. });
  1046. _.extend(_.prototype, {
  1047. // Start chaining a wrapped Underscore object.
  1048. chain: function() {
  1049. this._chain = true;
  1050. return this;
  1051. },
  1052. // Extracts the result from a wrapped and chained object.
  1053. value: function() {
  1054. return this._wrapped;
  1055. }
  1056. });
  1057. }).call(this);