omf_web 0.9.9 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +31 -0
  3. data/bin/omf_web_server.rb +157 -0
  4. data/doc/screenshot2.png +0 -0
  5. data/doc/widget_detail.png +0 -0
  6. data/example/demo/data_sources/downloads.rb +2 -1
  7. data/example/simple/README.md +12 -13
  8. data/example/simple/create_waveform.rb +29 -0
  9. data/example/simple/introduction.md +17 -0
  10. data/example/simple/sample.sq3 +0 -0
  11. data/example/simple/sample.sql +1008 -0
  12. data/example/simple/simple.yaml +62 -0
  13. data/example/simple/simple_dynamic.yaml +66 -0
  14. data/lib/irods4r/file.rb +15 -14
  15. data/lib/irods4r/icommands.rb +18 -18
  16. data/lib/irods4r.rb +9 -9
  17. data/lib/omf-web/config.ru +41 -16
  18. data/lib/omf-web/content/git_repository.rb +32 -31
  19. data/lib/omf-web/content/irods_repository.rb +34 -33
  20. data/lib/omf-web/content/repository.rb +48 -44
  21. data/lib/omf-web/data_source_proxy.rb +33 -22
  22. data/lib/omf-web/rack/session_authenticator.rb +48 -12
  23. data/lib/omf-web/rack/tab_mapper.rb +30 -36
  24. data/lib/omf-web/rack/websocket_handler.rb +26 -25
  25. data/lib/omf-web/session_store.rb +16 -13
  26. data/lib/omf-web/theme/abstract_page.rb +26 -22
  27. data/lib/omf-web/theme/bright/page.rb +84 -34
  28. data/lib/omf-web/theme/bright/stacked_renderer.rb +20 -19
  29. data/lib/omf-web/theme.rb +14 -9
  30. data/lib/omf-web/thin/runner.rb +38 -36
  31. data/lib/omf-web/thin/server.rb +255 -0
  32. data/lib/omf-web/version.rb +1 -1
  33. data/lib/omf-web/widget/data_widget.rb +6 -6
  34. data/lib/omf-web/widget/text/maruku/helpers.rb +33 -30
  35. data/lib/omf-web/widget/text/maruku/input/parse_block.rb +117 -117
  36. data/lib/omf-web/widget/text/maruku/output/to_html.rb +155 -154
  37. data/lib/omf-web/widget/text/maruku.rb +17 -16
  38. data/omf_web.gemspec +6 -2
  39. data/sample.sq3 +0 -0
  40. data/share/htdocs/graph/js/gauge.js +524 -0
  41. data/share/htdocs/vendor/VERSION_MAP.yaml +3 -3
  42. data/share/htdocs/vendor/backbone-1.0.0/backbone.js +1571 -0
  43. data/share/htdocs/vendor/d3-3.0/LICENSE.brewer.txt +38 -0
  44. data/share/htdocs/vendor/d3-3.0/colorbrewer.js +1 -0
  45. data/share/htdocs/vendor/d3-3.0/d3.js +8810 -0
  46. data/share/htdocs/vendor/d3-3.0/d3.min.js +5 -0
  47. data/share/htdocs/vendor/geo_json/Readme.txt +71 -0
  48. data/share/htdocs/vendor/geo_json/regions.json +41 -0
  49. data/share/htdocs/vendor/geo_json/switzerland.json +24 -0
  50. data/share/htdocs/vendor/geo_json/world.json +497 -0
  51. data/share/htdocs/vendor/nv_d3/js/nv.d3.js +8801 -4447
  52. data/share/htdocs/vendor/spin/jquery.spin.js +46 -0
  53. data/share/htdocs/vendor/spin/spin.js +349 -0
  54. data/share/htdocs/vendor/spin/spin.min.js +1 -0
  55. data/share/htdocs/vendor/underscore-1.4.4/underscore.js +1227 -0
  56. metadata +63 -48
  57. data/example/simple/data_sources/gimi31.sq3 +0 -0
  58. data/example/simple/data_sources/ping_source.rb +0 -56
  59. data/example/simple/simple_viz_server.rb +0 -39
  60. data/example/simple/widgets/charts_tab.yaml +0 -38
  61. data/share/.DS_Store +0 -0
  62. data/share/htdocs/.DS_Store +0 -0
  63. data/share/htdocs/vendor/backbone-0.5.3/backbone.js +0 -1158
  64. data/share/htdocs/vendor/underscore-1.2.1/underscore.js +0 -958
@@ -1,958 +0,0 @@
1
- // Underscore.js 1.2.1
2
- // (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
3
- // Underscore is freely distributable under the MIT license.
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
8
-
9
- (function() {
10
-
11
- // Baseline setup
12
- // --------------
13
-
14
- // Establish the root object, `window` in the browser, or `global` on the server.
15
- var root = this;
16
-
17
- // Save the previous value of the `_` variable.
18
- var previousUnderscore = root._;
19
-
20
- // Establish the object that gets returned to break out of a loop iteration.
21
- var breaker = {};
22
-
23
- // Save bytes in the minified (but not gzipped) version:
24
- var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
25
-
26
- // Create quick reference variables for speed access to core prototypes.
27
- var slice = ArrayProto.slice,
28
- unshift = ArrayProto.unshift,
29
- toString = ObjProto.toString,
30
- hasOwnProperty = ObjProto.hasOwnProperty;
31
-
32
- // All **ECMAScript 5** native function implementations that we hope to use
33
- // are declared here.
34
- var
35
- nativeForEach = ArrayProto.forEach,
36
- nativeMap = ArrayProto.map,
37
- nativeReduce = ArrayProto.reduce,
38
- nativeReduceRight = ArrayProto.reduceRight,
39
- nativeFilter = ArrayProto.filter,
40
- nativeEvery = ArrayProto.every,
41
- nativeSome = ArrayProto.some,
42
- nativeIndexOf = ArrayProto.indexOf,
43
- nativeLastIndexOf = ArrayProto.lastIndexOf,
44
- nativeIsArray = Array.isArray,
45
- nativeKeys = Object.keys,
46
- nativeBind = FuncProto.bind;
47
-
48
- // Create a safe reference to the Underscore object for use below.
49
- var _ = function(obj) { return new wrapper(obj); };
50
-
51
- // Export the Underscore object for **Node.js** and **"CommonJS"**, with
52
- // backwards-compatibility for the old `require()` API. If we're not in
53
- // CommonJS, add `_` to the global object.
54
- if (typeof exports !== 'undefined') {
55
- if (typeof module !== 'undefined' && module.exports) {
56
- exports = module.exports = _;
57
- }
58
- exports._ = _;
59
- } else if (typeof define === 'function' && define.amd) {
60
- // Register as a named module with AMD.
61
- define('underscore', function() {
62
- return _;
63
- });
64
- } else {
65
- // Exported as a string, for Closure Compiler "advanced" mode.
66
- root['_'] = _;
67
- }
68
-
69
- // Current version.
70
- _.VERSION = '1.2.1';
71
-
72
- // Collection Functions
73
- // --------------------
74
-
75
- // The cornerstone, an `each` implementation, aka `forEach`.
76
- // Handles objects with the built-in `forEach`, arrays, and raw objects.
77
- // Delegates to **ECMAScript 5**'s native `forEach` if available.
78
- var each = _.each = _.forEach = function(obj, iterator, context) {
79
- if (obj == null) return;
80
- if (nativeForEach && obj.forEach === nativeForEach) {
81
- obj.forEach(iterator, context);
82
- } else if (obj.length === +obj.length) {
83
- for (var i = 0, l = obj.length; i < l; i++) {
84
- if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
85
- }
86
- } else {
87
- for (var key in obj) {
88
- if (hasOwnProperty.call(obj, key)) {
89
- if (iterator.call(context, obj[key], key, obj) === breaker) return;
90
- }
91
- }
92
- }
93
- };
94
-
95
- // Return the results of applying the iterator to each element.
96
- // Delegates to **ECMAScript 5**'s native `map` if available.
97
- _.map = function(obj, iterator, context) {
98
- var results = [];
99
- if (obj == null) return results;
100
- if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
101
- each(obj, function(value, index, list) {
102
- results[results.length] = iterator.call(context, value, index, list);
103
- });
104
- return results;
105
- };
106
-
107
- // **Reduce** builds up a single result from a list of values, aka `inject`,
108
- // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
109
- _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
110
- var initial = memo !== void 0;
111
- if (obj == null) obj = [];
112
- if (nativeReduce && obj.reduce === nativeReduce) {
113
- if (context) iterator = _.bind(iterator, context);
114
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
115
- }
116
- each(obj, function(value, index, list) {
117
- if (!initial) {
118
- memo = value;
119
- initial = true;
120
- } else {
121
- memo = iterator.call(context, memo, value, index, list);
122
- }
123
- });
124
- if (!initial) throw new TypeError("Reduce of empty array with no initial value");
125
- return memo;
126
- };
127
-
128
- // The right-associative version of reduce, also known as `foldr`.
129
- // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
130
- _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
131
- if (obj == null) obj = [];
132
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
133
- if (context) iterator = _.bind(iterator, context);
134
- return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
135
- }
136
- var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
137
- return _.reduce(reversed, iterator, memo, context);
138
- };
139
-
140
- // Return the first value which passes a truth test. Aliased as `detect`.
141
- _.find = _.detect = function(obj, iterator, context) {
142
- var result;
143
- any(obj, function(value, index, list) {
144
- if (iterator.call(context, value, index, list)) {
145
- result = value;
146
- return true;
147
- }
148
- });
149
- return result;
150
- };
151
-
152
- // Return all the elements that pass a truth test.
153
- // Delegates to **ECMAScript 5**'s native `filter` if available.
154
- // Aliased as `select`.
155
- _.filter = _.select = function(obj, iterator, context) {
156
- var results = [];
157
- if (obj == null) return results;
158
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
159
- each(obj, function(value, index, list) {
160
- if (iterator.call(context, value, index, list)) results[results.length] = value;
161
- });
162
- return results;
163
- };
164
-
165
- // Return all the elements for which a truth test fails.
166
- _.reject = function(obj, iterator, context) {
167
- var results = [];
168
- if (obj == null) return results;
169
- each(obj, function(value, index, list) {
170
- if (!iterator.call(context, value, index, list)) results[results.length] = value;
171
- });
172
- return results;
173
- };
174
-
175
- // Determine whether all of the elements match a truth test.
176
- // Delegates to **ECMAScript 5**'s native `every` if available.
177
- // Aliased as `all`.
178
- _.every = _.all = function(obj, iterator, context) {
179
- var result = true;
180
- if (obj == null) return result;
181
- if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
182
- each(obj, function(value, index, list) {
183
- if (!(result = result && iterator.call(context, value, index, list))) return breaker;
184
- });
185
- return result;
186
- };
187
-
188
- // Determine if at least one element in the object matches a truth test.
189
- // Delegates to **ECMAScript 5**'s native `some` if available.
190
- // Aliased as `any`.
191
- var any = _.some = _.any = function(obj, iterator, context) {
192
- iterator = iterator || _.identity;
193
- var result = false;
194
- if (obj == null) return result;
195
- if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
196
- each(obj, function(value, index, list) {
197
- if (result |= iterator.call(context, value, index, list)) return breaker;
198
- });
199
- return !!result;
200
- };
201
-
202
- // Determine if a given value is included in the array or object using `===`.
203
- // Aliased as `contains`.
204
- _.include = _.contains = function(obj, target) {
205
- var found = false;
206
- if (obj == null) return found;
207
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
208
- found = any(obj, function(value) {
209
- if (value === target) return true;
210
- });
211
- return found;
212
- };
213
-
214
- // Invoke a method (with arguments) on every item in a collection.
215
- _.invoke = function(obj, method) {
216
- var args = slice.call(arguments, 2);
217
- return _.map(obj, function(value) {
218
- return (method.call ? method || value : value[method]).apply(value, args);
219
- });
220
- };
221
-
222
- // Convenience version of a common use case of `map`: fetching a property.
223
- _.pluck = function(obj, key) {
224
- return _.map(obj, function(value){ return value[key]; });
225
- };
226
-
227
- // Return the maximum element or (element-based computation).
228
- _.max = function(obj, iterator, context) {
229
- if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
230
- if (!iterator && _.isEmpty(obj)) return -Infinity;
231
- var result = {computed : -Infinity};
232
- each(obj, function(value, index, list) {
233
- var computed = iterator ? iterator.call(context, value, index, list) : value;
234
- computed >= result.computed && (result = {value : value, computed : computed});
235
- });
236
- return result.value;
237
- };
238
-
239
- // Return the minimum element (or element-based computation).
240
- _.min = function(obj, iterator, context) {
241
- if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
242
- if (!iterator && _.isEmpty(obj)) return Infinity;
243
- var result = {computed : Infinity};
244
- each(obj, function(value, index, list) {
245
- var computed = iterator ? iterator.call(context, value, index, list) : value;
246
- computed < result.computed && (result = {value : value, computed : computed});
247
- });
248
- return result.value;
249
- };
250
-
251
- // Shuffle an array.
252
- _.shuffle = function(obj) {
253
- var shuffled = [], rand;
254
- each(obj, function(value, index, list) {
255
- if (index == 0) {
256
- shuffled[0] = value;
257
- } else {
258
- rand = Math.floor(Math.random() * (index + 1));
259
- shuffled[index] = shuffled[rand];
260
- shuffled[rand] = value;
261
- }
262
- });
263
- return shuffled;
264
- };
265
-
266
- // Sort the object's values by a criterion produced by an iterator.
267
- _.sortBy = function(obj, iterator, context) {
268
- return _.pluck(_.map(obj, function(value, index, list) {
269
- return {
270
- value : value,
271
- criteria : iterator.call(context, value, index, list)
272
- };
273
- }).sort(function(left, right) {
274
- var a = left.criteria, b = right.criteria;
275
- return a < b ? -1 : a > b ? 1 : 0;
276
- }), 'value');
277
- };
278
-
279
- // Groups the object's values by a criterion. Pass either a string attribute
280
- // to group by, or a function that returns the criterion.
281
- _.groupBy = function(obj, val) {
282
- var result = {};
283
- var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
284
- each(obj, function(value, index) {
285
- var key = iterator(value, index);
286
- (result[key] || (result[key] = [])).push(value);
287
- });
288
- return result;
289
- };
290
-
291
- // Use a comparator function to figure out at what index an object should
292
- // be inserted so as to maintain order. Uses binary search.
293
- _.sortedIndex = function(array, obj, iterator) {
294
- iterator || (iterator = _.identity);
295
- var low = 0, high = array.length;
296
- while (low < high) {
297
- var mid = (low + high) >> 1;
298
- iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
299
- }
300
- return low;
301
- };
302
-
303
- // Safely convert anything iterable into a real, live array.
304
- _.toArray = function(iterable) {
305
- if (!iterable) return [];
306
- if (iterable.toArray) return iterable.toArray();
307
- if (_.isArray(iterable)) return slice.call(iterable);
308
- if (_.isArguments(iterable)) return slice.call(iterable);
309
- return _.values(iterable);
310
- };
311
-
312
- // Return the number of elements in an object.
313
- _.size = function(obj) {
314
- return _.toArray(obj).length;
315
- };
316
-
317
- // Array Functions
318
- // ---------------
319
-
320
- // Get the first element of an array. Passing **n** will return the first N
321
- // values in the array. Aliased as `head`. The **guard** check allows it to work
322
- // with `_.map`.
323
- _.first = _.head = function(array, n, guard) {
324
- return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
325
- };
326
-
327
- // Returns everything but the last entry of the array. Especcialy useful on
328
- // the arguments object. Passing **n** will return all the values in
329
- // the array, excluding the last N. The **guard** check allows it to work with
330
- // `_.map`.
331
- _.initial = function(array, n, guard) {
332
- return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
333
- };
334
-
335
- // Get the last element of an array. Passing **n** will return the last N
336
- // values in the array. The **guard** check allows it to work with `_.map`.
337
- _.last = function(array, n, guard) {
338
- return (n != null) && !guard ? slice.call(array, array.length - n) : array[array.length - 1];
339
- };
340
-
341
- // Returns everything but the first entry of the array. Aliased as `tail`.
342
- // Especially useful on the arguments object. Passing an **index** will return
343
- // the rest of the values in the array from that index onward. The **guard**
344
- // check allows it to work with `_.map`.
345
- _.rest = _.tail = function(array, index, guard) {
346
- return slice.call(array, (index == null) || guard ? 1 : index);
347
- };
348
-
349
- // Trim out all falsy values from an array.
350
- _.compact = function(array) {
351
- return _.filter(array, function(value){ return !!value; });
352
- };
353
-
354
- // Return a completely flattened version of an array.
355
- _.flatten = function(array, shallow) {
356
- return _.reduce(array, function(memo, value) {
357
- if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
358
- memo[memo.length] = value;
359
- return memo;
360
- }, []);
361
- };
362
-
363
- // Return a version of the array that does not contain the specified value(s).
364
- _.without = function(array) {
365
- return _.difference(array, slice.call(arguments, 1));
366
- };
367
-
368
- // Produce a duplicate-free version of the array. If the array has already
369
- // been sorted, you have the option of using a faster algorithm.
370
- // Aliased as `unique`.
371
- _.uniq = _.unique = function(array, isSorted, iterator) {
372
- var initial = iterator ? _.map(array, iterator) : array;
373
- var result = [];
374
- _.reduce(initial, function(memo, el, i) {
375
- if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
376
- memo[memo.length] = el;
377
- result[result.length] = array[i];
378
- }
379
- return memo;
380
- }, []);
381
- return result;
382
- };
383
-
384
- // Produce an array that contains the union: each distinct element from all of
385
- // the passed-in arrays.
386
- _.union = function() {
387
- return _.uniq(_.flatten(arguments, true));
388
- };
389
-
390
- // Produce an array that contains every item shared between all the
391
- // passed-in arrays. (Aliased as "intersect" for back-compat.)
392
- _.intersection = _.intersect = function(array) {
393
- var rest = slice.call(arguments, 1);
394
- return _.filter(_.uniq(array), function(item) {
395
- return _.every(rest, function(other) {
396
- return _.indexOf(other, item) >= 0;
397
- });
398
- });
399
- };
400
-
401
- // Take the difference between one array and another.
402
- // Only the elements present in just the first array will remain.
403
- _.difference = function(array, other) {
404
- return _.filter(array, function(value){ return !_.include(other, value); });
405
- };
406
-
407
- // Zip together multiple lists into a single array -- elements that share
408
- // an index go together.
409
- _.zip = function() {
410
- var args = slice.call(arguments);
411
- var length = _.max(_.pluck(args, 'length'));
412
- var results = new Array(length);
413
- for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
414
- return results;
415
- };
416
-
417
- // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
418
- // we need this function. Return the position of the first occurrence of an
419
- // item in an array, or -1 if the item is not included in the array.
420
- // Delegates to **ECMAScript 5**'s native `indexOf` if available.
421
- // If the array is large and already in sort order, pass `true`
422
- // for **isSorted** to use binary search.
423
- _.indexOf = function(array, item, isSorted) {
424
- if (array == null) return -1;
425
- var i, l;
426
- if (isSorted) {
427
- i = _.sortedIndex(array, item);
428
- return array[i] === item ? i : -1;
429
- }
430
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
431
- for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
432
- return -1;
433
- };
434
-
435
- // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
436
- _.lastIndexOf = function(array, item) {
437
- if (array == null) return -1;
438
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
439
- var i = array.length;
440
- while (i--) if (array[i] === item) return i;
441
- return -1;
442
- };
443
-
444
- // Generate an integer Array containing an arithmetic progression. A port of
445
- // the native Python `range()` function. See
446
- // [the Python documentation](http://docs.python.org/library/functions.html#range).
447
- _.range = function(start, stop, step) {
448
- if (arguments.length <= 1) {
449
- stop = start || 0;
450
- start = 0;
451
- }
452
- step = arguments[2] || 1;
453
-
454
- var len = Math.max(Math.ceil((stop - start) / step), 0);
455
- var idx = 0;
456
- var range = new Array(len);
457
-
458
- while(idx < len) {
459
- range[idx++] = start;
460
- start += step;
461
- }
462
-
463
- return range;
464
- };
465
-
466
- // Function (ahem) Functions
467
- // ------------------
468
-
469
- // Reusable constructor function for prototype setting.
470
- var ctor = function(){};
471
-
472
- // Create a function bound to a given object (assigning `this`, and arguments,
473
- // optionally). Binding with arguments is also known as `curry`.
474
- // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
475
- // We check for `func.bind` first, to fail fast when `func` is undefined.
476
- _.bind = function bind(func, context) {
477
- var bound, args;
478
- if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
479
- if (!_.isFunction(func)) throw new TypeError;
480
- args = slice.call(arguments, 2);
481
- return bound = function() {
482
- if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
483
- ctor.prototype = func.prototype;
484
- var self = new ctor;
485
- var result = func.apply(self, args.concat(slice.call(arguments)));
486
- if (Object(result) === result) return result;
487
- return self;
488
- };
489
- };
490
-
491
- // Bind all of an object's methods to that object. Useful for ensuring that
492
- // all callbacks defined on an object belong to it.
493
- _.bindAll = function(obj) {
494
- var funcs = slice.call(arguments, 1);
495
- if (funcs.length == 0) funcs = _.functions(obj);
496
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
497
- return obj;
498
- };
499
-
500
- // Memoize an expensive function by storing its results.
501
- _.memoize = function(func, hasher) {
502
- var memo = {};
503
- hasher || (hasher = _.identity);
504
- return function() {
505
- var key = hasher.apply(this, arguments);
506
- return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
507
- };
508
- };
509
-
510
- // Delays a function for the given number of milliseconds, and then calls
511
- // it with the arguments supplied.
512
- _.delay = function(func, wait) {
513
- var args = slice.call(arguments, 2);
514
- return setTimeout(function(){ return func.apply(func, args); }, wait);
515
- };
516
-
517
- // Defers a function, scheduling it to run after the current call stack has
518
- // cleared.
519
- _.defer = function(func) {
520
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
521
- };
522
-
523
- // Returns a function, that, when invoked, will only be triggered at most once
524
- // during a given window of time.
525
- _.throttle = function(func, wait) {
526
- var timeout, context, args, throttling, finishThrottle;
527
- finishThrottle = _.debounce(function(){ throttling = false; }, wait);
528
- return function() {
529
- context = this; args = arguments;
530
- var throttler = function() {
531
- timeout = null;
532
- func.apply(context, args);
533
- finishThrottle();
534
- };
535
- if (!timeout) timeout = setTimeout(throttler, wait);
536
- if (!throttling) func.apply(context, args);
537
- if (finishThrottle) finishThrottle();
538
- throttling = true;
539
- };
540
- };
541
-
542
- // Returns a function, that, as long as it continues to be invoked, will not
543
- // be triggered. The function will be called after it stops being called for
544
- // N milliseconds.
545
- _.debounce = function(func, wait) {
546
- var timeout;
547
- return function() {
548
- var context = this, args = arguments;
549
- var throttler = function() {
550
- timeout = null;
551
- func.apply(context, args);
552
- };
553
- clearTimeout(timeout);
554
- timeout = setTimeout(throttler, wait);
555
- };
556
- };
557
-
558
- // Returns a function that will be executed at most one time, no matter how
559
- // often you call it. Useful for lazy initialization.
560
- _.once = function(func) {
561
- var ran = false, memo;
562
- return function() {
563
- if (ran) return memo;
564
- ran = true;
565
- return memo = func.apply(this, arguments);
566
- };
567
- };
568
-
569
- // Returns the first function passed as an argument to the second,
570
- // allowing you to adjust arguments, run code before and after, and
571
- // conditionally execute the original function.
572
- _.wrap = function(func, wrapper) {
573
- return function() {
574
- var args = [func].concat(slice.call(arguments));
575
- return wrapper.apply(this, args);
576
- };
577
- };
578
-
579
- // Returns a function that is the composition of a list of functions, each
580
- // consuming the return value of the function that follows.
581
- _.compose = function() {
582
- var funcs = slice.call(arguments);
583
- return function() {
584
- var args = slice.call(arguments);
585
- for (var i = funcs.length - 1; i >= 0; i--) {
586
- args = [funcs[i].apply(this, args)];
587
- }
588
- return args[0];
589
- };
590
- };
591
-
592
- // Returns a function that will only be executed after being called N times.
593
- _.after = function(times, func) {
594
- return function() {
595
- if (--times < 1) { return func.apply(this, arguments); }
596
- };
597
- };
598
-
599
- // Object Functions
600
- // ----------------
601
-
602
- // Retrieve the names of an object's properties.
603
- // Delegates to **ECMAScript 5**'s native `Object.keys`
604
- _.keys = nativeKeys || function(obj) {
605
- if (obj !== Object(obj)) throw new TypeError('Invalid object');
606
- var keys = [];
607
- for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
608
- return keys;
609
- };
610
-
611
- // Retrieve the values of an object's properties.
612
- _.values = function(obj) {
613
- return _.map(obj, _.identity);
614
- };
615
-
616
- // Return a sorted list of the function names available on the object.
617
- // Aliased as `methods`
618
- _.functions = _.methods = function(obj) {
619
- var names = [];
620
- for (var key in obj) {
621
- if (_.isFunction(obj[key])) names.push(key);
622
- }
623
- return names.sort();
624
- };
625
-
626
- // Extend a given object with all the properties in passed-in object(s).
627
- _.extend = function(obj) {
628
- each(slice.call(arguments, 1), function(source) {
629
- for (var prop in source) {
630
- if (source[prop] !== void 0) obj[prop] = source[prop];
631
- }
632
- });
633
- return obj;
634
- };
635
-
636
- // Fill in a given object with default properties.
637
- _.defaults = function(obj) {
638
- each(slice.call(arguments, 1), function(source) {
639
- for (var prop in source) {
640
- if (obj[prop] == null) obj[prop] = source[prop];
641
- }
642
- });
643
- return obj;
644
- };
645
-
646
- // Create a (shallow-cloned) duplicate of an object.
647
- _.clone = function(obj) {
648
- if (!_.isObject(obj)) return obj;
649
- return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
650
- };
651
-
652
- // Invokes interceptor with the obj, and then returns obj.
653
- // The primary purpose of this method is to "tap into" a method chain, in
654
- // order to perform operations on intermediate results within the chain.
655
- _.tap = function(obj, interceptor) {
656
- interceptor(obj);
657
- return obj;
658
- };
659
-
660
- // Internal recursive comparison function.
661
- function eq(a, b, stack) {
662
- // Identical objects are equal. `0 === -0`, but they aren't identical.
663
- // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
664
- if (a === b) return a !== 0 || 1 / a == 1 / b;
665
- // A strict comparison is necessary because `null == undefined`.
666
- if ((a == null) || (b == null)) return a === b;
667
- // Unwrap any wrapped objects.
668
- if (a._chain) a = a._wrapped;
669
- if (b._chain) b = b._wrapped;
670
- // Invoke a custom `isEqual` method if one is provided.
671
- if (_.isFunction(a.isEqual)) return a.isEqual(b);
672
- if (_.isFunction(b.isEqual)) return b.isEqual(a);
673
- // Compare object types.
674
- var typeA = typeof a;
675
- if (typeA != typeof b) return false;
676
- // Optimization; ensure that both values are truthy or falsy.
677
- if (!a != !b) return false;
678
- // `NaN` values are equal.
679
- if (_.isNaN(a)) return _.isNaN(b);
680
- // Compare string objects by value.
681
- var isStringA = _.isString(a), isStringB = _.isString(b);
682
- if (isStringA || isStringB) return isStringA && isStringB && String(a) == String(b);
683
- // Compare number objects by value.
684
- var isNumberA = _.isNumber(a), isNumberB = _.isNumber(b);
685
- if (isNumberA || isNumberB) return isNumberA && isNumberB && +a == +b;
686
- // Compare boolean objects by value. The value of `true` is 1; the value of `false` is 0.
687
- var isBooleanA = _.isBoolean(a), isBooleanB = _.isBoolean(b);
688
- if (isBooleanA || isBooleanB) return isBooleanA && isBooleanB && +a == +b;
689
- // Compare dates by their millisecond values.
690
- var isDateA = _.isDate(a), isDateB = _.isDate(b);
691
- if (isDateA || isDateB) return isDateA && isDateB && a.getTime() == b.getTime();
692
- // Compare RegExps by their source patterns and flags.
693
- var isRegExpA = _.isRegExp(a), isRegExpB = _.isRegExp(b);
694
- if (isRegExpA || isRegExpB) {
695
- // Ensure commutative equality for RegExps.
696
- return isRegExpA && isRegExpB &&
697
- a.source == b.source &&
698
- a.global == b.global &&
699
- a.multiline == b.multiline &&
700
- a.ignoreCase == b.ignoreCase;
701
- }
702
- // Ensure that both values are objects.
703
- if (typeA != 'object') return false;
704
- // Arrays or Arraylikes with different lengths are not equal.
705
- if (a.length !== b.length) return false;
706
- // Objects with different constructors are not equal.
707
- if (a.constructor !== b.constructor) return false;
708
- // Assume equality for cyclic structures. The algorithm for detecting cyclic
709
- // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
710
- var length = stack.length;
711
- while (length--) {
712
- // Linear search. Performance is inversely proportional to the number of
713
- // unique nested structures.
714
- if (stack[length] == a) return true;
715
- }
716
- // Add the first object to the stack of traversed objects.
717
- stack.push(a);
718
- var size = 0, result = true;
719
- // Deep compare objects.
720
- for (var key in a) {
721
- if (hasOwnProperty.call(a, key)) {
722
- // Count the expected number of properties.
723
- size++;
724
- // Deep compare each member.
725
- if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
726
- }
727
- }
728
- // Ensure that both objects contain the same number of properties.
729
- if (result) {
730
- for (key in b) {
731
- if (hasOwnProperty.call(b, key) && !size--) break;
732
- }
733
- result = !size;
734
- }
735
- // Remove the first object from the stack of traversed objects.
736
- stack.pop();
737
- return result;
738
- }
739
-
740
- // Perform a deep comparison to check if two objects are equal.
741
- _.isEqual = function(a, b) {
742
- return eq(a, b, []);
743
- };
744
-
745
- // Is a given array, string, or object empty?
746
- // An "empty" object has no enumerable own-properties.
747
- _.isEmpty = function(obj) {
748
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
749
- for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
750
- return true;
751
- };
752
-
753
- // Is a given value a DOM element?
754
- _.isElement = function(obj) {
755
- return !!(obj && obj.nodeType == 1);
756
- };
757
-
758
- // Is a given value an array?
759
- // Delegates to ECMA5's native Array.isArray
760
- _.isArray = nativeIsArray || function(obj) {
761
- return toString.call(obj) == '[object Array]';
762
- };
763
-
764
- // Is a given variable an object?
765
- _.isObject = function(obj) {
766
- return obj === Object(obj);
767
- };
768
-
769
- // Is a given variable an arguments object?
770
- if (toString.call(arguments) == '[object Arguments]') {
771
- _.isArguments = function(obj) {
772
- return toString.call(obj) == '[object Arguments]';
773
- };
774
- } else {
775
- _.isArguments = function(obj) {
776
- return !!(obj && hasOwnProperty.call(obj, 'callee'));
777
- };
778
- }
779
-
780
- // Is a given value a function?
781
- _.isFunction = function(obj) {
782
- return toString.call(obj) == '[object Function]';
783
- };
784
-
785
- // Is a given value a string?
786
- _.isString = function(obj) {
787
- return toString.call(obj) == '[object String]';
788
- };
789
-
790
- // Is a given value a number?
791
- _.isNumber = function(obj) {
792
- return toString.call(obj) == '[object Number]';
793
- };
794
-
795
- // Is the given value `NaN`?
796
- _.isNaN = function(obj) {
797
- // `NaN` is the only value for which `===` is not reflexive.
798
- return obj !== obj;
799
- };
800
-
801
- // Is a given value a boolean?
802
- _.isBoolean = function(obj) {
803
- return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
804
- };
805
-
806
- // Is a given value a date?
807
- _.isDate = function(obj) {
808
- return toString.call(obj) == '[object Date]';
809
- };
810
-
811
- // Is the given value a regular expression?
812
- _.isRegExp = function(obj) {
813
- return toString.call(obj) == '[object RegExp]';
814
- };
815
-
816
- // Is a given value equal to null?
817
- _.isNull = function(obj) {
818
- return obj === null;
819
- };
820
-
821
- // Is a given variable undefined?
822
- _.isUndefined = function(obj) {
823
- return obj === void 0;
824
- };
825
-
826
- // Utility Functions
827
- // -----------------
828
-
829
- // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
830
- // previous owner. Returns a reference to the Underscore object.
831
- _.noConflict = function() {
832
- root._ = previousUnderscore;
833
- return this;
834
- };
835
-
836
- // Keep the identity function around for default iterators.
837
- _.identity = function(value) {
838
- return value;
839
- };
840
-
841
- // Run a function **n** times.
842
- _.times = function (n, iterator, context) {
843
- for (var i = 0; i < n; i++) iterator.call(context, i);
844
- };
845
-
846
- // Escape a string for HTML interpolation.
847
- _.escape = function(string) {
848
- return (''+string).replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
849
- };
850
-
851
- // Add your own custom functions to the Underscore object, ensuring that
852
- // they're correctly added to the OOP wrapper as well.
853
- _.mixin = function(obj) {
854
- each(_.functions(obj), function(name){
855
- addToWrapper(name, _[name] = obj[name]);
856
- });
857
- };
858
-
859
- // Generate a unique integer id (unique within the entire client session).
860
- // Useful for temporary DOM ids.
861
- var idCounter = 0;
862
- _.uniqueId = function(prefix) {
863
- var id = idCounter++;
864
- return prefix ? prefix + id : id;
865
- };
866
-
867
- // By default, Underscore uses ERB-style template delimiters, change the
868
- // following template settings to use alternative delimiters.
869
- _.templateSettings = {
870
- evaluate : /<%([\s\S]+?)%>/g,
871
- interpolate : /<%=([\s\S]+?)%>/g,
872
- escape : /<%-([\s\S]+?)%>/g
873
- };
874
-
875
- // JavaScript micro-templating, similar to John Resig's implementation.
876
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
877
- // and correctly escapes quotes within interpolated code.
878
- _.template = function(str, data) {
879
- var c = _.templateSettings;
880
- var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
881
- 'with(obj||{}){__p.push(\'' +
882
- str.replace(/\\/g, '\\\\')
883
- .replace(/'/g, "\\'")
884
- .replace(c.escape, function(match, code) {
885
- return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";
886
- })
887
- .replace(c.interpolate, function(match, code) {
888
- return "'," + code.replace(/\\'/g, "'") + ",'";
889
- })
890
- .replace(c.evaluate || null, function(match, code) {
891
- return "');" + code.replace(/\\'/g, "'")
892
- .replace(/[\r\n\t]/g, ' ') + "__p.push('";
893
- })
894
- .replace(/\r/g, '\\r')
895
- .replace(/\n/g, '\\n')
896
- .replace(/\t/g, '\\t')
897
- + "');}return __p.join('');";
898
- var func = new Function('obj', tmpl);
899
- return data ? func(data) : func;
900
- };
901
-
902
- // The OOP Wrapper
903
- // ---------------
904
-
905
- // If Underscore is called as a function, it returns a wrapped object that
906
- // can be used OO-style. This wrapper holds altered versions of all the
907
- // underscore functions. Wrapped objects may be chained.
908
- var wrapper = function(obj) { this._wrapped = obj; };
909
-
910
- // Expose `wrapper.prototype` as `_.prototype`
911
- _.prototype = wrapper.prototype;
912
-
913
- // Helper function to continue chaining intermediate results.
914
- var result = function(obj, chain) {
915
- return chain ? _(obj).chain() : obj;
916
- };
917
-
918
- // A method to easily add functions to the OOP wrapper.
919
- var addToWrapper = function(name, func) {
920
- wrapper.prototype[name] = function() {
921
- var args = slice.call(arguments);
922
- unshift.call(args, this._wrapped);
923
- return result(func.apply(_, args), this._chain);
924
- };
925
- };
926
-
927
- // Add all of the Underscore functions to the wrapper object.
928
- _.mixin(_);
929
-
930
- // Add all mutator Array functions to the wrapper.
931
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
932
- var method = ArrayProto[name];
933
- wrapper.prototype[name] = function() {
934
- method.apply(this._wrapped, arguments);
935
- return result(this._wrapped, this._chain);
936
- };
937
- });
938
-
939
- // Add all accessor Array functions to the wrapper.
940
- each(['concat', 'join', 'slice'], function(name) {
941
- var method = ArrayProto[name];
942
- wrapper.prototype[name] = function() {
943
- return result(method.apply(this._wrapped, arguments), this._chain);
944
- };
945
- });
946
-
947
- // Start chaining a wrapped Underscore object.
948
- wrapper.prototype.chain = function() {
949
- this._chain = true;
950
- return this;
951
- };
952
-
953
- // Extracts the result from a wrapped and chained object.
954
- wrapper.prototype.value = function() {
955
- return this._wrapped;
956
- };
957
-
958
- })();