underscore_extensions 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +1 -2
- data/lib/underscore_extensions/version.rb +2 -2
- data/vendor/assets/javascripts/underscore.js +182 -133
- data/vendor/assets/javascripts/underscore.string.js +2 -2
- metadata +19 -36
- data/.rvmrc +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 042a27db5ef9ba1099d77038c102c139bf890af3
|
4
|
+
data.tar.gz: 2ca5ba4ca74be59e61601da701ed50601617d51c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 15f82e7a81c84d4055931acda7030c7acdfbf2c08dc2f518741ccbb5c68111867d8cf0c141272bee39e1b3a8616c562335bdd286c539deee67786ca29af6fd3b
|
7
|
+
data.tar.gz: 8af5584e0d09de5325fad62fb69e6c0f8d9a224ba2da7c48f6a697b16c14c24d9a7995dc1f3d0a48d0ba6806ec085d3686dcd3722a336c3d051aa7361170720a
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
underscore_extensions
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0
|
data/.travis.yml
CHANGED
@@ -1,15 +1,14 @@
|
|
1
|
-
//
|
2
|
-
//
|
1
|
+
// Underscore.js 1.5.2
|
2
|
+
// http://underscorejs.org
|
3
|
+
// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
4
|
+
// Underscore may be freely distributed under the MIT license.
|
3
5
|
|
4
|
-
// > http://underscorejs.org
|
5
|
-
// > (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
|
6
|
-
// > Underscore may be freely distributed under the MIT license.
|
7
|
-
|
8
|
-
// Baseline setup
|
9
|
-
// --------------
|
10
6
|
(function() {
|
11
7
|
|
12
|
-
//
|
8
|
+
// Baseline setup
|
9
|
+
// --------------
|
10
|
+
|
11
|
+
// Establish the root object, `window` in the browser, or `exports` on the server.
|
13
12
|
var root = this;
|
14
13
|
|
15
14
|
// Save the previous value of the `_` variable.
|
@@ -22,27 +21,28 @@
|
|
22
21
|
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
23
22
|
|
24
23
|
// Create quick reference variables for speed access to core prototypes.
|
25
|
-
var
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
var
|
25
|
+
push = ArrayProto.push,
|
26
|
+
slice = ArrayProto.slice,
|
27
|
+
concat = ArrayProto.concat,
|
28
|
+
toString = ObjProto.toString,
|
29
|
+
hasOwnProperty = ObjProto.hasOwnProperty;
|
30
30
|
|
31
31
|
// All **ECMAScript 5** native function implementations that we hope to use
|
32
32
|
// are declared here.
|
33
33
|
var
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
34
|
+
nativeForEach = ArrayProto.forEach,
|
35
|
+
nativeMap = ArrayProto.map,
|
36
|
+
nativeReduce = ArrayProto.reduce,
|
37
|
+
nativeReduceRight = ArrayProto.reduceRight,
|
38
|
+
nativeFilter = ArrayProto.filter,
|
39
|
+
nativeEvery = ArrayProto.every,
|
40
|
+
nativeSome = ArrayProto.some,
|
41
|
+
nativeIndexOf = ArrayProto.indexOf,
|
42
|
+
nativeLastIndexOf = ArrayProto.lastIndexOf,
|
43
|
+
nativeIsArray = Array.isArray,
|
44
|
+
nativeKeys = Object.keys,
|
45
|
+
nativeBind = FuncProto.bind;
|
46
46
|
|
47
47
|
// Create a safe reference to the Underscore object for use below.
|
48
48
|
var _ = function(obj) {
|
@@ -65,7 +65,7 @@
|
|
65
65
|
}
|
66
66
|
|
67
67
|
// Current version.
|
68
|
-
_.VERSION = '1.
|
68
|
+
_.VERSION = '1.5.2';
|
69
69
|
|
70
70
|
// Collection Functions
|
71
71
|
// --------------------
|
@@ -78,14 +78,13 @@
|
|
78
78
|
if (nativeForEach && obj.forEach === nativeForEach) {
|
79
79
|
obj.forEach(iterator, context);
|
80
80
|
} else if (obj.length === +obj.length) {
|
81
|
-
for (var i = 0,
|
81
|
+
for (var i = 0, length = obj.length; i < length; i++) {
|
82
82
|
if (iterator.call(context, obj[i], i, obj) === breaker) return;
|
83
83
|
}
|
84
84
|
} else {
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
}
|
85
|
+
var keys = _.keys(obj);
|
86
|
+
for (var i = 0, length = keys.length; i < length; i++) {
|
87
|
+
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
|
89
88
|
}
|
90
89
|
}
|
91
90
|
};
|
@@ -97,7 +96,7 @@
|
|
97
96
|
if (obj == null) return results;
|
98
97
|
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
99
98
|
each(obj, function(value, index, list) {
|
100
|
-
results
|
99
|
+
results.push(iterator.call(context, value, index, list));
|
101
100
|
});
|
102
101
|
return results;
|
103
102
|
};
|
@@ -172,7 +171,7 @@
|
|
172
171
|
if (obj == null) return results;
|
173
172
|
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
174
173
|
each(obj, function(value, index, list) {
|
175
|
-
if (iterator.call(context, value, index, list)) results
|
174
|
+
if (iterator.call(context, value, index, list)) results.push(value);
|
176
175
|
});
|
177
176
|
return results;
|
178
177
|
};
|
@@ -239,7 +238,7 @@
|
|
239
238
|
// Convenience version of a common use case of `filter`: selecting only objects
|
240
239
|
// containing specific `key:value` pairs.
|
241
240
|
_.where = function(obj, attrs, first) {
|
242
|
-
if (_.isEmpty(attrs)) return first ?
|
241
|
+
if (_.isEmpty(attrs)) return first ? void 0 : [];
|
243
242
|
return _[first ? 'find' : 'filter'](obj, function(value) {
|
244
243
|
for (var key in attrs) {
|
245
244
|
if (attrs[key] !== value[key]) return false;
|
@@ -256,7 +255,7 @@
|
|
256
255
|
|
257
256
|
// Return the maximum element or (element-based computation).
|
258
257
|
// Can't optimize arrays of integers longer than 65,535 elements.
|
259
|
-
// See
|
258
|
+
// See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
|
260
259
|
_.max = function(obj, iterator, context) {
|
261
260
|
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
|
262
261
|
return Math.max.apply(Math, obj);
|
@@ -265,7 +264,7 @@
|
|
265
264
|
var result = {computed : -Infinity, value: -Infinity};
|
266
265
|
each(obj, function(value, index, list) {
|
267
266
|
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
268
|
-
computed
|
267
|
+
computed > result.computed && (result = {value : value, computed : computed});
|
269
268
|
});
|
270
269
|
return result.value;
|
271
270
|
};
|
@@ -284,7 +283,8 @@
|
|
284
283
|
return result.value;
|
285
284
|
};
|
286
285
|
|
287
|
-
// Shuffle an array
|
286
|
+
// Shuffle an array, using the modern version of the
|
287
|
+
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
|
288
288
|
_.shuffle = function(obj) {
|
289
289
|
var rand;
|
290
290
|
var index = 0;
|
@@ -297,6 +297,16 @@
|
|
297
297
|
return shuffled;
|
298
298
|
};
|
299
299
|
|
300
|
+
// Sample **n** random values from an array.
|
301
|
+
// If **n** is not specified, returns a single random element from the array.
|
302
|
+
// The internal `guard` argument allows it to work with `map`.
|
303
|
+
_.sample = function(obj, n, guard) {
|
304
|
+
if (arguments.length < 2 || guard) {
|
305
|
+
return obj[_.random(obj.length - 1)];
|
306
|
+
}
|
307
|
+
return _.shuffle(obj).slice(0, Math.max(0, n));
|
308
|
+
};
|
309
|
+
|
300
310
|
// An internal function to generate lookup iterators.
|
301
311
|
var lookupIterator = function(value) {
|
302
312
|
return _.isFunction(value) ? value : function(obj){ return obj[value]; };
|
@@ -307,49 +317,52 @@
|
|
307
317
|
var iterator = lookupIterator(value);
|
308
318
|
return _.pluck(_.map(obj, function(value, index, list) {
|
309
319
|
return {
|
310
|
-
value
|
311
|
-
index
|
312
|
-
criteria
|
320
|
+
value: value,
|
321
|
+
index: index,
|
322
|
+
criteria: iterator.call(context, value, index, list)
|
313
323
|
};
|
314
324
|
}).sort(function(left, right) {
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
325
|
+
var a = left.criteria;
|
326
|
+
var b = right.criteria;
|
327
|
+
if (a !== b) {
|
328
|
+
if (a > b || a === void 0) return 1;
|
329
|
+
if (a < b || b === void 0) return -1;
|
330
|
+
}
|
331
|
+
return left.index - right.index;
|
332
|
+
}), 'value');
|
323
333
|
};
|
324
334
|
|
325
335
|
// An internal function used for aggregate "group by" operations.
|
326
|
-
var group = function(
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
336
|
+
var group = function(behavior) {
|
337
|
+
return function(obj, value, context) {
|
338
|
+
var result = {};
|
339
|
+
var iterator = value == null ? _.identity : lookupIterator(value);
|
340
|
+
each(obj, function(value, index) {
|
341
|
+
var key = iterator.call(context, value, index, obj);
|
342
|
+
behavior(result, key, value);
|
343
|
+
});
|
344
|
+
return result;
|
345
|
+
};
|
334
346
|
};
|
335
347
|
|
336
348
|
// Groups the object's values by a criterion. Pass either a string attribute
|
337
349
|
// to group by, or a function that returns the criterion.
|
338
|
-
_.groupBy = function(
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
350
|
+
_.groupBy = group(function(result, key, value) {
|
351
|
+
(_.has(result, key) ? result[key] : (result[key] = [])).push(value);
|
352
|
+
});
|
353
|
+
|
354
|
+
// Indexes the object's values by a criterion, similar to `groupBy`, but for
|
355
|
+
// when you know that your index values will be unique.
|
356
|
+
_.indexBy = group(function(result, key, value) {
|
357
|
+
result[key] = value;
|
358
|
+
});
|
343
359
|
|
344
360
|
// Counts instances of an object that group by a certain criterion. Pass
|
345
361
|
// either a string attribute to count by, or a function that returns the
|
346
362
|
// criterion.
|
347
|
-
_.countBy = function(
|
348
|
-
|
349
|
-
|
350
|
-
result[key]++;
|
351
|
-
});
|
352
|
-
};
|
363
|
+
_.countBy = group(function(result, key) {
|
364
|
+
_.has(result, key) ? result[key]++ : result[key] = 1;
|
365
|
+
});
|
353
366
|
|
354
367
|
// Use a comparator function to figure out the smallest index at which
|
355
368
|
// an object should be inserted so as to maintain order. Uses binary search.
|
@@ -364,7 +377,7 @@
|
|
364
377
|
return low;
|
365
378
|
};
|
366
379
|
|
367
|
-
// Safely
|
380
|
+
// Safely create a real, live array from anything iterable.
|
368
381
|
_.toArray = function(obj) {
|
369
382
|
if (!obj) return [];
|
370
383
|
if (_.isArray(obj)) return slice.call(obj);
|
@@ -386,7 +399,7 @@
|
|
386
399
|
// allows it to work with `_.map`.
|
387
400
|
_.first = _.head = _.take = function(array, n, guard) {
|
388
401
|
if (array == null) return void 0;
|
389
|
-
return (n
|
402
|
+
return (n == null) || guard ? array[0] : slice.call(array, 0, n);
|
390
403
|
};
|
391
404
|
|
392
405
|
// Returns everything but the last entry of the array. Especially useful on
|
@@ -401,10 +414,10 @@
|
|
401
414
|
// values in the array. The **guard** check allows it to work with `_.map`.
|
402
415
|
_.last = function(array, n, guard) {
|
403
416
|
if (array == null) return void 0;
|
404
|
-
if ((n
|
405
|
-
return slice.call(array, Math.max(array.length - n, 0));
|
406
|
-
} else {
|
417
|
+
if ((n == null) || guard) {
|
407
418
|
return array[array.length - 1];
|
419
|
+
} else {
|
420
|
+
return slice.call(array, Math.max(array.length - n, 0));
|
408
421
|
}
|
409
422
|
};
|
410
423
|
|
@@ -423,8 +436,11 @@
|
|
423
436
|
|
424
437
|
// Internal implementation of a recursive `flatten` function.
|
425
438
|
var flatten = function(input, shallow, output) {
|
439
|
+
if (shallow && _.every(input, _.isArray)) {
|
440
|
+
return concat.apply(output, input);
|
441
|
+
}
|
426
442
|
each(input, function(value) {
|
427
|
-
if (_.isArray(value)) {
|
443
|
+
if (_.isArray(value) || _.isArguments(value)) {
|
428
444
|
shallow ? push.apply(output, value) : flatten(value, shallow, output);
|
429
445
|
} else {
|
430
446
|
output.push(value);
|
@@ -433,7 +449,7 @@
|
|
433
449
|
return output;
|
434
450
|
};
|
435
451
|
|
436
|
-
//
|
452
|
+
// Flatten out an array, either recursively (by default), or just one level.
|
437
453
|
_.flatten = function(array, shallow) {
|
438
454
|
return flatten(array, shallow, []);
|
439
455
|
};
|
@@ -467,7 +483,7 @@
|
|
467
483
|
// Produce an array that contains the union: each distinct element from all of
|
468
484
|
// the passed-in arrays.
|
469
485
|
_.union = function() {
|
470
|
-
return _.uniq(
|
486
|
+
return _.uniq(_.flatten(arguments, true));
|
471
487
|
};
|
472
488
|
|
473
489
|
// Produce an array that contains every item shared between all the
|
@@ -491,11 +507,10 @@
|
|
491
507
|
// Zip together multiple lists into a single array -- elements that share
|
492
508
|
// an index go together.
|
493
509
|
_.zip = function() {
|
494
|
-
var
|
495
|
-
var length = _.max(_.pluck(args, 'length'));
|
510
|
+
var length = _.max(_.pluck(arguments, "length").concat(0));
|
496
511
|
var results = new Array(length);
|
497
512
|
for (var i = 0; i < length; i++) {
|
498
|
-
results[i] = _.pluck(
|
513
|
+
results[i] = _.pluck(arguments, '' + i);
|
499
514
|
}
|
500
515
|
return results;
|
501
516
|
};
|
@@ -506,7 +521,7 @@
|
|
506
521
|
_.object = function(list, values) {
|
507
522
|
if (list == null) return {};
|
508
523
|
var result = {};
|
509
|
-
for (var i = 0,
|
524
|
+
for (var i = 0, length = list.length; i < length; i++) {
|
510
525
|
if (values) {
|
511
526
|
result[list[i]] = values[i];
|
512
527
|
} else {
|
@@ -524,17 +539,17 @@
|
|
524
539
|
// for **isSorted** to use binary search.
|
525
540
|
_.indexOf = function(array, item, isSorted) {
|
526
541
|
if (array == null) return -1;
|
527
|
-
var i = 0,
|
542
|
+
var i = 0, length = array.length;
|
528
543
|
if (isSorted) {
|
529
544
|
if (typeof isSorted == 'number') {
|
530
|
-
i = (isSorted < 0 ? Math.max(0,
|
545
|
+
i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
|
531
546
|
} else {
|
532
547
|
i = _.sortedIndex(array, item);
|
533
548
|
return array[i] === item ? i : -1;
|
534
549
|
}
|
535
550
|
}
|
536
551
|
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
|
537
|
-
for (; i <
|
552
|
+
for (; i < length; i++) if (array[i] === item) return i;
|
538
553
|
return -1;
|
539
554
|
};
|
540
555
|
|
@@ -560,11 +575,11 @@
|
|
560
575
|
}
|
561
576
|
step = arguments[2] || 1;
|
562
577
|
|
563
|
-
var
|
578
|
+
var length = Math.max(Math.ceil((stop - start) / step), 0);
|
564
579
|
var idx = 0;
|
565
|
-
var range = new Array(
|
580
|
+
var range = new Array(length);
|
566
581
|
|
567
|
-
while(idx <
|
582
|
+
while(idx < length) {
|
568
583
|
range[idx++] = start;
|
569
584
|
start += step;
|
570
585
|
}
|
@@ -575,14 +590,25 @@
|
|
575
590
|
// Function (ahem) Functions
|
576
591
|
// ------------------
|
577
592
|
|
593
|
+
// Reusable constructor function for prototype setting.
|
594
|
+
var ctor = function(){};
|
595
|
+
|
578
596
|
// Create a function bound to a given object (assigning `this`, and arguments,
|
579
597
|
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
|
580
598
|
// available.
|
581
599
|
_.bind = function(func, context) {
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
600
|
+
var args, bound;
|
601
|
+
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
602
|
+
if (!_.isFunction(func)) throw new TypeError;
|
603
|
+
args = slice.call(arguments, 2);
|
604
|
+
return bound = function() {
|
605
|
+
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
|
606
|
+
ctor.prototype = func.prototype;
|
607
|
+
var self = new ctor;
|
608
|
+
ctor.prototype = null;
|
609
|
+
var result = func.apply(self, args.concat(slice.call(arguments)));
|
610
|
+
if (Object(result) === result) return result;
|
611
|
+
return self;
|
586
612
|
};
|
587
613
|
};
|
588
614
|
|
@@ -599,7 +625,7 @@
|
|
599
625
|
// all callbacks defined on an object belong to it.
|
600
626
|
_.bindAll = function(obj) {
|
601
627
|
var funcs = slice.call(arguments, 1);
|
602
|
-
if (funcs.length === 0)
|
628
|
+
if (funcs.length === 0) throw new Error("bindAll must be passed function names");
|
603
629
|
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
604
630
|
return obj;
|
605
631
|
};
|
@@ -628,17 +654,23 @@
|
|
628
654
|
};
|
629
655
|
|
630
656
|
// Returns a function, that, when invoked, will only be triggered at most once
|
631
|
-
// during a given window of time.
|
632
|
-
|
633
|
-
|
657
|
+
// during a given window of time. Normally, the throttled function will run
|
658
|
+
// as much as it can, without ever going more than once per `wait` duration;
|
659
|
+
// but if you'd like to disable the execution on the leading edge, pass
|
660
|
+
// `{leading: false}`. To disable execution on the trailing edge, ditto.
|
661
|
+
_.throttle = function(func, wait, options) {
|
662
|
+
var context, args, result;
|
663
|
+
var timeout = null;
|
634
664
|
var previous = 0;
|
665
|
+
options || (options = {});
|
635
666
|
var later = function() {
|
636
|
-
previous = new Date;
|
667
|
+
previous = options.leading === false ? 0 : new Date;
|
637
668
|
timeout = null;
|
638
669
|
result = func.apply(context, args);
|
639
670
|
};
|
640
671
|
return function() {
|
641
672
|
var now = new Date;
|
673
|
+
if (!previous && options.leading === false) previous = now;
|
642
674
|
var remaining = wait - (now - previous);
|
643
675
|
context = this;
|
644
676
|
args = arguments;
|
@@ -647,7 +679,7 @@
|
|
647
679
|
timeout = null;
|
648
680
|
previous = now;
|
649
681
|
result = func.apply(context, args);
|
650
|
-
} else if (!timeout) {
|
682
|
+
} else if (!timeout && options.trailing !== false) {
|
651
683
|
timeout = setTimeout(later, remaining);
|
652
684
|
}
|
653
685
|
return result;
|
@@ -659,16 +691,24 @@
|
|
659
691
|
// N milliseconds. If `immediate` is passed, trigger the function on the
|
660
692
|
// leading edge, instead of the trailing.
|
661
693
|
_.debounce = function(func, wait, immediate) {
|
662
|
-
var timeout, result;
|
694
|
+
var timeout, args, context, timestamp, result;
|
663
695
|
return function() {
|
664
|
-
|
696
|
+
context = this;
|
697
|
+
args = arguments;
|
698
|
+
timestamp = new Date();
|
665
699
|
var later = function() {
|
666
|
-
|
667
|
-
if (
|
700
|
+
var last = (new Date()) - timestamp;
|
701
|
+
if (last < wait) {
|
702
|
+
timeout = setTimeout(later, wait - last);
|
703
|
+
} else {
|
704
|
+
timeout = null;
|
705
|
+
if (!immediate) result = func.apply(context, args);
|
706
|
+
}
|
668
707
|
};
|
669
708
|
var callNow = immediate && !timeout;
|
670
|
-
|
671
|
-
|
709
|
+
if (!timeout) {
|
710
|
+
timeout = setTimeout(later, wait);
|
711
|
+
}
|
672
712
|
if (callNow) result = func.apply(context, args);
|
673
713
|
return result;
|
674
714
|
};
|
@@ -713,7 +753,6 @@
|
|
713
753
|
|
714
754
|
// Returns a function that will only be executed after being called N times.
|
715
755
|
_.after = function(times, func) {
|
716
|
-
if (times <= 0) return func();
|
717
756
|
return function() {
|
718
757
|
if (--times < 1) {
|
719
758
|
return func.apply(this, arguments);
|
@@ -729,28 +768,39 @@
|
|
729
768
|
_.keys = nativeKeys || function(obj) {
|
730
769
|
if (obj !== Object(obj)) throw new TypeError('Invalid object');
|
731
770
|
var keys = [];
|
732
|
-
for (var key in obj) if (_.has(obj, key)) keys
|
771
|
+
for (var key in obj) if (_.has(obj, key)) keys.push(key);
|
733
772
|
return keys;
|
734
773
|
};
|
735
774
|
|
736
775
|
// Retrieve the values of an object's properties.
|
737
776
|
_.values = function(obj) {
|
738
|
-
var
|
739
|
-
|
777
|
+
var keys = _.keys(obj);
|
778
|
+
var length = keys.length;
|
779
|
+
var values = new Array(length);
|
780
|
+
for (var i = 0; i < length; i++) {
|
781
|
+
values[i] = obj[keys[i]];
|
782
|
+
}
|
740
783
|
return values;
|
741
784
|
};
|
742
785
|
|
743
786
|
// Convert an object into a list of `[key, value]` pairs.
|
744
787
|
_.pairs = function(obj) {
|
745
|
-
var
|
746
|
-
|
788
|
+
var keys = _.keys(obj);
|
789
|
+
var length = keys.length;
|
790
|
+
var pairs = new Array(length);
|
791
|
+
for (var i = 0; i < length; i++) {
|
792
|
+
pairs[i] = [keys[i], obj[keys[i]]];
|
793
|
+
}
|
747
794
|
return pairs;
|
748
795
|
};
|
749
796
|
|
750
797
|
// Invert the keys and values of an object. The values must be serializable.
|
751
798
|
_.invert = function(obj) {
|
752
799
|
var result = {};
|
753
|
-
|
800
|
+
var keys = _.keys(obj);
|
801
|
+
for (var i = 0, length = keys.length; i < length; i++) {
|
802
|
+
result[obj[keys[i]]] = keys[i];
|
803
|
+
}
|
754
804
|
return result;
|
755
805
|
};
|
756
806
|
|
@@ -786,7 +836,7 @@
|
|
786
836
|
return copy;
|
787
837
|
};
|
788
838
|
|
789
|
-
|
839
|
+
// Return a copy of the object without the blacklisted properties.
|
790
840
|
_.omit = function(obj) {
|
791
841
|
var copy = {};
|
792
842
|
var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
|
@@ -801,7 +851,7 @@
|
|
801
851
|
each(slice.call(arguments, 1), function(source) {
|
802
852
|
if (source) {
|
803
853
|
for (var prop in source) {
|
804
|
-
if (obj[prop]
|
854
|
+
if (obj[prop] === void 0) obj[prop] = source[prop];
|
805
855
|
}
|
806
856
|
}
|
807
857
|
});
|
@@ -825,7 +875,7 @@
|
|
825
875
|
// Internal recursive comparison function for `isEqual`.
|
826
876
|
var eq = function(a, b, aStack, bStack) {
|
827
877
|
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
828
|
-
// See the Harmony `egal` proposal
|
878
|
+
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
|
829
879
|
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
830
880
|
// A strict comparison is necessary because `null == undefined`.
|
831
881
|
if (a == null || b == null) return a === b;
|
@@ -854,9 +904,9 @@
|
|
854
904
|
// RegExps are compared by their source patterns and flags.
|
855
905
|
case '[object RegExp]':
|
856
906
|
return a.source == b.source &&
|
857
|
-
|
858
|
-
|
859
|
-
|
907
|
+
a.global == b.global &&
|
908
|
+
a.multiline == b.multiline &&
|
909
|
+
a.ignoreCase == b.ignoreCase;
|
860
910
|
}
|
861
911
|
if (typeof a != 'object' || typeof b != 'object') return false;
|
862
912
|
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
@@ -867,6 +917,13 @@
|
|
867
917
|
// unique nested structures.
|
868
918
|
if (aStack[length] == a) return bStack[length] == b;
|
869
919
|
}
|
920
|
+
// Objects with different constructors are not equivalent, but `Object`s
|
921
|
+
// from different frames are.
|
922
|
+
var aCtor = a.constructor, bCtor = b.constructor;
|
923
|
+
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
|
924
|
+
_.isFunction(bCtor) && (bCtor instanceof bCtor))) {
|
925
|
+
return false;
|
926
|
+
}
|
870
927
|
// Add the first object to the stack of traversed objects.
|
871
928
|
aStack.push(a);
|
872
929
|
bStack.push(b);
|
@@ -883,13 +940,6 @@
|
|
883
940
|
}
|
884
941
|
}
|
885
942
|
} else {
|
886
|
-
// Objects with different constructors are not equivalent, but `Object`s
|
887
|
-
// from different frames are.
|
888
|
-
var aCtor = a.constructor, bCtor = b.constructor;
|
889
|
-
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
|
890
|
-
_.isFunction(bCtor) && (bCtor instanceof bCtor))) {
|
891
|
-
return false;
|
892
|
-
}
|
893
943
|
// Deep compare objects.
|
894
944
|
for (var key in a) {
|
895
945
|
if (_.has(a, key)) {
|
@@ -1013,7 +1063,7 @@
|
|
1013
1063
|
|
1014
1064
|
// Run a function **n** times.
|
1015
1065
|
_.times = function(n, iterator, context) {
|
1016
|
-
var accum = Array(n);
|
1066
|
+
var accum = Array(Math.max(0, n));
|
1017
1067
|
for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
|
1018
1068
|
return accum;
|
1019
1069
|
};
|
@@ -1034,8 +1084,7 @@
|
|
1034
1084
|
'<': '<',
|
1035
1085
|
'>': '>',
|
1036
1086
|
'"': '"',
|
1037
|
-
"'": '''
|
1038
|
-
'/': '/'
|
1087
|
+
"'": '''
|
1039
1088
|
}
|
1040
1089
|
};
|
1041
1090
|
entityMap.unescape = _.invert(entityMap.escape);
|
@@ -1056,17 +1105,17 @@
|
|
1056
1105
|
};
|
1057
1106
|
});
|
1058
1107
|
|
1059
|
-
// If the value of the named property is a function then invoke it
|
1060
|
-
// otherwise, return it.
|
1108
|
+
// If the value of the named `property` is a function then invoke it with the
|
1109
|
+
// `object` as context; otherwise, return it.
|
1061
1110
|
_.result = function(object, property) {
|
1062
|
-
if (object == null) return
|
1111
|
+
if (object == null) return void 0;
|
1063
1112
|
var value = object[property];
|
1064
1113
|
return _.isFunction(value) ? value.call(object) : value;
|
1065
1114
|
};
|
1066
1115
|
|
1067
1116
|
// Add your own custom functions to the Underscore object.
|
1068
1117
|
_.mixin = function(obj) {
|
1069
|
-
each(_.functions(obj), function(name){
|
1118
|
+
each(_.functions(obj), function(name) {
|
1070
1119
|
var func = _[name] = obj[name];
|
1071
1120
|
_.prototype[name] = function() {
|
1072
1121
|
var args = [this._wrapped];
|
@@ -1130,7 +1179,7 @@
|
|
1130
1179
|
var source = "__p+='";
|
1131
1180
|
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
1132
1181
|
source += text.slice(index, offset)
|
1133
|
-
|
1182
|
+
.replace(escaper, function(match) { return '\\' + escapes[match]; });
|
1134
1183
|
|
1135
1184
|
if (escape) {
|
1136
1185
|
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
|
@@ -1150,8 +1199,8 @@
|
|
1150
1199
|
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
|
1151
1200
|
|
1152
1201
|
source = "var __t,__p='',__j=Array.prototype.join," +
|
1153
|
-
|
1154
|
-
|
1202
|
+
"print=function(){__p+=__j.call(arguments,'');};\n" +
|
1203
|
+
source + "return __p;\n";
|
1155
1204
|
|
1156
1205
|
try {
|
1157
1206
|
render = new Function(settings.variable || 'obj', '_', source);
|
@@ -1224,4 +1273,4 @@
|
|
1224
1273
|
|
1225
1274
|
});
|
1226
1275
|
|
1227
|
-
}).call(this);
|
1276
|
+
}).call(this);
|
@@ -494,7 +494,7 @@
|
|
494
494
|
slugify: function(str) {
|
495
495
|
if (str == null) return '';
|
496
496
|
|
497
|
-
var from = "
|
497
|
+
var from = "ąàáäâãåæćęèéëêìíïîłńòóöôõøùúüûñçżź",
|
498
498
|
to = "aaaaaaaaceeeeeiiiilnoooooouuuunczz",
|
499
499
|
regex = new RegExp(defaultToWhiteSpace(from), 'g');
|
500
500
|
|
@@ -597,4 +597,4 @@
|
|
597
597
|
root._.string = root._.str = _s;
|
598
598
|
}
|
599
599
|
|
600
|
-
}(this, String);
|
600
|
+
}(this, String);
|
metadata
CHANGED
@@ -1,94 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: underscore_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.5
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Ryan Dy
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-01-23 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: fuubar
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: jasmine
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: 1.3.2
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: 1.3.2
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: jshint_on_rails
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: thin
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - '>='
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - '>='
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: rails
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - '>='
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '3.1'
|
86
76
|
type: :runtime
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - '>='
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '3.1'
|
94
83
|
description: Adds extensions to the underscore javascript library. It adds the javascript
|
@@ -101,7 +90,8 @@ extensions: []
|
|
101
90
|
extra_rdoc_files: []
|
102
91
|
files:
|
103
92
|
- .gitignore
|
104
|
-
- .
|
93
|
+
- .ruby-gemset
|
94
|
+
- .ruby-version
|
105
95
|
- .travis.yml
|
106
96
|
- Gemfile
|
107
97
|
- README.markdown
|
@@ -119,33 +109,26 @@ files:
|
|
119
109
|
- vendor/assets/javascripts/underscore.string.js
|
120
110
|
homepage: http://github.com/rdy/underscore_extensions
|
121
111
|
licenses: []
|
112
|
+
metadata: {}
|
122
113
|
post_install_message:
|
123
114
|
rdoc_options: []
|
124
115
|
require_paths:
|
125
116
|
- lib
|
126
117
|
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
-
none: false
|
128
118
|
requirements:
|
129
|
-
- -
|
119
|
+
- - '>='
|
130
120
|
- !ruby/object:Gem::Version
|
131
121
|
version: '0'
|
132
|
-
segments:
|
133
|
-
- 0
|
134
|
-
hash: 1293456751333068915
|
135
122
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
-
none: false
|
137
123
|
requirements:
|
138
|
-
- -
|
124
|
+
- - '>='
|
139
125
|
- !ruby/object:Gem::Version
|
140
126
|
version: '0'
|
141
|
-
segments:
|
142
|
-
- 0
|
143
|
-
hash: 1293456751333068915
|
144
127
|
requirements: []
|
145
128
|
rubyforge_project: underscore_extensions
|
146
|
-
rubygems_version:
|
129
|
+
rubygems_version: 2.2.1
|
147
130
|
signing_key:
|
148
|
-
specification_version:
|
131
|
+
specification_version: 4
|
149
132
|
summary: Extensions to underscore javascript library as a rails engine
|
150
133
|
test_files:
|
151
134
|
- spec/javascripts/support/jasmine.yml
|
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm 1.9.3@underscore_extensions --create
|