PageRenderTime 32ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/media/foundry/2.1/scripts_/underscore.js

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