rails-backbone 0.7.2 → 0.8.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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function() {
|
|
1
|
+
(function($) {
|
|
2
2
|
var methodMap = {
|
|
3
3
|
'create': 'POST',
|
|
4
4
|
'update': 'PUT',
|
|
@@ -23,9 +23,10 @@
|
|
|
23
23
|
type: type,
|
|
24
24
|
dataType: 'json',
|
|
25
25
|
beforeSend: function( xhr ) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
if (!options.noCSRF) {
|
|
27
|
+
var token = $('meta[name="csrf-token"]').attr('content');
|
|
28
|
+
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
|
|
29
|
+
}
|
|
29
30
|
model.trigger('sync:start');
|
|
30
31
|
}
|
|
31
32
|
}, options);
|
|
@@ -65,4 +66,4 @@
|
|
|
65
66
|
return $.ajax(params);
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
})
|
|
69
|
+
})(jQuery);
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
// Underscore.js 1.
|
|
1
|
+
// Underscore.js 1.4.0
|
|
2
|
+
// http://underscorejs.org
|
|
2
3
|
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
|
3
|
-
// Underscore
|
|
4
|
-
// Portions of Underscore are inspired or borrowed from Prototype,
|
|
5
|
-
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
|
6
|
-
// For all details and documentation:
|
|
7
|
-
// http://documentcloud.github.com/underscore
|
|
4
|
+
// Underscore may be freely distributed under the MIT license.
|
|
8
5
|
|
|
9
6
|
(function() {
|
|
10
7
|
|
|
@@ -24,7 +21,9 @@
|
|
|
24
21
|
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
|
25
22
|
|
|
26
23
|
// Create quick reference variables for speed access to core prototypes.
|
|
27
|
-
var
|
|
24
|
+
var push = ArrayProto.push,
|
|
25
|
+
slice = ArrayProto.slice,
|
|
26
|
+
concat = ArrayProto.concat,
|
|
28
27
|
unshift = ArrayProto.unshift,
|
|
29
28
|
toString = ObjProto.toString,
|
|
30
29
|
hasOwnProperty = ObjProto.hasOwnProperty;
|
|
@@ -46,7 +45,11 @@
|
|
|
46
45
|
nativeBind = FuncProto.bind;
|
|
47
46
|
|
|
48
47
|
// Create a safe reference to the Underscore object for use below.
|
|
49
|
-
var _ = function(obj) {
|
|
48
|
+
var _ = function(obj) {
|
|
49
|
+
if (obj instanceof _) return obj;
|
|
50
|
+
if (!(this instanceof _)) return new _(obj);
|
|
51
|
+
this._wrapped = obj;
|
|
52
|
+
};
|
|
50
53
|
|
|
51
54
|
// Export the Underscore object for **Node.js**, with
|
|
52
55
|
// backwards-compatibility for the old `require()` API. If we're in
|
|
@@ -62,7 +65,7 @@
|
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
// Current version.
|
|
65
|
-
_.VERSION = '1.
|
|
68
|
+
_.VERSION = '1.4.0';
|
|
66
69
|
|
|
67
70
|
// Collection Functions
|
|
68
71
|
// --------------------
|
|
@@ -71,12 +74,11 @@
|
|
|
71
74
|
// Handles objects with the built-in `forEach`, arrays, and raw objects.
|
|
72
75
|
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
|
73
76
|
var each = _.each = _.forEach = function(obj, iterator, context) {
|
|
74
|
-
if (obj == null) return;
|
|
75
77
|
if (nativeForEach && obj.forEach === nativeForEach) {
|
|
76
78
|
obj.forEach(iterator, context);
|
|
77
79
|
} else if (obj.length === +obj.length) {
|
|
78
80
|
for (var i = 0, l = obj.length; i < l; i++) {
|
|
79
|
-
if (
|
|
81
|
+
if (iterator.call(context, obj[i], i, obj) === breaker) return;
|
|
80
82
|
}
|
|
81
83
|
} else {
|
|
82
84
|
for (var key in obj) {
|
|
@@ -91,12 +93,10 @@
|
|
|
91
93
|
// Delegates to **ECMAScript 5**'s native `map` if available.
|
|
92
94
|
_.map = _.collect = function(obj, iterator, context) {
|
|
93
95
|
var results = [];
|
|
94
|
-
if (obj == null) return results;
|
|
95
96
|
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
|
96
97
|
each(obj, function(value, index, list) {
|
|
97
98
|
results[results.length] = iterator.call(context, value, index, list);
|
|
98
99
|
});
|
|
99
|
-
if (obj.length === +obj.length) results.length = obj.length;
|
|
100
100
|
return results;
|
|
101
101
|
};
|
|
102
102
|
|
|
@@ -104,7 +104,6 @@
|
|
|
104
104
|
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
|
|
105
105
|
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
|
|
106
106
|
var initial = arguments.length > 2;
|
|
107
|
-
if (obj == null) obj = [];
|
|
108
107
|
if (nativeReduce && obj.reduce === nativeReduce) {
|
|
109
108
|
if (context) iterator = _.bind(iterator, context);
|
|
110
109
|
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
|
|
@@ -125,14 +124,26 @@
|
|
|
125
124
|
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
|
|
126
125
|
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
|
|
127
126
|
var initial = arguments.length > 2;
|
|
128
|
-
if (obj == null) obj = [];
|
|
129
127
|
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
|
130
128
|
if (context) iterator = _.bind(iterator, context);
|
|
131
|
-
return
|
|
129
|
+
return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
|
130
|
+
}
|
|
131
|
+
var length = obj.length;
|
|
132
|
+
if (length !== +length) {
|
|
133
|
+
var keys = _.keys(obj);
|
|
134
|
+
length = keys.length;
|
|
132
135
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
each(obj, function(value, index, list) {
|
|
137
|
+
index = keys ? keys[--length] : --length;
|
|
138
|
+
if (!initial) {
|
|
139
|
+
memo = obj[index];
|
|
140
|
+
initial = true;
|
|
141
|
+
} else {
|
|
142
|
+
memo = iterator.call(context, memo, obj[index], index, list);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
if (!initial) throw new TypeError('Reduce of empty array with no initial value');
|
|
146
|
+
return memo;
|
|
136
147
|
};
|
|
137
148
|
|
|
138
149
|
// Return the first value which passes a truth test. Aliased as `detect`.
|
|
@@ -152,7 +163,6 @@
|
|
|
152
163
|
// Aliased as `select`.
|
|
153
164
|
_.filter = _.select = function(obj, iterator, context) {
|
|
154
165
|
var results = [];
|
|
155
|
-
if (obj == null) return results;
|
|
156
166
|
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
|
157
167
|
each(obj, function(value, index, list) {
|
|
158
168
|
if (iterator.call(context, value, index, list)) results[results.length] = value;
|
|
@@ -163,7 +173,6 @@
|
|
|
163
173
|
// Return all the elements for which a truth test fails.
|
|
164
174
|
_.reject = function(obj, iterator, context) {
|
|
165
175
|
var results = [];
|
|
166
|
-
if (obj == null) return results;
|
|
167
176
|
each(obj, function(value, index, list) {
|
|
168
177
|
if (!iterator.call(context, value, index, list)) results[results.length] = value;
|
|
169
178
|
});
|
|
@@ -174,8 +183,8 @@
|
|
|
174
183
|
// Delegates to **ECMAScript 5**'s native `every` if available.
|
|
175
184
|
// Aliased as `all`.
|
|
176
185
|
_.every = _.all = function(obj, iterator, context) {
|
|
186
|
+
iterator || (iterator = _.identity);
|
|
177
187
|
var result = true;
|
|
178
|
-
if (obj == null) return result;
|
|
179
188
|
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
|
180
189
|
each(obj, function(value, index, list) {
|
|
181
190
|
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
|
|
@@ -189,7 +198,6 @@
|
|
|
189
198
|
var any = _.some = _.any = function(obj, iterator, context) {
|
|
190
199
|
iterator || (iterator = _.identity);
|
|
191
200
|
var result = false;
|
|
192
|
-
if (obj == null) return result;
|
|
193
201
|
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
|
194
202
|
each(obj, function(value, index, list) {
|
|
195
203
|
if (result || (result = iterator.call(context, value, index, list))) return breaker;
|
|
@@ -197,11 +205,10 @@
|
|
|
197
205
|
return !!result;
|
|
198
206
|
};
|
|
199
207
|
|
|
200
|
-
// Determine if
|
|
201
|
-
// Aliased as `
|
|
202
|
-
_.
|
|
208
|
+
// Determine if the array or object contains a given value (using `===`).
|
|
209
|
+
// Aliased as `include`.
|
|
210
|
+
_.contains = _.include = function(obj, target) {
|
|
203
211
|
var found = false;
|
|
204
|
-
if (obj == null) return found;
|
|
205
212
|
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
|
206
213
|
found = any(obj, function(value) {
|
|
207
214
|
return value === target;
|
|
@@ -213,7 +220,7 @@
|
|
|
213
220
|
_.invoke = function(obj, method) {
|
|
214
221
|
var args = slice.call(arguments, 2);
|
|
215
222
|
return _.map(obj, function(value) {
|
|
216
|
-
return (_.isFunction(method) ? method
|
|
223
|
+
return (_.isFunction(method) ? method : value[method]).apply(value, args);
|
|
217
224
|
});
|
|
218
225
|
};
|
|
219
226
|
|
|
@@ -222,9 +229,25 @@
|
|
|
222
229
|
return _.map(obj, function(value){ return value[key]; });
|
|
223
230
|
};
|
|
224
231
|
|
|
232
|
+
// Convenience version of a common use case of `filter`: selecting only objects
|
|
233
|
+
// with specific `key:value` pairs.
|
|
234
|
+
_.where = function(obj, attrs) {
|
|
235
|
+
if (_.isEmpty(attrs)) return [];
|
|
236
|
+
return _.filter(obj, function(value) {
|
|
237
|
+
for (var key in attrs) {
|
|
238
|
+
if (attrs[key] !== value[key]) return false;
|
|
239
|
+
}
|
|
240
|
+
return true;
|
|
241
|
+
});
|
|
242
|
+
};
|
|
243
|
+
|
|
225
244
|
// Return the maximum element or (element-based computation).
|
|
245
|
+
// Can't optimize arrays of integers longer than 65,535 elements.
|
|
246
|
+
// See: https://bugs.webkit.org/show_bug.cgi?id=80797
|
|
226
247
|
_.max = function(obj, iterator, context) {
|
|
227
|
-
if (!iterator && _.isArray(obj) && obj[0] === +obj[0]
|
|
248
|
+
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
|
|
249
|
+
return Math.max.apply(Math, obj);
|
|
250
|
+
}
|
|
228
251
|
if (!iterator && _.isEmpty(obj)) return -Infinity;
|
|
229
252
|
var result = {computed : -Infinity};
|
|
230
253
|
each(obj, function(value, index, list) {
|
|
@@ -236,7 +259,9 @@
|
|
|
236
259
|
|
|
237
260
|
// Return the minimum element (or element-based computation).
|
|
238
261
|
_.min = function(obj, iterator, context) {
|
|
239
|
-
if (!iterator && _.isArray(obj) && obj[0] === +obj[0]
|
|
262
|
+
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
|
|
263
|
+
return Math.min.apply(Math, obj);
|
|
264
|
+
}
|
|
240
265
|
if (!iterator && _.isEmpty(obj)) return Infinity;
|
|
241
266
|
var result = {computed : Infinity};
|
|
242
267
|
each(obj, function(value, index, list) {
|
|
@@ -248,67 +273,94 @@
|
|
|
248
273
|
|
|
249
274
|
// Shuffle an array.
|
|
250
275
|
_.shuffle = function(obj) {
|
|
251
|
-
var
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
276
|
+
var rand;
|
|
277
|
+
var index = 0;
|
|
278
|
+
var shuffled = [];
|
|
279
|
+
each(obj, function(value) {
|
|
280
|
+
rand = _.random(index++);
|
|
281
|
+
shuffled[index - 1] = shuffled[rand];
|
|
255
282
|
shuffled[rand] = value;
|
|
256
283
|
});
|
|
257
284
|
return shuffled;
|
|
258
285
|
};
|
|
259
286
|
|
|
287
|
+
// An internal function to generate lookup iterators.
|
|
288
|
+
var lookupIterator = function(value) {
|
|
289
|
+
return _.isFunction(value) ? value : function(obj){ return obj[value]; };
|
|
290
|
+
};
|
|
291
|
+
|
|
260
292
|
// Sort the object's values by a criterion produced by an iterator.
|
|
261
|
-
_.sortBy = function(obj,
|
|
262
|
-
var iterator =
|
|
293
|
+
_.sortBy = function(obj, value, context) {
|
|
294
|
+
var iterator = lookupIterator(value);
|
|
263
295
|
return _.pluck(_.map(obj, function(value, index, list) {
|
|
264
296
|
return {
|
|
265
297
|
value : value,
|
|
298
|
+
index : index,
|
|
266
299
|
criteria : iterator.call(context, value, index, list)
|
|
267
300
|
};
|
|
268
301
|
}).sort(function(left, right) {
|
|
269
|
-
var a = left.criteria
|
|
270
|
-
|
|
271
|
-
if (
|
|
272
|
-
|
|
302
|
+
var a = left.criteria;
|
|
303
|
+
var b = right.criteria;
|
|
304
|
+
if (a !== b) {
|
|
305
|
+
if (a > b || a === void 0) return 1;
|
|
306
|
+
if (a < b || b === void 0) return -1;
|
|
307
|
+
}
|
|
308
|
+
return left.index < right.index ? -1 : 1;
|
|
273
309
|
}), 'value');
|
|
274
310
|
};
|
|
275
311
|
|
|
276
|
-
//
|
|
277
|
-
|
|
278
|
-
_.groupBy = function(obj, val) {
|
|
312
|
+
// An internal function used for aggregate "group by" operations.
|
|
313
|
+
var group = function(obj, value, context, behavior) {
|
|
279
314
|
var result = {};
|
|
280
|
-
var iterator =
|
|
315
|
+
var iterator = lookupIterator(value);
|
|
281
316
|
each(obj, function(value, index) {
|
|
282
|
-
var key = iterator(value, index);
|
|
283
|
-
(result
|
|
317
|
+
var key = iterator.call(context, value, index, obj);
|
|
318
|
+
behavior(result, key, value);
|
|
284
319
|
});
|
|
285
320
|
return result;
|
|
286
321
|
};
|
|
287
322
|
|
|
288
|
-
//
|
|
289
|
-
//
|
|
290
|
-
_.
|
|
291
|
-
|
|
323
|
+
// Groups the object's values by a criterion. Pass either a string attribute
|
|
324
|
+
// to group by, or a function that returns the criterion.
|
|
325
|
+
_.groupBy = function(obj, value, context) {
|
|
326
|
+
return group(obj, value, context, function(result, key, value) {
|
|
327
|
+
(_.has(result, key) ? result[key] : (result[key] = [])).push(value);
|
|
328
|
+
});
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
// Counts instances of an object that group by a certain criterion. Pass
|
|
332
|
+
// either a string attribute to count by, or a function that returns the
|
|
333
|
+
// criterion.
|
|
334
|
+
_.countBy = function(obj, value, context) {
|
|
335
|
+
return group(obj, value, context, function(result, key, value) {
|
|
336
|
+
if (!_.has(result, key)) result[key] = 0;
|
|
337
|
+
result[key]++;
|
|
338
|
+
});
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// Use a comparator function to figure out the smallest index at which
|
|
342
|
+
// an object should be inserted so as to maintain order. Uses binary search.
|
|
343
|
+
_.sortedIndex = function(array, obj, iterator, context) {
|
|
344
|
+
iterator = iterator == null ? _.identity : lookupIterator(iterator);
|
|
345
|
+
var value = iterator.call(context, obj);
|
|
292
346
|
var low = 0, high = array.length;
|
|
293
347
|
while (low < high) {
|
|
294
|
-
var mid = (low + high)
|
|
295
|
-
iterator(array[mid]) <
|
|
348
|
+
var mid = (low + high) >>> 1;
|
|
349
|
+
iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
|
|
296
350
|
}
|
|
297
351
|
return low;
|
|
298
352
|
};
|
|
299
353
|
|
|
300
354
|
// Safely convert anything iterable into a real, live array.
|
|
301
355
|
_.toArray = function(obj) {
|
|
302
|
-
if (!obj)
|
|
303
|
-
if (
|
|
304
|
-
if (_.isArguments(obj)) return slice.call(obj);
|
|
305
|
-
if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray();
|
|
356
|
+
if (!obj) return [];
|
|
357
|
+
if (obj.length === +obj.length) return slice.call(obj);
|
|
306
358
|
return _.values(obj);
|
|
307
359
|
};
|
|
308
360
|
|
|
309
361
|
// Return the number of elements in an object.
|
|
310
362
|
_.size = function(obj) {
|
|
311
|
-
return
|
|
363
|
+
return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
|
|
312
364
|
};
|
|
313
365
|
|
|
314
366
|
// Array Functions
|
|
@@ -321,7 +373,7 @@
|
|
|
321
373
|
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
|
|
322
374
|
};
|
|
323
375
|
|
|
324
|
-
// Returns everything but the last entry of the array.
|
|
376
|
+
// Returns everything but the last entry of the array. Especially useful on
|
|
325
377
|
// the arguments object. Passing **n** will return all the values in
|
|
326
378
|
// the array, excluding the last N. The **guard** check allows it to work with
|
|
327
379
|
// `_.map`.
|
|
@@ -339,12 +391,12 @@
|
|
|
339
391
|
}
|
|
340
392
|
};
|
|
341
393
|
|
|
342
|
-
// Returns everything but the first entry of the array. Aliased as `tail`.
|
|
343
|
-
// Especially useful on the arguments object. Passing an **
|
|
344
|
-
// the rest
|
|
394
|
+
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
|
|
395
|
+
// Especially useful on the arguments object. Passing an **n** will return
|
|
396
|
+
// the rest N values in the array. The **guard**
|
|
345
397
|
// check allows it to work with `_.map`.
|
|
346
|
-
_.rest = _.tail = function(array,
|
|
347
|
-
return slice.call(array, (
|
|
398
|
+
_.rest = _.tail = _.drop = function(array, n, guard) {
|
|
399
|
+
return slice.call(array, (n == null) || guard ? 1 : n);
|
|
348
400
|
};
|
|
349
401
|
|
|
350
402
|
// Trim out all falsy values from an array.
|
|
@@ -352,13 +404,21 @@
|
|
|
352
404
|
return _.filter(array, function(value){ return !!value; });
|
|
353
405
|
};
|
|
354
406
|
|
|
407
|
+
// Internal implementation of a recursive `flatten` function.
|
|
408
|
+
var flatten = function(input, shallow, output) {
|
|
409
|
+
each(input, function(value) {
|
|
410
|
+
if (_.isArray(value)) {
|
|
411
|
+
shallow ? push.apply(output, value) : flatten(value, shallow, output);
|
|
412
|
+
} else {
|
|
413
|
+
output.push(value);
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
return output;
|
|
417
|
+
};
|
|
418
|
+
|
|
355
419
|
// Return a completely flattened version of an array.
|
|
356
420
|
_.flatten = function(array, shallow) {
|
|
357
|
-
return
|
|
358
|
-
if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
|
|
359
|
-
memo[memo.length] = value;
|
|
360
|
-
return memo;
|
|
361
|
-
}, []);
|
|
421
|
+
return flatten(array, shallow, []);
|
|
362
422
|
};
|
|
363
423
|
|
|
364
424
|
// Return a version of the array that does not contain the specified value(s).
|
|
@@ -369,30 +429,28 @@
|
|
|
369
429
|
// Produce a duplicate-free version of the array. If the array has already
|
|
370
430
|
// been sorted, you have the option of using a faster algorithm.
|
|
371
431
|
// Aliased as `unique`.
|
|
372
|
-
_.uniq = _.unique = function(array, isSorted, iterator) {
|
|
373
|
-
var initial = iterator ? _.map(array, iterator) : array;
|
|
432
|
+
_.uniq = _.unique = function(array, isSorted, iterator, context) {
|
|
433
|
+
var initial = iterator ? _.map(array, iterator, context) : array;
|
|
374
434
|
var results = [];
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
memo.push(value);
|
|
435
|
+
var seen = [];
|
|
436
|
+
each(initial, function(value, index) {
|
|
437
|
+
if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
|
|
438
|
+
seen.push(value);
|
|
380
439
|
results.push(array[index]);
|
|
381
440
|
}
|
|
382
|
-
|
|
383
|
-
}, []);
|
|
441
|
+
});
|
|
384
442
|
return results;
|
|
385
443
|
};
|
|
386
444
|
|
|
387
445
|
// Produce an array that contains the union: each distinct element from all of
|
|
388
446
|
// the passed-in arrays.
|
|
389
447
|
_.union = function() {
|
|
390
|
-
return _.uniq(
|
|
448
|
+
return _.uniq(concat.apply(ArrayProto, arguments));
|
|
391
449
|
};
|
|
392
450
|
|
|
393
451
|
// Produce an array that contains every item shared between all the
|
|
394
|
-
// passed-in arrays.
|
|
395
|
-
_.intersection =
|
|
452
|
+
// passed-in arrays.
|
|
453
|
+
_.intersection = function(array) {
|
|
396
454
|
var rest = slice.call(arguments, 1);
|
|
397
455
|
return _.filter(_.uniq(array), function(item) {
|
|
398
456
|
return _.every(rest, function(other) {
|
|
@@ -404,8 +462,8 @@
|
|
|
404
462
|
// Take the difference between one array and a number of other arrays.
|
|
405
463
|
// Only the elements present in just the first array will remain.
|
|
406
464
|
_.difference = function(array) {
|
|
407
|
-
var rest =
|
|
408
|
-
return _.filter(array, function(value){ return !_.
|
|
465
|
+
var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
|
|
466
|
+
return _.filter(array, function(value){ return !_.contains(rest, value); });
|
|
409
467
|
};
|
|
410
468
|
|
|
411
469
|
// Zip together multiple lists into a single array -- elements that share
|
|
@@ -414,10 +472,27 @@
|
|
|
414
472
|
var args = slice.call(arguments);
|
|
415
473
|
var length = _.max(_.pluck(args, 'length'));
|
|
416
474
|
var results = new Array(length);
|
|
417
|
-
for (var i = 0; i < length; i++)
|
|
475
|
+
for (var i = 0; i < length; i++) {
|
|
476
|
+
results[i] = _.pluck(args, "" + i);
|
|
477
|
+
}
|
|
418
478
|
return results;
|
|
419
479
|
};
|
|
420
480
|
|
|
481
|
+
// Converts lists into objects. Pass either a single array of `[key, value]`
|
|
482
|
+
// pairs, or two parallel arrays of the same length -- one of keys, and one of
|
|
483
|
+
// the corresponding values.
|
|
484
|
+
_.object = function(list, values) {
|
|
485
|
+
var result = {};
|
|
486
|
+
for (var i = 0, l = list.length; i < l; i++) {
|
|
487
|
+
if (values) {
|
|
488
|
+
result[list[i]] = values[i];
|
|
489
|
+
} else {
|
|
490
|
+
result[list[i][0]] = list[i][1];
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return result;
|
|
494
|
+
};
|
|
495
|
+
|
|
421
496
|
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
|
|
422
497
|
// we need this function. Return the position of the first occurrence of an
|
|
423
498
|
// item in an array, or -1 if the item is not included in the array.
|
|
@@ -425,23 +500,25 @@
|
|
|
425
500
|
// If the array is large and already in sort order, pass `true`
|
|
426
501
|
// for **isSorted** to use binary search.
|
|
427
502
|
_.indexOf = function(array, item, isSorted) {
|
|
428
|
-
|
|
429
|
-
var i, l;
|
|
503
|
+
var i = 0, l = array.length;
|
|
430
504
|
if (isSorted) {
|
|
431
|
-
|
|
432
|
-
|
|
505
|
+
if (typeof isSorted == 'number') {
|
|
506
|
+
i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
|
|
507
|
+
} else {
|
|
508
|
+
i = _.sortedIndex(array, item);
|
|
509
|
+
return array[i] === item ? i : -1;
|
|
510
|
+
}
|
|
433
511
|
}
|
|
434
|
-
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
|
|
435
|
-
for (
|
|
512
|
+
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
|
|
513
|
+
for (; i < l; i++) if (array[i] === item) return i;
|
|
436
514
|
return -1;
|
|
437
515
|
};
|
|
438
516
|
|
|
439
517
|
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
|
|
440
|
-
_.lastIndexOf = function(array, item) {
|
|
441
|
-
if (array
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
while (i--) if (i in array && array[i] === item) return i;
|
|
518
|
+
_.lastIndexOf = function(array, item, fromIndex) {
|
|
519
|
+
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item, fromIndex);
|
|
520
|
+
var i = (fromIndex != null ? fromIndex : array.length);
|
|
521
|
+
while (i--) if (array[i] === item) return i;
|
|
445
522
|
return -1;
|
|
446
523
|
};
|
|
447
524
|
|
|
@@ -533,17 +610,19 @@
|
|
|
533
610
|
context = this; args = arguments;
|
|
534
611
|
var later = function() {
|
|
535
612
|
timeout = null;
|
|
536
|
-
if (more)
|
|
613
|
+
if (more) {
|
|
614
|
+
result = func.apply(context, args);
|
|
615
|
+
}
|
|
537
616
|
whenDone();
|
|
538
617
|
};
|
|
539
618
|
if (!timeout) timeout = setTimeout(later, wait);
|
|
540
619
|
if (throttling) {
|
|
541
620
|
more = true;
|
|
542
621
|
} else {
|
|
622
|
+
throttling = true;
|
|
543
623
|
result = func.apply(context, args);
|
|
544
624
|
}
|
|
545
625
|
whenDone();
|
|
546
|
-
throttling = true;
|
|
547
626
|
return result;
|
|
548
627
|
};
|
|
549
628
|
};
|
|
@@ -553,16 +632,18 @@
|
|
|
553
632
|
// N milliseconds. If `immediate` is passed, trigger the function on the
|
|
554
633
|
// leading edge, instead of the trailing.
|
|
555
634
|
_.debounce = function(func, wait, immediate) {
|
|
556
|
-
var timeout;
|
|
635
|
+
var timeout, result;
|
|
557
636
|
return function() {
|
|
558
637
|
var context = this, args = arguments;
|
|
559
638
|
var later = function() {
|
|
560
639
|
timeout = null;
|
|
561
|
-
if (!immediate) func.apply(context, args);
|
|
640
|
+
if (!immediate) result = func.apply(context, args);
|
|
562
641
|
};
|
|
563
|
-
|
|
642
|
+
var callNow = immediate && !timeout;
|
|
564
643
|
clearTimeout(timeout);
|
|
565
644
|
timeout = setTimeout(later, wait);
|
|
645
|
+
if (callNow) result = func.apply(context, args);
|
|
646
|
+
return result;
|
|
566
647
|
};
|
|
567
648
|
};
|
|
568
649
|
|
|
@@ -573,7 +654,9 @@
|
|
|
573
654
|
return function() {
|
|
574
655
|
if (ran) return memo;
|
|
575
656
|
ran = true;
|
|
576
|
-
|
|
657
|
+
memo = func.apply(this, arguments);
|
|
658
|
+
func = null;
|
|
659
|
+
return memo;
|
|
577
660
|
};
|
|
578
661
|
};
|
|
579
662
|
|
|
@@ -582,7 +665,8 @@
|
|
|
582
665
|
// conditionally execute the original function.
|
|
583
666
|
_.wrap = function(func, wrapper) {
|
|
584
667
|
return function() {
|
|
585
|
-
var args = [func]
|
|
668
|
+
var args = [func];
|
|
669
|
+
push.apply(args, arguments);
|
|
586
670
|
return wrapper.apply(this, args);
|
|
587
671
|
};
|
|
588
672
|
};
|
|
@@ -604,7 +688,9 @@
|
|
|
604
688
|
_.after = function(times, func) {
|
|
605
689
|
if (times <= 0) return func();
|
|
606
690
|
return function() {
|
|
607
|
-
if (--times < 1) {
|
|
691
|
+
if (--times < 1) {
|
|
692
|
+
return func.apply(this, arguments);
|
|
693
|
+
}
|
|
608
694
|
};
|
|
609
695
|
};
|
|
610
696
|
|
|
@@ -622,7 +708,23 @@
|
|
|
622
708
|
|
|
623
709
|
// Retrieve the values of an object's properties.
|
|
624
710
|
_.values = function(obj) {
|
|
625
|
-
|
|
711
|
+
var values = [];
|
|
712
|
+
for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
|
|
713
|
+
return values;
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
// Convert an object into a list of `[key, value]` pairs.
|
|
717
|
+
_.pairs = function(obj) {
|
|
718
|
+
var pairs = [];
|
|
719
|
+
for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
|
|
720
|
+
return pairs;
|
|
721
|
+
};
|
|
722
|
+
|
|
723
|
+
// Invert the keys and values of an object. The values must be serializable.
|
|
724
|
+
_.invert = function(obj) {
|
|
725
|
+
var result = {};
|
|
726
|
+
for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
|
|
727
|
+
return result;
|
|
626
728
|
};
|
|
627
729
|
|
|
628
730
|
// Return a sorted list of the function names available on the object.
|
|
@@ -647,11 +749,22 @@
|
|
|
647
749
|
|
|
648
750
|
// Return a copy of the object only containing the whitelisted properties.
|
|
649
751
|
_.pick = function(obj) {
|
|
650
|
-
var
|
|
651
|
-
|
|
652
|
-
|
|
752
|
+
var copy = {};
|
|
753
|
+
var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
|
|
754
|
+
each(keys, function(key) {
|
|
755
|
+
if (key in obj) copy[key] = obj[key];
|
|
653
756
|
});
|
|
654
|
-
return
|
|
757
|
+
return copy;
|
|
758
|
+
};
|
|
759
|
+
|
|
760
|
+
// Return a copy of the object without the blacklisted properties.
|
|
761
|
+
_.omit = function(obj) {
|
|
762
|
+
var copy = {};
|
|
763
|
+
var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
|
|
764
|
+
for (var key in obj) {
|
|
765
|
+
if (!_.contains(keys, key)) copy[key] = obj[key];
|
|
766
|
+
}
|
|
767
|
+
return copy;
|
|
655
768
|
};
|
|
656
769
|
|
|
657
770
|
// Fill in a given object with default properties.
|
|
@@ -678,19 +791,16 @@
|
|
|
678
791
|
return obj;
|
|
679
792
|
};
|
|
680
793
|
|
|
681
|
-
// Internal recursive comparison function
|
|
682
|
-
|
|
794
|
+
// Internal recursive comparison function for `isEqual`.
|
|
795
|
+
var eq = function(a, b, aStack, bStack) {
|
|
683
796
|
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
|
684
797
|
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
|
|
685
798
|
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
|
686
799
|
// A strict comparison is necessary because `null == undefined`.
|
|
687
800
|
if (a == null || b == null) return a === b;
|
|
688
801
|
// Unwrap any wrapped objects.
|
|
689
|
-
if (a
|
|
690
|
-
if (b
|
|
691
|
-
// Invoke a custom `isEqual` method if one is provided.
|
|
692
|
-
if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
|
|
693
|
-
if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
|
|
802
|
+
if (a instanceof _) a = a._wrapped;
|
|
803
|
+
if (b instanceof _) b = b._wrapped;
|
|
694
804
|
// Compare `[[Class]]` names.
|
|
695
805
|
var className = toString.call(a);
|
|
696
806
|
if (className != toString.call(b)) return false;
|
|
@@ -720,14 +830,15 @@
|
|
|
720
830
|
if (typeof a != 'object' || typeof b != 'object') return false;
|
|
721
831
|
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
|
722
832
|
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
|
723
|
-
var length =
|
|
833
|
+
var length = aStack.length;
|
|
724
834
|
while (length--) {
|
|
725
835
|
// Linear search. Performance is inversely proportional to the number of
|
|
726
836
|
// unique nested structures.
|
|
727
|
-
if (
|
|
837
|
+
if (aStack[length] == a) return bStack[length] == b;
|
|
728
838
|
}
|
|
729
839
|
// Add the first object to the stack of traversed objects.
|
|
730
|
-
|
|
840
|
+
aStack.push(a);
|
|
841
|
+
bStack.push(b);
|
|
731
842
|
var size = 0, result = true;
|
|
732
843
|
// Recursively compare objects and arrays.
|
|
733
844
|
if (className == '[object Array]') {
|
|
@@ -737,20 +848,24 @@
|
|
|
737
848
|
if (result) {
|
|
738
849
|
// Deep compare the contents, ignoring non-numeric properties.
|
|
739
850
|
while (size--) {
|
|
740
|
-
|
|
741
|
-
if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
|
|
851
|
+
if (!(result = eq(a[size], b[size], aStack, bStack))) break;
|
|
742
852
|
}
|
|
743
853
|
}
|
|
744
854
|
} else {
|
|
745
|
-
// Objects with different constructors are not equivalent
|
|
746
|
-
|
|
855
|
+
// Objects with different constructors are not equivalent, but `Object`s
|
|
856
|
+
// from different frames are.
|
|
857
|
+
var aCtor = a.constructor, bCtor = b.constructor;
|
|
858
|
+
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
|
|
859
|
+
_.isFunction(bCtor) && (bCtor instanceof bCtor))) {
|
|
860
|
+
return false;
|
|
861
|
+
}
|
|
747
862
|
// Deep compare objects.
|
|
748
863
|
for (var key in a) {
|
|
749
864
|
if (_.has(a, key)) {
|
|
750
865
|
// Count the expected number of properties.
|
|
751
866
|
size++;
|
|
752
867
|
// Deep compare each member.
|
|
753
|
-
if (!(result = _.has(b, key) && eq(a[key], b[key],
|
|
868
|
+
if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
|
|
754
869
|
}
|
|
755
870
|
}
|
|
756
871
|
// Ensure that both objects contain the same number of properties.
|
|
@@ -762,13 +877,14 @@
|
|
|
762
877
|
}
|
|
763
878
|
}
|
|
764
879
|
// Remove the first object from the stack of traversed objects.
|
|
765
|
-
|
|
880
|
+
aStack.pop();
|
|
881
|
+
bStack.pop();
|
|
766
882
|
return result;
|
|
767
|
-
}
|
|
883
|
+
};
|
|
768
884
|
|
|
769
885
|
// Perform a deep comparison to check if two objects are equal.
|
|
770
886
|
_.isEqual = function(a, b) {
|
|
771
|
-
return eq(a, b, []);
|
|
887
|
+
return eq(a, b, [], []);
|
|
772
888
|
};
|
|
773
889
|
|
|
774
890
|
// Is a given array, string, or object empty?
|
|
@@ -782,7 +898,7 @@
|
|
|
782
898
|
|
|
783
899
|
// Is a given value a DOM element?
|
|
784
900
|
_.isElement = function(obj) {
|
|
785
|
-
return !!(obj && obj.nodeType
|
|
901
|
+
return !!(obj && obj.nodeType === 1);
|
|
786
902
|
};
|
|
787
903
|
|
|
788
904
|
// Is a given value an array?
|
|
@@ -796,40 +912,36 @@
|
|
|
796
912
|
return obj === Object(obj);
|
|
797
913
|
};
|
|
798
914
|
|
|
799
|
-
//
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
915
|
+
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
|
|
916
|
+
each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
|
|
917
|
+
_['is' + name] = function(obj) {
|
|
918
|
+
return toString.call(obj) == '[object ' + name + ']';
|
|
919
|
+
};
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
// Define a fallback version of the method in browsers (ahem, IE), where
|
|
923
|
+
// there isn't any inspectable "Arguments" type.
|
|
803
924
|
if (!_.isArguments(arguments)) {
|
|
804
925
|
_.isArguments = function(obj) {
|
|
805
926
|
return !!(obj && _.has(obj, 'callee'));
|
|
806
927
|
};
|
|
807
928
|
}
|
|
808
929
|
|
|
809
|
-
//
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
_.isString = function(obj) {
|
|
816
|
-
return toString.call(obj) == '[object String]';
|
|
817
|
-
};
|
|
818
|
-
|
|
819
|
-
// Is a given value a number?
|
|
820
|
-
_.isNumber = function(obj) {
|
|
821
|
-
return toString.call(obj) == '[object Number]';
|
|
822
|
-
};
|
|
930
|
+
// Optimize `isFunction` if appropriate.
|
|
931
|
+
if (typeof (/./) !== 'function') {
|
|
932
|
+
_.isFunction = function(obj) {
|
|
933
|
+
return typeof obj === 'function';
|
|
934
|
+
};
|
|
935
|
+
}
|
|
823
936
|
|
|
824
937
|
// Is a given object a finite number?
|
|
825
938
|
_.isFinite = function(obj) {
|
|
826
939
|
return _.isNumber(obj) && isFinite(obj);
|
|
827
940
|
};
|
|
828
941
|
|
|
829
|
-
// Is the given value `NaN`?
|
|
942
|
+
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
|
|
830
943
|
_.isNaN = function(obj) {
|
|
831
|
-
|
|
832
|
-
return obj !== obj;
|
|
944
|
+
return _.isNumber(obj) && obj != +obj;
|
|
833
945
|
};
|
|
834
946
|
|
|
835
947
|
// Is a given value a boolean?
|
|
@@ -837,16 +949,6 @@
|
|
|
837
949
|
return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
|
|
838
950
|
};
|
|
839
951
|
|
|
840
|
-
// Is a given value a date?
|
|
841
|
-
_.isDate = function(obj) {
|
|
842
|
-
return toString.call(obj) == '[object Date]';
|
|
843
|
-
};
|
|
844
|
-
|
|
845
|
-
// Is the given value a regular expression?
|
|
846
|
-
_.isRegExp = function(obj) {
|
|
847
|
-
return toString.call(obj) == '[object RegExp]';
|
|
848
|
-
};
|
|
849
|
-
|
|
850
952
|
// Is a given value equal to null?
|
|
851
953
|
_.isNull = function(obj) {
|
|
852
954
|
return obj === null;
|
|
@@ -857,7 +959,8 @@
|
|
|
857
959
|
return obj === void 0;
|
|
858
960
|
};
|
|
859
961
|
|
|
860
|
-
//
|
|
962
|
+
// Shortcut function for checking if an object has a given property directly
|
|
963
|
+
// on itself (in other words, not on a prototype).
|
|
861
964
|
_.has = function(obj, key) {
|
|
862
965
|
return hasOwnProperty.call(obj, key);
|
|
863
966
|
};
|
|
@@ -878,15 +981,48 @@
|
|
|
878
981
|
};
|
|
879
982
|
|
|
880
983
|
// Run a function **n** times.
|
|
881
|
-
_.times = function
|
|
984
|
+
_.times = function(n, iterator, context) {
|
|
882
985
|
for (var i = 0; i < n; i++) iterator.call(context, i);
|
|
883
986
|
};
|
|
884
987
|
|
|
885
|
-
//
|
|
886
|
-
_.
|
|
887
|
-
|
|
988
|
+
// Return a random integer between min and max (inclusive).
|
|
989
|
+
_.random = function(min, max) {
|
|
990
|
+
if (max == null) {
|
|
991
|
+
max = min;
|
|
992
|
+
min = 0;
|
|
993
|
+
}
|
|
994
|
+
return min + (0 | Math.random() * (max - min + 1));
|
|
995
|
+
};
|
|
996
|
+
|
|
997
|
+
// List of HTML entities for escaping.
|
|
998
|
+
var entityMap = {
|
|
999
|
+
escape: {
|
|
1000
|
+
'&': '&',
|
|
1001
|
+
'<': '<',
|
|
1002
|
+
'>': '>',
|
|
1003
|
+
'"': '"',
|
|
1004
|
+
"'": ''',
|
|
1005
|
+
'/': '/'
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
entityMap.unescape = _.invert(entityMap.escape);
|
|
1009
|
+
|
|
1010
|
+
// Regexes containing the keys and values listed immediately above.
|
|
1011
|
+
var entityRegexes = {
|
|
1012
|
+
escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
|
|
1013
|
+
unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
|
|
888
1014
|
};
|
|
889
1015
|
|
|
1016
|
+
// Functions for escaping and unescaping strings to/from HTML interpolation.
|
|
1017
|
+
_.each(['escape', 'unescape'], function(method) {
|
|
1018
|
+
_[method] = function(string) {
|
|
1019
|
+
if (string == null) return '';
|
|
1020
|
+
return ('' + string).replace(entityRegexes[method], function(match) {
|
|
1021
|
+
return entityMap[method][match];
|
|
1022
|
+
});
|
|
1023
|
+
};
|
|
1024
|
+
});
|
|
1025
|
+
|
|
890
1026
|
// If the value of the named property is a function then invoke it;
|
|
891
1027
|
// otherwise, return it.
|
|
892
1028
|
_.result = function(object, property) {
|
|
@@ -895,11 +1031,15 @@
|
|
|
895
1031
|
return _.isFunction(value) ? value.call(object) : value;
|
|
896
1032
|
};
|
|
897
1033
|
|
|
898
|
-
// Add your own custom functions to the Underscore object
|
|
899
|
-
// they're correctly added to the OOP wrapper as well.
|
|
1034
|
+
// Add your own custom functions to the Underscore object.
|
|
900
1035
|
_.mixin = function(obj) {
|
|
901
1036
|
each(_.functions(obj), function(name){
|
|
902
|
-
|
|
1037
|
+
var func = _[name] = obj[name];
|
|
1038
|
+
_.prototype[name] = function() {
|
|
1039
|
+
var args = [this._wrapped];
|
|
1040
|
+
push.apply(args, arguments);
|
|
1041
|
+
return result.call(this, func.apply(_, args));
|
|
1042
|
+
};
|
|
903
1043
|
});
|
|
904
1044
|
};
|
|
905
1045
|
|
|
@@ -922,72 +1062,70 @@
|
|
|
922
1062
|
// When customizing `templateSettings`, if you don't want to define an
|
|
923
1063
|
// interpolation, evaluation or escaping regex, we need one that is
|
|
924
1064
|
// guaranteed not to match.
|
|
925
|
-
var noMatch =
|
|
1065
|
+
var noMatch = /(.)^/;
|
|
926
1066
|
|
|
927
1067
|
// Certain characters need to be escaped so that they can be put into a
|
|
928
1068
|
// string literal.
|
|
929
1069
|
var escapes = {
|
|
930
|
-
'
|
|
931
|
-
|
|
932
|
-
'r':
|
|
933
|
-
'n':
|
|
934
|
-
't':
|
|
935
|
-
'u2028': '
|
|
936
|
-
'u2029': '
|
|
1070
|
+
"'": "'",
|
|
1071
|
+
'\\': '\\',
|
|
1072
|
+
'\r': 'r',
|
|
1073
|
+
'\n': 'n',
|
|
1074
|
+
'\t': 't',
|
|
1075
|
+
'\u2028': 'u2028',
|
|
1076
|
+
'\u2029': 'u2029'
|
|
937
1077
|
};
|
|
938
1078
|
|
|
939
|
-
for (var p in escapes) escapes[escapes[p]] = p;
|
|
940
1079
|
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
|
|
941
|
-
var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
|
|
942
|
-
|
|
943
|
-
// Within an interpolation, evaluation, or escaping, remove HTML escaping
|
|
944
|
-
// that had been previously added.
|
|
945
|
-
var unescape = function(code) {
|
|
946
|
-
return code.replace(unescaper, function(match, escape) {
|
|
947
|
-
return escapes[escape];
|
|
948
|
-
});
|
|
949
|
-
};
|
|
950
1080
|
|
|
951
1081
|
// JavaScript micro-templating, similar to John Resig's implementation.
|
|
952
1082
|
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
|
953
1083
|
// and correctly escapes quotes within interpolated code.
|
|
954
1084
|
_.template = function(text, data, settings) {
|
|
955
|
-
settings = _.defaults(
|
|
956
|
-
|
|
957
|
-
//
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
.
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1085
|
+
settings = _.defaults({}, settings, _.templateSettings);
|
|
1086
|
+
|
|
1087
|
+
// Combine delimiters into one regular expression via alternation.
|
|
1088
|
+
var matcher = new RegExp([
|
|
1089
|
+
(settings.escape || noMatch).source,
|
|
1090
|
+
(settings.interpolate || noMatch).source,
|
|
1091
|
+
(settings.evaluate || noMatch).source
|
|
1092
|
+
].join('|') + '|$', 'g');
|
|
1093
|
+
|
|
1094
|
+
// Compile the template source, escaping string literals appropriately.
|
|
1095
|
+
var index = 0;
|
|
1096
|
+
var source = "__p+='";
|
|
1097
|
+
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
|
1098
|
+
source += text.slice(index, offset)
|
|
1099
|
+
.replace(escaper, function(match) { return '\\' + escapes[match]; });
|
|
1100
|
+
source +=
|
|
1101
|
+
escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" :
|
|
1102
|
+
interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" :
|
|
1103
|
+
evaluate ? "';\n" + evaluate + "\n__p+='" : '';
|
|
1104
|
+
index = offset + match.length;
|
|
1105
|
+
});
|
|
1106
|
+
source += "';\n";
|
|
973
1107
|
|
|
974
1108
|
// If a variable is not specified, place data values in local scope.
|
|
975
1109
|
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
|
|
976
1110
|
|
|
977
|
-
source = "var __p=''
|
|
978
|
-
"
|
|
1111
|
+
source = "var __t,__p='',__j=Array.prototype.join," +
|
|
1112
|
+
"print=function(){__p+=__j.call(arguments,'');};\n" +
|
|
979
1113
|
source + "return __p;\n";
|
|
980
1114
|
|
|
981
|
-
|
|
1115
|
+
try {
|
|
1116
|
+
var render = new Function(settings.variable || 'obj', '_', source);
|
|
1117
|
+
} catch (e) {
|
|
1118
|
+
e.source = source;
|
|
1119
|
+
throw e;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
982
1122
|
if (data) return render(data, _);
|
|
983
1123
|
var template = function(data) {
|
|
984
1124
|
return render.call(this, data, _);
|
|
985
1125
|
};
|
|
986
1126
|
|
|
987
|
-
// Provide the compiled function source as a convenience for
|
|
988
|
-
|
|
989
|
-
template.source = 'function(' + (settings.variable || 'obj') + '){\n' +
|
|
990
|
-
source + '}';
|
|
1127
|
+
// Provide the compiled function source as a convenience for precompilation.
|
|
1128
|
+
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
|
|
991
1129
|
|
|
992
1130
|
return template;
|
|
993
1131
|
};
|
|
@@ -997,29 +1135,15 @@
|
|
|
997
1135
|
return _(obj).chain();
|
|
998
1136
|
};
|
|
999
1137
|
|
|
1000
|
-
//
|
|
1138
|
+
// OOP
|
|
1001
1139
|
// ---------------
|
|
1002
|
-
|
|
1003
1140
|
// If Underscore is called as a function, it returns a wrapped object that
|
|
1004
1141
|
// can be used OO-style. This wrapper holds altered versions of all the
|
|
1005
1142
|
// underscore functions. Wrapped objects may be chained.
|
|
1006
|
-
var wrapper = function(obj) { this._wrapped = obj; };
|
|
1007
|
-
|
|
1008
|
-
// Expose `wrapper.prototype` as `_.prototype`
|
|
1009
|
-
_.prototype = wrapper.prototype;
|
|
1010
1143
|
|
|
1011
1144
|
// Helper function to continue chaining intermediate results.
|
|
1012
|
-
var result = function(obj
|
|
1013
|
-
return
|
|
1014
|
-
};
|
|
1015
|
-
|
|
1016
|
-
// A method to easily add functions to the OOP wrapper.
|
|
1017
|
-
var addToWrapper = function(name, func) {
|
|
1018
|
-
wrapper.prototype[name] = function() {
|
|
1019
|
-
var args = slice.call(arguments);
|
|
1020
|
-
unshift.call(args, this._wrapped);
|
|
1021
|
-
return result(func.apply(_, args), this._chain);
|
|
1022
|
-
};
|
|
1145
|
+
var result = function(obj) {
|
|
1146
|
+
return this._chain ? _(obj).chain() : obj;
|
|
1023
1147
|
};
|
|
1024
1148
|
|
|
1025
1149
|
// Add all of the Underscore functions to the wrapper object.
|
|
@@ -1028,32 +1152,35 @@
|
|
|
1028
1152
|
// Add all mutator Array functions to the wrapper.
|
|
1029
1153
|
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
|
1030
1154
|
var method = ArrayProto[name];
|
|
1031
|
-
|
|
1032
|
-
var
|
|
1033
|
-
method.apply(
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
return result(wrapped, this._chain);
|
|
1155
|
+
_.prototype[name] = function() {
|
|
1156
|
+
var obj = this._wrapped;
|
|
1157
|
+
method.apply(obj, arguments);
|
|
1158
|
+
if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
|
|
1159
|
+
return result.call(this, obj);
|
|
1037
1160
|
};
|
|
1038
1161
|
});
|
|
1039
1162
|
|
|
1040
1163
|
// Add all accessor Array functions to the wrapper.
|
|
1041
1164
|
each(['concat', 'join', 'slice'], function(name) {
|
|
1042
1165
|
var method = ArrayProto[name];
|
|
1043
|
-
|
|
1044
|
-
return result(method.apply(this._wrapped, arguments)
|
|
1166
|
+
_.prototype[name] = function() {
|
|
1167
|
+
return result.call(this, method.apply(this._wrapped, arguments));
|
|
1045
1168
|
};
|
|
1046
1169
|
});
|
|
1047
1170
|
|
|
1048
|
-
|
|
1049
|
-
wrapper.prototype.chain = function() {
|
|
1050
|
-
this._chain = true;
|
|
1051
|
-
return this;
|
|
1052
|
-
};
|
|
1171
|
+
_.extend(_.prototype, {
|
|
1053
1172
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1173
|
+
// Start chaining a wrapped Underscore object.
|
|
1174
|
+
chain: function() {
|
|
1175
|
+
this._chain = true;
|
|
1176
|
+
return this;
|
|
1177
|
+
},
|
|
1178
|
+
|
|
1179
|
+
// Extracts the result from a wrapped and chained object.
|
|
1180
|
+
value: function() {
|
|
1181
|
+
return this._wrapped;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
});
|
|
1058
1185
|
|
|
1059
1186
|
}).call(this);
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-backbone
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -10,11 +10,11 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2012-
|
|
13
|
+
date: 2012-09-29 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: railties
|
|
17
|
-
requirement: &
|
|
17
|
+
requirement: &70328437701900 !ruby/object:Gem::Requirement
|
|
18
18
|
none: false
|
|
19
19
|
requirements:
|
|
20
20
|
- - ! '>='
|
|
@@ -22,10 +22,10 @@ dependencies:
|
|
|
22
22
|
version: 3.1.0
|
|
23
23
|
type: :runtime
|
|
24
24
|
prerelease: false
|
|
25
|
-
version_requirements: *
|
|
25
|
+
version_requirements: *70328437701900
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: coffee-script
|
|
28
|
-
requirement: &
|
|
28
|
+
requirement: &70328437697400 !ruby/object:Gem::Requirement
|
|
29
29
|
none: false
|
|
30
30
|
requirements:
|
|
31
31
|
- - ~>
|
|
@@ -33,18 +33,106 @@ dependencies:
|
|
|
33
33
|
version: 2.2.0
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
|
-
version_requirements: *
|
|
36
|
+
version_requirements: *70328437697400
|
|
37
|
+
- !ruby/object:Gem::Dependency
|
|
38
|
+
name: jquery-rails
|
|
39
|
+
requirement: &70328437695940 !ruby/object:Gem::Requirement
|
|
40
|
+
none: false
|
|
41
|
+
requirements:
|
|
42
|
+
- - ~>
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: 2.1.3
|
|
45
|
+
type: :runtime
|
|
46
|
+
prerelease: false
|
|
47
|
+
version_requirements: *70328437695940
|
|
37
48
|
- !ruby/object:Gem::Dependency
|
|
38
49
|
name: ejs
|
|
39
|
-
requirement: &
|
|
50
|
+
requirement: &70328437707540 !ruby/object:Gem::Requirement
|
|
40
51
|
none: false
|
|
41
52
|
requirements:
|
|
42
53
|
- - ~>
|
|
43
54
|
- !ruby/object:Gem::Version
|
|
44
|
-
version: 1.
|
|
55
|
+
version: 1.1.1
|
|
45
56
|
type: :runtime
|
|
46
57
|
prerelease: false
|
|
47
|
-
version_requirements: *
|
|
58
|
+
version_requirements: *70328437707540
|
|
59
|
+
- !ruby/object:Gem::Dependency
|
|
60
|
+
name: rails
|
|
61
|
+
requirement: &70328437765580 !ruby/object:Gem::Requirement
|
|
62
|
+
none: false
|
|
63
|
+
requirements:
|
|
64
|
+
- - ~>
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: 3.2.0
|
|
67
|
+
type: :development
|
|
68
|
+
prerelease: false
|
|
69
|
+
version_requirements: *70328437765580
|
|
70
|
+
- !ruby/object:Gem::Dependency
|
|
71
|
+
name: sqlite3
|
|
72
|
+
requirement: &70328437778880 !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ! '>='
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
78
|
+
type: :development
|
|
79
|
+
prerelease: false
|
|
80
|
+
version_requirements: *70328437778880
|
|
81
|
+
- !ruby/object:Gem::Dependency
|
|
82
|
+
name: sass
|
|
83
|
+
requirement: &70328437776700 !ruby/object:Gem::Requirement
|
|
84
|
+
none: false
|
|
85
|
+
requirements:
|
|
86
|
+
- - ! '>='
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: *70328437776700
|
|
92
|
+
- !ruby/object:Gem::Dependency
|
|
93
|
+
name: uglifier
|
|
94
|
+
requirement: &70328437772440 !ruby/object:Gem::Requirement
|
|
95
|
+
none: false
|
|
96
|
+
requirements:
|
|
97
|
+
- - ! '>='
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '0'
|
|
100
|
+
type: :development
|
|
101
|
+
prerelease: false
|
|
102
|
+
version_requirements: *70328437772440
|
|
103
|
+
- !ruby/object:Gem::Dependency
|
|
104
|
+
name: mocha
|
|
105
|
+
requirement: &70328437785780 !ruby/object:Gem::Requirement
|
|
106
|
+
none: false
|
|
107
|
+
requirements:
|
|
108
|
+
- - ~>
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 0.10.3
|
|
111
|
+
type: :development
|
|
112
|
+
prerelease: false
|
|
113
|
+
version_requirements: *70328437785780
|
|
114
|
+
- !ruby/object:Gem::Dependency
|
|
115
|
+
name: turn
|
|
116
|
+
requirement: &70328437802400 !ruby/object:Gem::Requirement
|
|
117
|
+
none: false
|
|
118
|
+
requirements:
|
|
119
|
+
- - ~>
|
|
120
|
+
- !ruby/object:Gem::Version
|
|
121
|
+
version: 0.8.3
|
|
122
|
+
type: :development
|
|
123
|
+
prerelease: false
|
|
124
|
+
version_requirements: *70328437802400
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: minitest
|
|
127
|
+
requirement: &70328437800700 !ruby/object:Gem::Requirement
|
|
128
|
+
none: false
|
|
129
|
+
requirements:
|
|
130
|
+
- - ~>
|
|
131
|
+
- !ruby/object:Gem::Version
|
|
132
|
+
version: 2.10.1
|
|
133
|
+
type: :development
|
|
134
|
+
prerelease: false
|
|
135
|
+
version_requirements: *70328437800700
|
|
48
136
|
description: Quickly setup backbone.js for use with rails 3.1. Generators are provided
|
|
49
137
|
to quickly get started.
|
|
50
138
|
email:
|
|
@@ -99,13 +187,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
99
187
|
version: '0'
|
|
100
188
|
segments:
|
|
101
189
|
- 0
|
|
102
|
-
hash:
|
|
190
|
+
hash: -1632237313035377260
|
|
103
191
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
192
|
none: false
|
|
105
193
|
requirements:
|
|
106
194
|
- - ! '>='
|
|
107
195
|
- !ruby/object:Gem::Version
|
|
108
196
|
version: '0'
|
|
197
|
+
segments:
|
|
198
|
+
- 0
|
|
199
|
+
hash: -1632237313035377260
|
|
109
200
|
requirements: []
|
|
110
201
|
rubyforge_project:
|
|
111
202
|
rubygems_version: 1.8.11
|