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