mix-rails-core 0.12.1 → 0.12.2

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