underscore-source 0.1.1 → 0.2.0
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.
- data/lib/underscore-source/version.rb +1 -1
- data/vendor/assets/javascripts/underscore.js +133 -99
- metadata +1 -1
@@ -5,17 +5,22 @@
|
|
5
5
|
// Oliver Steele's Functional, And John Resig's Micro-Templating.
|
6
6
|
// For all details and documentation:
|
7
7
|
// http://documentcloud.github.com/underscore/
|
8
|
-
|
8
|
+
|
9
|
+
(function() {
|
10
|
+
|
11
|
+
var root = (typeof window != 'undefined') ? window : exports;
|
9
12
|
|
10
|
-
|
13
|
+
var previousUnderscore = root._;
|
11
14
|
|
12
|
-
|
15
|
+
var _ = root._ = {};
|
13
16
|
|
17
|
+
_.VERSION = '0.2.0';
|
18
|
+
|
14
19
|
/*------------------------ Collection Functions: ---------------------------*/
|
15
20
|
|
16
21
|
// The cornerstone, an each implementation.
|
17
22
|
// Handles objects implementing forEach, each, arrays, and raw objects.
|
18
|
-
each
|
23
|
+
_.each = function(obj, iterator, context) {
|
19
24
|
var index = 0;
|
20
25
|
try {
|
21
26
|
if (obj.forEach) {
|
@@ -37,30 +42,30 @@ window.Underscore = {
|
|
37
42
|
if (e != '__break__') throw e;
|
38
43
|
}
|
39
44
|
return obj;
|
40
|
-
}
|
45
|
+
};
|
41
46
|
|
42
47
|
// Return the results of applying the iterator to each element. Use Javascript
|
43
48
|
// 1.6's version of map, if possible.
|
44
|
-
map
|
49
|
+
_.map = function(obj, iterator, context) {
|
45
50
|
if (obj && obj.map) return obj.map(iterator, context);
|
46
51
|
var results = [];
|
47
52
|
_.each(obj, function(value, index) {
|
48
53
|
results.push(iterator.call(context, value, index));
|
49
54
|
});
|
50
55
|
return results;
|
51
|
-
}
|
56
|
+
};
|
52
57
|
|
53
|
-
//
|
54
|
-
//
|
55
|
-
|
58
|
+
// Reduce builds up a single result from a list of values. Also known as
|
59
|
+
// inject, or foldl.
|
60
|
+
_.reduce = function(obj, memo, iterator, context) {
|
56
61
|
_.each(obj, function(value, index) {
|
57
62
|
memo = iterator.call(context, memo, value, index);
|
58
63
|
});
|
59
64
|
return memo;
|
60
|
-
}
|
65
|
+
};
|
61
66
|
|
62
67
|
// Return the first value which passes a truth test.
|
63
|
-
detect
|
68
|
+
_.detect = function(obj, iterator, context) {
|
64
69
|
var result;
|
65
70
|
_.each(obj, function(value, index) {
|
66
71
|
if (iterator.call(context, value, index)) {
|
@@ -69,31 +74,31 @@ window.Underscore = {
|
|
69
74
|
}
|
70
75
|
});
|
71
76
|
return result;
|
72
|
-
}
|
77
|
+
};
|
73
78
|
|
74
79
|
// Return all the elements that pass a truth test. Use Javascript 1.6's
|
75
80
|
// filter(), if it exists.
|
76
|
-
select
|
81
|
+
_.select = function(obj, iterator, context) {
|
77
82
|
if (obj.filter) return obj.filter(iterator, context);
|
78
83
|
var results = [];
|
79
84
|
_.each(obj, function(value, index) {
|
80
85
|
if (iterator.call(context, value, index)) results.push(value);
|
81
86
|
});
|
82
87
|
return results;
|
83
|
-
}
|
88
|
+
};
|
84
89
|
|
85
90
|
// Return all the elements for which a truth test fails.
|
86
|
-
reject
|
91
|
+
_.reject = function(obj, iterator, context) {
|
87
92
|
var results = [];
|
88
93
|
_.each(obj, function(value, index) {
|
89
94
|
if (!iterator.call(context, value, index)) results.push(value);
|
90
95
|
});
|
91
96
|
return results;
|
92
|
-
}
|
97
|
+
};
|
93
98
|
|
94
99
|
// Determine whether all of the elements match a truth test. Delegate to
|
95
100
|
// Javascript 1.6's every(), if it is present.
|
96
|
-
all
|
101
|
+
_.all = function(obj, iterator, context) {
|
97
102
|
iterator = iterator || function(v){ return v; };
|
98
103
|
if (obj.every) return obj.every(iterator, context);
|
99
104
|
var result = true;
|
@@ -102,11 +107,11 @@ window.Underscore = {
|
|
102
107
|
if (!result) throw '__break__';
|
103
108
|
});
|
104
109
|
return result;
|
105
|
-
}
|
110
|
+
};
|
106
111
|
|
107
112
|
// Determine if at least one element in the object matches a truth test. Use
|
108
113
|
// Javascript 1.6's some(), if it exists.
|
109
|
-
any
|
114
|
+
_.any = function(obj, iterator, context) {
|
110
115
|
iterator = iterator || function(v) { return v; };
|
111
116
|
if (obj.some) return obj.some(iterator, context);
|
112
117
|
var result = false;
|
@@ -114,11 +119,11 @@ window.Underscore = {
|
|
114
119
|
if (result = !!iterator.call(context, value, index)) throw '__break__';
|
115
120
|
});
|
116
121
|
return result;
|
117
|
-
}
|
122
|
+
};
|
118
123
|
|
119
124
|
// Determine if a given value is included in the array or object,
|
120
125
|
// based on '==='.
|
121
|
-
include
|
126
|
+
_.include = function(obj, target) {
|
122
127
|
if (_.isArray(obj)) return _.indexOf(obj, target) != -1;
|
123
128
|
var found = false;
|
124
129
|
_.each(obj, function(pair) {
|
@@ -128,25 +133,25 @@ window.Underscore = {
|
|
128
133
|
}
|
129
134
|
});
|
130
135
|
return found;
|
131
|
-
}
|
136
|
+
};
|
132
137
|
|
133
138
|
// Invoke a method with arguments on every item in a collection.
|
134
|
-
invoke
|
139
|
+
_.invoke = function(obj, method) {
|
135
140
|
var args = _.toArray(arguments).slice(2);
|
136
141
|
return _.map(obj, function(value) {
|
137
142
|
return (method ? value[method] : value).apply(value, args);
|
138
143
|
});
|
139
|
-
}
|
144
|
+
};
|
140
145
|
|
141
146
|
// Optimized version of a common use case of map: fetching a property.
|
142
|
-
pluck
|
147
|
+
_.pluck = function(obj, key) {
|
143
148
|
var results = [];
|
144
149
|
_.each(obj, function(value){ results.push(value[key]); });
|
145
150
|
return results;
|
146
|
-
}
|
151
|
+
};
|
147
152
|
|
148
153
|
// Return the maximum item or (item-based computation).
|
149
|
-
max
|
154
|
+
_.max = function(obj, iterator, context) {
|
150
155
|
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
151
156
|
var result;
|
152
157
|
_.each(obj, function(value, index) {
|
@@ -154,10 +159,10 @@ window.Underscore = {
|
|
154
159
|
if (result == null || computed >= result.computed) result = {value : value, computed : computed};
|
155
160
|
});
|
156
161
|
return result.value;
|
157
|
-
}
|
162
|
+
};
|
158
163
|
|
159
164
|
// Return the minimum element (or element-based computation).
|
160
|
-
min
|
165
|
+
_.min = function(obj, iterator, context) {
|
161
166
|
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
162
167
|
var result;
|
163
168
|
_.each(obj, function(value, index) {
|
@@ -165,10 +170,10 @@ window.Underscore = {
|
|
165
170
|
if (result == null || computed < result.computed) result = {value : value, computed : computed};
|
166
171
|
});
|
167
172
|
return result.value;
|
168
|
-
}
|
173
|
+
};
|
169
174
|
|
170
175
|
// Sort the object's values by a criteria produced by an iterator.
|
171
|
-
sortBy
|
176
|
+
_.sortBy = function(obj, iterator, context) {
|
172
177
|
return _.pluck(_.map(obj, function(value, index) {
|
173
178
|
return {
|
174
179
|
value : value,
|
@@ -178,11 +183,11 @@ window.Underscore = {
|
|
178
183
|
var a = left.criteria, b = right.criteria;
|
179
184
|
return a < b ? -1 : a > b ? 1 : 0;
|
180
185
|
}), 'value');
|
181
|
-
}
|
186
|
+
};
|
182
187
|
|
183
188
|
// Use a comparator function to figure out at what index an object should
|
184
189
|
// be inserted so as to maintain order. Uses binary search.
|
185
|
-
sortedIndex
|
190
|
+
_.sortedIndex = function(array, obj, iterator) {
|
186
191
|
iterator = iterator || function(val) { return val; };
|
187
192
|
var low = 0, high = array.length;
|
188
193
|
while (low < high) {
|
@@ -190,163 +195,182 @@ window.Underscore = {
|
|
190
195
|
iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
|
191
196
|
}
|
192
197
|
return low;
|
193
|
-
}
|
198
|
+
};
|
194
199
|
|
195
200
|
// Convert anything iterable into a real, live array.
|
196
|
-
toArray
|
201
|
+
_.toArray = function(iterable) {
|
197
202
|
if (!iterable) return [];
|
198
203
|
if (_.isArray(iterable)) return iterable;
|
199
204
|
return _.map(iterable, function(val){ return val; });
|
200
|
-
}
|
205
|
+
};
|
201
206
|
|
202
207
|
// Return the number of elements in an object.
|
203
|
-
size
|
208
|
+
_.size = function(obj) {
|
204
209
|
return _.toArray(obj).length;
|
205
|
-
}
|
210
|
+
};
|
206
211
|
|
207
212
|
/*-------------------------- Array Functions: ------------------------------*/
|
208
213
|
|
209
214
|
// Get the first element of an array.
|
210
|
-
first
|
215
|
+
_.first = function(array) {
|
211
216
|
return array[0];
|
212
|
-
}
|
217
|
+
};
|
213
218
|
|
214
219
|
// Get the last element of an array.
|
215
|
-
last
|
220
|
+
_.last = function(array) {
|
216
221
|
return array[array.length - 1];
|
217
|
-
}
|
222
|
+
};
|
218
223
|
|
219
224
|
// Trim out all falsy values from an array.
|
220
|
-
compact
|
225
|
+
_.compact = function(array) {
|
221
226
|
return _.select(array, function(value){ return !!value; });
|
222
|
-
}
|
227
|
+
};
|
223
228
|
|
224
229
|
// Return a completely flattened version of an array.
|
225
|
-
flatten
|
226
|
-
return _.
|
230
|
+
_.flatten = function(array) {
|
231
|
+
return _.reduce(array, [], function(memo, value) {
|
227
232
|
if (_.isArray(value)) return memo.concat(_.flatten(value));
|
228
233
|
memo.push(value);
|
229
234
|
return memo;
|
230
235
|
});
|
231
|
-
}
|
236
|
+
};
|
232
237
|
|
233
238
|
// Return a version of the array that does not contain the specified value(s).
|
234
|
-
without
|
239
|
+
_.without = function(array) {
|
235
240
|
var values = array.slice.call(arguments, 0);
|
236
241
|
return _.select(array, function(value){ return !_.include(values, value); });
|
237
|
-
}
|
242
|
+
};
|
238
243
|
|
239
244
|
// Produce a duplicate-free version of the array. If the array has already
|
240
245
|
// been sorted, you have the option of using a faster algorithm.
|
241
|
-
uniq
|
242
|
-
return _.
|
246
|
+
_.uniq = function(array, isSorted) {
|
247
|
+
return _.reduce(array, [], function(memo, el, i) {
|
243
248
|
if (0 == i || (isSorted ? _.last(memo) != el : !_.include(memo, el))) memo.push(el);
|
244
249
|
return memo;
|
245
250
|
});
|
246
|
-
}
|
251
|
+
};
|
247
252
|
|
248
253
|
// Produce an array that contains every item shared between all the
|
249
254
|
// passed-in arrays.
|
250
|
-
intersect
|
255
|
+
_.intersect = function(array) {
|
251
256
|
var rest = _.toArray(arguments).slice(1);
|
252
257
|
return _.select(_.uniq(array), function(item) {
|
253
258
|
return _.all(rest, function(other) {
|
254
259
|
return _.indexOf(other, item) >= 0;
|
255
260
|
});
|
256
261
|
});
|
257
|
-
}
|
262
|
+
};
|
258
263
|
|
259
264
|
// Zip together multiple lists into a single array -- elements that share
|
260
265
|
// an index go together.
|
261
|
-
zip
|
266
|
+
_.zip = function() {
|
262
267
|
var args = _.toArray(arguments);
|
263
268
|
var length = _.max(_.pluck(args, 'length'));
|
264
269
|
var results = new Array(length);
|
265
270
|
for (var i=0; i<length; i++) results[i] = _.pluck(args, String(i));
|
266
271
|
return results;
|
267
|
-
}
|
272
|
+
};
|
268
273
|
|
269
274
|
// If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
|
270
275
|
// we need this function. Return the position of the first occurence of an
|
271
276
|
// item in an array, or -1 if the item is not included in the array.
|
272
|
-
indexOf
|
277
|
+
_.indexOf = function(array, item) {
|
273
278
|
if (array.indexOf) return array.indexOf(item);
|
274
|
-
|
275
|
-
|
279
|
+
for (i=0; i<array.length; i++) if (array[i] === item) return i;
|
280
|
+
return -1;
|
281
|
+
};
|
282
|
+
|
283
|
+
// Provide Javascript 1.6's lastIndexOf, delegating to the native function,
|
284
|
+
// if possible.
|
285
|
+
_.lastIndexOf = function(array, item) {
|
286
|
+
if (array.lastIndexOf) return array.lastIndexOf(item);
|
287
|
+
for (i=array.length - 1; i>=0; i--) if (array[i] === item) return i;
|
276
288
|
return -1;
|
277
|
-
}
|
289
|
+
};
|
278
290
|
|
279
291
|
/* ----------------------- Function Functions: -----------------------------*/
|
280
292
|
|
281
293
|
// Create a function bound to a given object (assigning 'this', and arguments,
|
282
294
|
// optionally). Binding with arguments is also known as 'curry'.
|
283
|
-
bind
|
295
|
+
_.bind = function(func, context) {
|
284
296
|
if (!context) return func;
|
285
297
|
var args = _.toArray(arguments).slice(2);
|
286
298
|
return function() {
|
287
299
|
var a = args.concat(_.toArray(arguments));
|
288
300
|
return func.apply(context, a);
|
289
301
|
};
|
290
|
-
}
|
302
|
+
};
|
291
303
|
|
292
304
|
// Bind all of an object's methods to that object. Useful for ensuring that
|
293
305
|
// all callbacks defined on an object belong to it.
|
294
|
-
bindAll
|
306
|
+
_.bindAll = function() {
|
295
307
|
var args = _.toArray(arguments);
|
296
308
|
var context = args.pop();
|
297
309
|
_.each(args, function(methodName) {
|
298
310
|
context[methodName] = _.bind(context[methodName], context);
|
299
311
|
});
|
300
|
-
}
|
312
|
+
};
|
301
313
|
|
302
314
|
// Delays a function for the given number of milliseconds, and then calls
|
303
315
|
// it with the arguments supplied.
|
304
|
-
delay
|
316
|
+
_.delay = function(func, wait) {
|
305
317
|
var args = _.toArray(arguments).slice(2);
|
306
|
-
return
|
307
|
-
}
|
318
|
+
return setTimeout(function(){ return func.apply(func, args); }, wait);
|
319
|
+
};
|
308
320
|
|
309
321
|
// Defers a function, scheduling it to run after the current call stack has
|
310
322
|
// cleared.
|
311
|
-
defer
|
323
|
+
_.defer = function(func) {
|
312
324
|
return _.delay.apply(_, [func, 1].concat(_.toArray(arguments).slice(1)));
|
313
|
-
}
|
325
|
+
};
|
314
326
|
|
315
327
|
// Returns the first function passed as an argument to the second,
|
316
328
|
// allowing you to adjust arguments, run code before and after, and
|
317
329
|
// conditionally execute the original function.
|
318
|
-
wrap
|
330
|
+
_.wrap = function(func, wrapper) {
|
319
331
|
return function() {
|
320
332
|
var args = [func].concat(_.toArray(arguments));
|
321
333
|
return wrapper.apply(wrapper, args);
|
322
334
|
};
|
323
|
-
}
|
335
|
+
};
|
336
|
+
|
337
|
+
// Returns a function that is the composition of a list of functions, each
|
338
|
+
// consuming the return value of the function that follows.
|
339
|
+
_.compose = function() {
|
340
|
+
var funcs = _.toArray(arguments);
|
341
|
+
return function() {
|
342
|
+
for (var i=funcs.length-1; i >= 0; i--) {
|
343
|
+
arguments = [funcs[i].apply(this, arguments)];
|
344
|
+
}
|
345
|
+
return arguments[0];
|
346
|
+
};
|
347
|
+
};
|
324
348
|
|
325
349
|
/* ------------------------- Object Functions: ---------------------------- */
|
326
350
|
|
327
351
|
// Retrieve the names of an object's properties.
|
328
|
-
keys
|
352
|
+
_.keys = function(obj) {
|
329
353
|
return _.pluck(obj, 'key');
|
330
|
-
}
|
354
|
+
};
|
331
355
|
|
332
356
|
// Retrieve the values of an object's properties.
|
333
|
-
values
|
357
|
+
_.values = function(obj) {
|
334
358
|
return _.pluck(obj, 'value');
|
335
|
-
}
|
359
|
+
};
|
336
360
|
|
337
361
|
// Extend a given object with all of the properties in a source object.
|
338
|
-
extend
|
362
|
+
_.extend = function(destination, source) {
|
339
363
|
for (var property in source) destination[property] = source[property];
|
340
364
|
return destination;
|
341
|
-
}
|
365
|
+
};
|
342
366
|
|
343
367
|
// Create a (shallow-cloned) duplicate of an object.
|
344
|
-
clone
|
368
|
+
_.clone = function(obj) {
|
345
369
|
return _.extend({}, obj);
|
346
|
-
}
|
370
|
+
};
|
347
371
|
|
348
372
|
// Perform a deep comparison to check if two objects are equal.
|
349
|
-
isEqual
|
373
|
+
_.isEqual = function(a, b) {
|
350
374
|
// Check object identity.
|
351
375
|
if (a === b) return true;
|
352
376
|
// Different types?
|
@@ -365,47 +389,47 @@ window.Underscore = {
|
|
365
389
|
// Recursive comparison of contents.
|
366
390
|
for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
|
367
391
|
return true;
|
368
|
-
}
|
392
|
+
};
|
369
393
|
|
370
394
|
// Is a given value a DOM element?
|
371
|
-
isElement
|
395
|
+
_.isElement = function(obj) {
|
372
396
|
return !!(obj && obj.nodeType == 1);
|
373
|
-
}
|
397
|
+
};
|
374
398
|
|
375
399
|
// Is a given value a real Array?
|
376
|
-
isArray
|
400
|
+
_.isArray = function(obj) {
|
377
401
|
return Object.prototype.toString.call(obj) == '[object Array]';
|
378
|
-
}
|
402
|
+
};
|
379
403
|
|
380
404
|
// Is a given value a Function?
|
381
|
-
isFunction
|
405
|
+
_.isFunction = function(obj) {
|
382
406
|
return typeof obj == 'function';
|
383
|
-
}
|
407
|
+
};
|
384
408
|
|
385
409
|
// Is a given variable undefined?
|
386
|
-
isUndefined
|
410
|
+
_.isUndefined = function(obj) {
|
387
411
|
return typeof obj == 'undefined';
|
388
|
-
}
|
412
|
+
};
|
389
413
|
|
390
414
|
/* -------------------------- Utility Functions: -------------------------- */
|
391
415
|
|
392
416
|
// Run Underscore.js in noConflict mode, returning the '_' variable to its
|
393
417
|
// previous owner. Returns a reference to the Underscore object.
|
394
|
-
noConflict
|
395
|
-
|
418
|
+
_.noConflict = function() {
|
419
|
+
root._ = previousUnderscore;
|
396
420
|
return this;
|
397
|
-
}
|
421
|
+
};
|
398
422
|
|
399
423
|
// Generate a unique integer id (unique within the entire client session).
|
400
424
|
// Useful for temporary DOM ids.
|
401
|
-
uniqueId
|
425
|
+
_.uniqueId = function(prefix) {
|
402
426
|
var id = this._idCounter = (this._idCounter || 0) + 1;
|
403
427
|
return prefix ? prefix + id : id;
|
404
|
-
}
|
428
|
+
};
|
405
429
|
|
406
430
|
// Javascript templating a-la ERB, pilfered from John Resig's
|
407
431
|
// "Secrets of the Javascript Ninja", page 83.
|
408
|
-
template
|
432
|
+
_.template = function(str, data) {
|
409
433
|
var fn = new Function('obj',
|
410
434
|
'var p=[],print=function(){p.push.apply(p,arguments);};' +
|
411
435
|
'with(obj){p.push(\'' +
|
@@ -419,8 +443,18 @@ window.Underscore = {
|
|
419
443
|
.split("\r").join("\\'")
|
420
444
|
+ "');}return p.join('');");
|
421
445
|
return data ? fn(data) : fn;
|
422
|
-
}
|
446
|
+
};
|
447
|
+
|
448
|
+
/*------------------------------- Aliases ----------------------------------*/
|
449
|
+
|
450
|
+
_.forEach = _.each;
|
451
|
+
_.inject = _.reduce;
|
452
|
+
_.filter = _.select;
|
453
|
+
_.every = _.all;
|
454
|
+
_.some = _.any;
|
455
|
+
|
456
|
+
/*------------------------- Export for ServerJS ----------------------------*/
|
423
457
|
|
424
|
-
|
458
|
+
if (!_.isUndefined(exports)) exports = _;
|
425
459
|
|
426
|
-
|
460
|
+
})();
|