PluginProbe ʕ •ᴥ•ʔ
Appointment Booking Calendar / 1.3.71
Appointment Booking Calendar v1.3.71
1.4.04 1.4.03 1.4.02 trunk 1.3.51 1.3.52 1.3.53 1.3.54 1.3.55 1.3.56 1.3.57 1.3.58 1.3.59 1.3.60 1.3.61 1.3.62 1.3.63 1.3.64 1.3.65 1.3.66 1.3.67 1.3.68 1.3.69 1.3.70 1.3.71 1.3.72 1.3.73 1.3.74 1.3.75 1.3.76 1.3.77 1.3.78 1.3.79 1.3.80 1.3.81 1.3.82 1.3.83 1.3.84 1.3.85 1.3.86 1.3.87 1.3.88 1.3.89 1.3.90 1.3.91 1.3.92 1.3.93 1.3.94 1.3.95 1.3.96 1.3.97 1.3.98 1.3.99 1.4.01
appointment-booking-calendar / mv / js / underscore.js
appointment-booking-calendar / mv / js Last commit date
images 3 years ago Common.js 3 years ago jquery.alert.js 3 years ago jquery.calendar.js 3 years ago jquery.cleditor.css 3 years ago jquery.cleditor.js 3 years ago jquery.colorselect.js 3 years ago jquery.dropdown.js 3 years ago jquery.form.js 3 years ago jquery.validate.js 3 years ago multiview.js 3 years ago multiview.public.js 3 years ago repeat.js 3 years ago rrule.js 3 years ago underscore.js 3 years ago widget.admin.js 3 years ago
underscore.js
1062 lines
1 // Underscore.js 1.3.3
2 // (c) 2009-2012 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**, with
52 // backwards-compatibility for the old `require()` API. If we're in
53 // the browser, add `_` as a global object via a string identifier,
54 // for Closure Compiler "advanced" mode.
55 if (typeof exports !== 'undefined') {
56 if (typeof module !== 'undefined' && module.exports) {
57 exports = module.exports = _;
58 }
59 exports._ = _;
60 } else {
61 root['_'] = _;
62 }
63
64 // Current version.
65 _.VERSION = '1.3.3';
66
67 // Collection Functions
68 // --------------------
69
70 // The cornerstone, an `each` implementation, aka `forEach`.
71 // Handles objects with the built-in `forEach`, arrays, and raw objects.
72 // Delegates to **ECMAScript 5**'s native `forEach` if available.
73 var each = _.each = _.forEach = function(obj, iterator, context) {
74 if (obj == null) return;
75 if (nativeForEach && obj.forEach === nativeForEach) {
76 obj.forEach(iterator, context);
77 } else if (obj.length === +obj.length) {
78 for (var i = 0, l = obj.length; i < l; i++) {
79 if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
80 }
81 } else {
82 for (var key in obj) {
83 if (_.has(obj, key)) {
84 if (iterator.call(context, obj[key], key, obj) === breaker) return;
85 }
86 }
87 }
88 };
89
90 // Return the results of applying the iterator to each element.
91 // Delegates to **ECMAScript 5**'s native `map` if available.
92 _.map = _.collect = function(obj, iterator, context) {
93 var results = [];
94 if (obj == null) return results;
95 if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
96 each(obj, function(value, index, list) {
97 results[results.length] = iterator.call(context, value, index, list);
98 });
99 if (obj.length === +obj.length) results.length = obj.length;
100 return results;
101 };
102
103 // **Reduce** builds up a single result from a list of values, aka `inject`,
104 // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
105 _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
106 var initial = arguments.length > 2;
107 if (obj == null) obj = [];
108 if (nativeReduce && obj.reduce === nativeReduce) {
109 if (context) iterator = _.bind(iterator, context);
110 return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
111 }
112 each(obj, function(value, index, list) {
113 if (!initial) {
114 memo = value;
115 initial = true;
116 } else {
117 memo = iterator.call(context, memo, value, index, list);
118 }
119 });
120 if (!initial) throw new TypeError('Reduce of empty array with no initial value');
121 return memo;
122 };
123
124 // The right-associative version of reduce, also known as `foldr`.
125 // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
126 _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
127 var initial = arguments.length > 2;
128 if (obj == null) obj = [];
129 if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
130 if (context) iterator = _.bind(iterator, context);
131 return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
132 }
133 var reversed = _.toArray(obj).reverse();
134 if (context && !initial) iterator = _.bind(iterator, context);
135 return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
136 };
137
138 // Return the first value which passes a truth test. Aliased as `detect`.
139 _.find = _.detect = function(obj, iterator, context) {
140 var result;
141 any(obj, function(value, index, list) {
142 if (iterator.call(context, value, index, list)) {
143 result = value;
144 return true;
145 }
146 });
147 return result;
148 };
149
150 // Return all the elements that pass a truth test.
151 // Delegates to **ECMAScript 5**'s native `filter` if available.
152 // Aliased as `select`.
153 _.filter = _.select = function(obj, iterator, context) {
154 var results = [];
155 if (obj == null) return results;
156 if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
157 each(obj, function(value, index, list) {
158 if (iterator.call(context, value, index, list)) results[results.length] = value;
159 });
160 return results;
161 };
162
163 // Return all the elements for which a truth test fails.
164 _.reject = function(obj, iterator, context) {
165 var results = [];
166 if (obj == null) return results;
167 each(obj, function(value, index, list) {
168 if (!iterator.call(context, value, index, list)) results[results.length] = value;
169 });
170 return results;
171 };
172
173 // Determine whether all of the elements match a truth test.
174 // Delegates to **ECMAScript 5**'s native `every` if available.
175 // Aliased as `all`.
176 _.every = _.all = function(obj, iterator, context) {
177 var result = true;
178 if (obj == null) return result;
179 if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
180 each(obj, function(value, index, list) {
181 if (!(result = result && iterator.call(context, value, index, list))) return breaker;
182 });
183 return !!result;
184 };
185
186 // Determine if at least one element in the object matches a truth test.
187 // Delegates to **ECMAScript 5**'s native `some` if available.
188 // Aliased as `any`.
189 var any = _.some = _.any = function(obj, iterator, context) {
190 iterator || (iterator = _.identity);
191 var result = false;
192 if (obj == null) return result;
193 if (nativeSome && obj.some === nativeSome) return obj.some(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 a given value is included in the array or object using `===`.
201 // Aliased as `contains`.
202 _.include = _.contains = function(obj, target) {
203 var found = false;
204 if (obj == null) return found;
205 if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
206 found = any(obj, function(value) {
207 return value === target;
208 });
209 return found;
210 };
211
212 // Invoke a method (with arguments) on every item in a collection.
213 _.invoke = function(obj, method) {
214 var args = slice.call(arguments, 2);
215 return _.map(obj, function(value) {
216 return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
217 });
218 };
219
220 // Convenience version of a common use case of `map`: fetching a property.
221 _.pluck = function(obj, key) {
222 return _.map(obj, function(value){ return value[key]; });
223 };
224
225 // Return the maximum element or (element-based computation).
226 _.max = function(obj, iterator, context) {
227 if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.max.apply(Math, obj);
228 if (!iterator && _.isEmpty(obj)) return -Infinity;
229 var result = {computed : -Infinity};
230 each(obj, function(value, index, list) {
231 var computed = iterator ? iterator.call(context, value, index, list) : value;
232 computed >= result.computed && (result = {value : value, computed : computed});
233 });
234 return result.value;
235 };
236
237 // Return the minimum element (or element-based computation).
238 _.min = function(obj, iterator, context) {
239 if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.min.apply(Math, obj);
240 if (!iterator && _.isEmpty(obj)) return Infinity;
241 var result = {computed : Infinity};
242 each(obj, function(value, index, list) {
243 var computed = iterator ? iterator.call(context, value, index, list) : value;
244 computed < result.computed && (result = {value : value, computed : computed});
245 });
246 return result.value;
247 };
248
249 // Shuffle an array.
250 _.shuffle = function(obj) {
251 var shuffled = [], rand;
252 each(obj, function(value, index, list) {
253 rand = Math.floor(Math.random() * (index + 1));
254 shuffled[index] = shuffled[rand];
255 shuffled[rand] = value;
256 });
257 return shuffled;
258 };
259
260 // Sort the object's values by a criterion produced by an iterator.
261 _.sortBy = function(obj, val, context) {
262 var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
263 return _.pluck(_.map(obj, function(value, index, list) {
264 return {
265 value : value,
266 criteria : iterator.call(context, value, index, list)
267 };
268 }).sort(function(left, right) {
269 var a = left.criteria, b = right.criteria;
270 if (a === void 0) return 1;
271 if (b === void 0) return -1;
272 return a < b ? -1 : a > b ? 1 : 0;
273 }), 'value');
274 };
275
276 // Groups the object's values by a criterion. Pass either a string attribute
277 // to group by, or a function that returns the criterion.
278 _.groupBy = function(obj, val) {
279 var result = {};
280 var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
281 each(obj, function(value, index) {
282 var key = iterator(value, index);
283 (result[key] || (result[key] = [])).push(value);
284 });
285 return result;
286 };
287
288 // Use a comparator function to figure out at what index an object should
289 // be inserted so as to maintain order. Uses binary search.
290 _.sortedIndex = function(array, obj, iterator) {
291 iterator || (iterator = _.identity);
292 var low = 0, high = array.length;
293 while (low < high) {
294 var mid = (low + high) >> 1;
295 iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
296 }
297 return low;
298 };
299
300 // Safely convert anything iterable into a real, live array.
301 _.toArray = function(obj) {
302 if (!obj) return [];
303 if (_.isArray(obj)) return slice.call(obj);
304 if (_.isArguments(obj)) return slice.call(obj);
305 if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray();
306 return _.values(obj);
307 };
308
309 // Return the number of elements in an object.
310 _.size = function(obj) {
311 try{
312 return _.isArray(obj) ? obj.length : _.keys(obj).length;
313 }catch (e) {}
314 };
315
316 // Array Functions
317 // ---------------
318
319 // Get the first element of an array. Passing **n** will return the first N
320 // values in the array. Aliased as `head` and `take`. The **guard** check
321 // allows it to work with `_.map`.
322 _.first = _.head = _.take = function(array, n, guard) {
323 return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
324 };
325
326 // Returns everything but the last entry of the array. Especcialy useful on
327 // the arguments object. Passing **n** will return all the values in
328 // the array, excluding the last N. The **guard** check allows it to work with
329 // `_.map`.
330 _.initial = function(array, n, guard) {
331 return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
332 };
333
334 // Get the last element of an array. Passing **n** will return the last N
335 // values in the array. The **guard** check allows it to work with `_.map`.
336 _.last = function(array, n, guard) {
337 if ((n != null) && !guard) {
338 return slice.call(array, Math.max(array.length - n, 0));
339 } else {
340 return array[array.length - 1];
341 }
342 };
343
344 // Returns everything but the first entry of the array. Aliased as `tail`.
345 // Especially useful on the arguments object. Passing an **index** will return
346 // the rest of the values in the array from that index onward. The **guard**
347 // check allows it to work with `_.map`.
348 _.rest = _.tail = function(array, index, guard) {
349 return slice.call(array, (index == null) || guard ? 1 : index);
350 };
351
352 // Trim out all falsy values from an array.
353 _.compact = function(array) {
354 return _.filter(array, function(value){ return !!value; });
355 };
356
357 // Return a completely flattened version of an array.
358 _.flatten = function(array, shallow) {
359 return _.reduce(array, function(memo, value) {
360 if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
361 memo[memo.length] = value;
362 return memo;
363 }, []);
364 };
365
366 // Return a version of the array that does not contain the specified value(s).
367 _.without = function(array) {
368 return _.difference(array, slice.call(arguments, 1));
369 };
370
371 // Produce a duplicate-free version of the array. If the array has already
372 // been sorted, you have the option of using a faster algorithm.
373 // Aliased as `unique`.
374 _.uniq = _.unique = function(array, isSorted, iterator) {
375 var initial = iterator ? _.map(array, iterator) : array;
376 var results = [];
377 // The `isSorted` flag is irrelevant if the array only contains two elements.
378 if (array.length < 3) isSorted = true;
379 _.reduce(initial, function (memo, value, index) {
380 if (isSorted ? _.last(memo) !== value || !memo.length : !_.include(memo, value)) {
381 memo.push(value);
382 results.push(array[index]);
383 }
384 return memo;
385 }, []);
386 return results;
387 };
388
389 // Produce an array that contains the union: each distinct element from all of
390 // the passed-in arrays.
391 _.union = function() {
392 return _.uniq(_.flatten(arguments, true));
393 };
394
395 // Produce an array that contains every item shared between all the
396 // passed-in arrays. (Aliased as "intersect" for back-compat.)
397 _.intersection = _.intersect = function(array) {
398 var rest = slice.call(arguments, 1);
399 return _.filter(_.uniq(array), function(item) {
400 return _.every(rest, function(other) {
401 return _.indexOf(other, item) >= 0;
402 });
403 });
404 };
405
406 // Take the difference between one array and a number of other arrays.
407 // Only the elements present in just the first array will remain.
408 _.difference = function(array) {
409 var rest = _.flatten(slice.call(arguments, 1), true);
410 return _.filter(array, function(value){ return !_.include(rest, value); });
411 };
412
413 // Zip together multiple lists into a single array -- elements that share
414 // an index go together.
415 _.zip = function() {
416 var args = slice.call(arguments);
417 var length = _.max(_.pluck(args, 'length'));
418 var results = new Array(length);
419 for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
420 return results;
421 };
422
423 // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
424 // we need this function. Return the position of the first occurrence of an
425 // item in an array, or -1 if the item is not included in the array.
426 // Delegates to **ECMAScript 5**'s native `indexOf` if available.
427 // If the array is large and already in sort order, pass `true`
428 // for **isSorted** to use binary search.
429 _.indexOf = function(array, item, isSorted) {
430 if (array == null) return -1;
431 var i, l;
432 if (isSorted) {
433 i = _.sortedIndex(array, item);
434 return array[i] === item ? i : -1;
435 }
436 if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
437 for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
438 return -1;
439 };
440
441 // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
442 _.lastIndexOf = function(array, item) {
443 if (array == null) return -1;
444 if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
445 var i = array.length;
446 while (i--) if (i in array && array[i] === item) return i;
447 return -1;
448 };
449
450 // Generate an integer Array containing an arithmetic progression. A port of
451 // the native Python `range()` function. See
452 // [the Python documentation](http://docs.python.org/library/functions.html#range).
453 _.range = function(start, stop, step) {
454 if (arguments.length <= 1) {
455 stop = start || 0;
456 start = 0;
457 }
458 step = arguments[2] || 1;
459
460 var len = Math.max(Math.ceil((stop - start) / step), 0);
461 var idx = 0;
462 var range = new Array(len);
463
464 while(idx < len) {
465 range[idx++] = start;
466 start += step;
467 }
468
469 return range;
470 };
471
472 // Function (ahem) Functions
473 // ------------------
474
475 // Reusable constructor function for prototype setting.
476 var ctor = function(){};
477
478 // Create a function bound to a given object (assigning `this`, and arguments,
479 // optionally). Binding with arguments is also known as `curry`.
480 // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
481 // We check for `func.bind` first, to fail fast when `func` is undefined.
482 _.bind = function bind(func, context) {
483 var bound, args;
484 if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
485 if (!_.isFunction(func)) throw new TypeError;
486 args = slice.call(arguments, 2);
487 return bound = function() {
488 if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
489 ctor.prototype = func.prototype;
490 var self = new ctor;
491 var result = func.apply(self, args.concat(slice.call(arguments)));
492 if (Object(result) === result) return result;
493 return self;
494 };
495 };
496
497 // Bind all of an object's methods to that object. Useful for ensuring that
498 // all callbacks defined on an object belong to it.
499 _.bindAll = function(obj) {
500 var funcs = slice.call(arguments, 1);
501 if (funcs.length == 0) funcs = _.functions(obj);
502 each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
503 return obj;
504 };
505
506 // Memoize an expensive function by storing its results.
507 _.memoize = function(func, hasher) {
508 var memo = {};
509 hasher || (hasher = _.identity);
510 return function() {
511 var key = hasher.apply(this, arguments);
512 return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
513 };
514 };
515
516 // Delays a function for the given number of milliseconds, and then calls
517 // it with the arguments supplied.
518 _.delay = function(func, wait) {
519 var args = slice.call(arguments, 2);
520 return setTimeout(function(){ return func.apply(null, args); }, wait);
521 };
522
523 // Defers a function, scheduling it to run after the current call stack has
524 // cleared.
525 _.defer = function(func) {
526 return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
527 };
528
529 // Returns a function, that, when invoked, will only be triggered at most once
530 // during a given window of time.
531 _.throttle = function(func, wait) {
532 var context, args, timeout, throttling, more, result;
533 var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
534 return function() {
535 context = this; args = arguments;
536 var later = function() {
537 timeout = null;
538 if (more) func.apply(context, args);
539 whenDone();
540 };
541 if (!timeout) timeout = setTimeout(later, wait);
542 if (throttling) {
543 more = true;
544 } else {
545 result = func.apply(context, args);
546 }
547 whenDone();
548 throttling = true;
549 return result;
550 };
551 };
552
553 // Returns a function, that, as long as it continues to be invoked, will not
554 // be triggered. The function will be called after it stops being called for
555 // N milliseconds. If `immediate` is passed, trigger the function on the
556 // leading edge, instead of the trailing.
557 _.debounce = function(func, wait, immediate) {
558 var timeout;
559 return function() {
560 var context = this, args = arguments;
561 var later = function() {
562 timeout = null;
563 if (!immediate) func.apply(context, args);
564 };
565 if (immediate && !timeout) func.apply(context, args);
566 clearTimeout(timeout);
567 timeout = setTimeout(later, wait);
568 };
569 };
570
571 // Returns a function that will be executed at most one time, no matter how
572 // often you call it. Useful for lazy initialization.
573 _.once = function(func) {
574 var ran = false, memo;
575 return function() {
576 if (ran) return memo;
577 ran = true;
578 return memo = func.apply(this, arguments);
579 };
580 };
581
582 // Returns the first function passed as an argument to the second,
583 // allowing you to adjust arguments, run code before and after, and
584 // conditionally execute the original function.
585 _.wrap = function(func, wrapper) {
586 return function() {
587 var args = [func].concat(slice.call(arguments, 0));
588 return wrapper.apply(this, args);
589 };
590 };
591
592 // Returns a function that is the composition of a list of functions, each
593 // consuming the return value of the function that follows.
594 _.compose = function() {
595 var funcs = arguments;
596 return function() {
597 var args = arguments;
598 for (var i = funcs.length - 1; i >= 0; i--) {
599 args = [funcs[i].apply(this, args)];
600 }
601 return args[0];
602 };
603 };
604
605 // Returns a function that will only be executed after being called N times.
606 _.after = function(times, func) {
607 if (times <= 0) return func();
608 return function() {
609 if (--times < 1) { return func.apply(this, arguments); }
610 };
611 };
612
613 // Object Functions
614 // ----------------
615
616 // Retrieve the names of an object's properties.
617 // Delegates to **ECMAScript 5**'s native `Object.keys`
618 _.keys = nativeKeys || function(obj) {
619 if (obj !== Object(obj)) throw new TypeError('Invalid object');
620 var keys = [];
621 for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
622 return keys;
623 };
624
625 // Retrieve the values of an object's properties.
626 _.values = function(obj) {
627 return _.map(obj, _.identity);
628 };
629
630 // Return a sorted list of the function names available on the object.
631 // Aliased as `methods`
632 _.functions = _.methods = function(obj) {
633 var names = [];
634 for (var key in obj) {
635 if (_.isFunction(obj[key])) names.push(key);
636 }
637 return names.sort();
638 };
639
640 // Extend a given object with all the properties in passed-in object(s).
641 _.extend = function(obj) {
642 each(slice.call(arguments, 1), function(source) {
643 for (var prop in source) {
644 obj[prop] = source[prop];
645 }
646 });
647 return obj;
648 };
649
650 // Return a copy of the object only containing the whitelisted properties.
651 _.pick = function(obj) {
652 var result = {};
653 each(_.flatten(slice.call(arguments, 1)), function(key) {
654 if (key in obj) result[key] = obj[key];
655 });
656 return result;
657 };
658
659 // Fill in a given object with default properties.
660 _.defaults = function(obj) {
661 each(slice.call(arguments, 1), function(source) {
662 for (var prop in source) {
663 if (obj[prop] == null) obj[prop] = source[prop];
664 }
665 });
666 return obj;
667 };
668
669 // Create a (shallow-cloned) duplicate of an object.
670 _.clone = function(obj) {
671 if (!_.isObject(obj)) return obj;
672 return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
673 };
674
675 // Invokes interceptor with the obj, and then returns obj.
676 // The primary purpose of this method is to "tap into" a method chain, in
677 // order to perform operations on intermediate results within the chain.
678 _.tap = function(obj, interceptor) {
679 interceptor(obj);
680 return obj;
681 };
682
683 // Internal recursive comparison function.
684 function eq(a, b, stack) {
685 // Identical objects are equal. `0 === -0`, but they aren't identical.
686 // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
687 if (a === b) return a !== 0 || 1 / a == 1 / b;
688 // A strict comparison is necessary because `null == undefined`.
689 if (a == null || b == null) return a === b;
690 // Unwrap any wrapped objects.
691 if (a._chain) a = a._wrapped;
692 if (b._chain) b = b._wrapped;
693 // Invoke a custom `isEqual` method if one is provided.
694 if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
695 if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
696 // Compare `[[Class]]` names.
697 var className = toString.call(a);
698 if (className != toString.call(b)) return false;
699 switch (className) {
700 // Strings, numbers, dates, and booleans are compared by value.
701 case '[object String]':
702 // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
703 // equivalent to `new String("5")`.
704 return a == String(b);
705 case '[object Number]':
706 // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
707 // other numeric values.
708 return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
709 case '[object Date]':
710 case '[object Boolean]':
711 // Coerce dates and booleans to numeric primitive values. Dates are compared by their
712 // millisecond representations. Note that invalid dates with millisecond representations
713 // of `NaN` are not equivalent.
714 return +a == +b;
715 // RegExps are compared by their source patterns and flags.
716 case '[object RegExp]':
717 return a.source == b.source &&
718 a.global == b.global &&
719 a.multiline == b.multiline &&
720 a.ignoreCase == b.ignoreCase;
721 }
722 if (typeof a != 'object' || typeof b != 'object') return false;
723 // Assume equality for cyclic structures. The algorithm for detecting cyclic
724 // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
725 var length = stack.length;
726 while (length--) {
727 // Linear search. Performance is inversely proportional to the number of
728 // unique nested structures.
729 if (stack[length] == a) return true;
730 }
731 // Add the first object to the stack of traversed objects.
732 stack.push(a);
733 var size = 0, result = true;
734 // Recursively compare objects and arrays.
735 if (className == '[object Array]') {
736 // Compare array lengths to determine if a deep comparison is necessary.
737 size = a.length;
738 result = size == b.length;
739 if (result) {
740 // Deep compare the contents, ignoring non-numeric properties.
741 while (size--) {
742 // Ensure commutative equality for sparse arrays.
743 if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
744 }
745 }
746 } else {
747 // Objects with different constructors are not equivalent.
748 if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
749 // Deep compare objects.
750 for (var key in a) {
751 if (_.has(a, key)) {
752 // Count the expected number of properties.
753 size++;
754 // Deep compare each member.
755 if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
756 }
757 }
758 // Ensure that both objects contain the same number of properties.
759 if (result) {
760 for (key in b) {
761 if (_.has(b, key) && !(size--)) break;
762 }
763 result = !size;
764 }
765 }
766 // Remove the first object from the stack of traversed objects.
767 stack.pop();
768 return result;
769 }
770
771 // Perform a deep comparison to check if two objects are equal.
772 _.isEqual = function(a, b) {
773 return eq(a, b, []);
774 };
775
776 // Is a given array, string, or object empty?
777 // An "empty" object has no enumerable own-properties.
778 _.isEmpty = function(obj) {
779 if (obj == null) return true;
780 if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
781 for (var key in obj) if (_.has(obj, key)) return false;
782 return true;
783 };
784
785 // Is a given value a DOM element?
786 _.isElement = function(obj) {
787 return !!(obj && obj.nodeType == 1);
788 };
789
790 // Is a given value an array?
791 // Delegates to ECMA5's native Array.isArray
792 _.isArray = nativeIsArray || function(obj) {
793 return toString.call(obj) == '[object Array]';
794 };
795
796 // Is a given variable an object?
797 _.isObject = function(obj) {
798 return obj === Object(obj);
799 };
800
801 // Is a given variable an arguments object?
802 _.isArguments = function(obj) {
803 return toString.call(obj) == '[object Arguments]';
804 };
805 if (!_.isArguments(arguments)) {
806 _.isArguments = function(obj) {
807 return !!(obj && _.has(obj, 'callee'));
808 };
809 }
810
811 // Is a given value a function?
812 _.isFunction = function(obj) {
813 return toString.call(obj) == '[object Function]';
814 };
815
816 // Is a given value a string?
817 _.isString = function(obj) {
818 return toString.call(obj) == '[object String]';
819 };
820
821 // Is a given value a number?
822 _.isNumber = function(obj) {
823 return toString.call(obj) == '[object Number]';
824 };
825
826 // Is a given object a finite number?
827 _.isFinite = function(obj) {
828 return _.isNumber(obj) && isFinite(obj);
829 };
830
831 // Is the given value `NaN`?
832 _.isNaN = function(obj) {
833 // `NaN` is the only value for which `===` is not reflexive.
834 return obj !== obj;
835 };
836
837 // Is a given value a boolean?
838 _.isBoolean = function(obj) {
839 return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
840 };
841
842 // Is a given value a date?
843 _.isDate = function(obj) {
844 return toString.call(obj) == '[object Date]';
845 };
846
847 // Is the given value a regular expression?
848 _.isRegExp = function(obj) {
849 return toString.call(obj) == '[object RegExp]';
850 };
851
852 // Is a given value equal to null?
853 _.isNull = function(obj) {
854 return obj === null;
855 };
856
857 // Is a given variable undefined?
858 _.isUndefined = function(obj) {
859 return obj === void 0;
860 };
861
862 // Has own property?
863 _.has = function(obj, key) {
864 return hasOwnProperty.call(obj, key);
865 };
866
867 // Utility Functions
868 // -----------------
869
870 // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
871 // previous owner. Returns a reference to the Underscore object.
872 _.noConflict = function() {
873 root._ = previousUnderscore;
874 return this;
875 };
876
877 // Keep the identity function around for default iterators.
878 _.identity = function(value) {
879 return value;
880 };
881
882 // Run a function **n** times.
883 _.times = function (n, iterator, context) {
884 for (var i = 0; i < n; i++) iterator.call(context, i);
885 };
886
887 // Escape a string for HTML interpolation.
888 _.escape = function(string) {
889 return (''+string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
890 };
891
892 // If the value of the named property is a function then invoke it;
893 // otherwise, return it.
894 _.result = function(object, property) {
895 if (object == null) return null;
896 var value = object[property];
897 return _.isFunction(value) ? value.call(object) : value;
898 };
899
900 // Add your own custom functions to the Underscore object, ensuring that
901 // they're correctly added to the OOP wrapper as well.
902 _.mixin = function(obj) {
903 each(_.functions(obj), function(name){
904 addToWrapper(name, _[name] = obj[name]);
905 });
906 };
907
908 // Generate a unique integer id (unique within the entire client session).
909 // Useful for temporary DOM ids.
910 var idCounter = 0;
911 _.uniqueId = function(prefix) {
912 var id = idCounter++;
913 return prefix ? prefix + id : id;
914 };
915
916 // By default, Underscore uses ERB-style template delimiters, change the
917 // following template settings to use alternative delimiters.
918 _.templateSettings = {
919 evaluate : /<%([\s\S]+?)%>/g,
920 interpolate : /<%=([\s\S]+?)%>/g,
921 escape : /<%-([\s\S]+?)%>/g
922 };
923
924 // When customizing `templateSettings`, if you don't want to define an
925 // interpolation, evaluation or escaping regex, we need one that is
926 // guaranteed not to match.
927 var noMatch = /.^/;
928
929 // Certain characters need to be escaped so that they can be put into a
930 // string literal.
931 var escapes = {
932 '\\': '\\',
933 "'": "'",
934 'r': '\r',
935 'n': '\n',
936 't': '\t',
937 'u2028': '\u2028',
938 'u2029': '\u2029'
939 };
940
941 for (var p in escapes) escapes[escapes[p]] = p;
942 var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
943 var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
944
945 // Within an interpolation, evaluation, or escaping, remove HTML escaping
946 // that had been previously added.
947 var unescape = function(code) {
948 return code.replace(unescaper, function(match, escape) {
949 return escapes[escape];
950 });
951 };
952
953 // JavaScript micro-templating, similar to John Resig's implementation.
954 // Underscore templating handles arbitrary delimiters, preserves whitespace,
955 // and correctly escapes quotes within interpolated code.
956 _.template = function(text, data, settings) {
957 settings = _.defaults(settings || {}, _.templateSettings);
958
959 // Compile the template source, taking care to escape characters that
960 // cannot be included in a string literal and then unescape them in code
961 // blocks.
962 var source = "__p+='" + text
963 .replace(escaper, function(match) {
964 return '\\' + escapes[match];
965 })
966 .replace(settings.escape || noMatch, function(match, code) {
967 return "'+\n_.escape(" + unescape(code) + ")+\n'";
968 })
969 .replace(settings.interpolate || noMatch, function(match, code) {
970 return "'+\n(" + unescape(code) + ")+\n'";
971 })
972 .replace(settings.evaluate || noMatch, function(match, code) {
973 return "';\n" + unescape(code) + "\n;__p+='";
974 }) + "';\n";
975
976 // If a variable is not specified, place data values in local scope.
977 if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
978
979 source = "var __p='';" +
980 "var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" +
981 source + "return __p;\n";
982
983 var render = new Function(settings.variable || 'obj', '_', source);
984 if (data) return render(data, _);
985 var template = function(data) {
986 return render.call(this, data, _);
987 };
988
989 // Provide the compiled function source as a convenience for build time
990 // precompilation.
991 template.source = 'function(' + (settings.variable || 'obj') + '){\n' +
992 source + '}';
993
994 return template;
995 };
996
997 // Add a "chain" function, which will delegate to the wrapper.
998 _.chain = function(obj) {
999 return _(obj).chain();
1000 };
1001
1002 // The OOP Wrapper
1003 // ---------------
1004
1005 // If Underscore is called as a function, it returns a wrapped object that
1006 // can be used OO-style. This wrapper holds altered versions of all the
1007 // underscore functions. Wrapped objects may be chained.
1008 var wrapper = function(obj) { this._wrapped = obj; };
1009
1010 // Expose `wrapper.prototype` as `_.prototype`
1011 _.prototype = wrapper.prototype;
1012
1013 // Helper function to continue chaining intermediate results.
1014 var result = function(obj, chain) {
1015 return chain ? _(obj).chain() : obj;
1016 };
1017
1018 // A method to easily add functions to the OOP wrapper.
1019 var addToWrapper = function(name, func) {
1020 wrapper.prototype[name] = function() {
1021 var args = slice.call(arguments);
1022 unshift.call(args, this._wrapped);
1023 return result(func.apply(_, args), this._chain);
1024 };
1025 };
1026
1027 // Add all of the Underscore functions to the wrapper object.
1028 _.mixin(_);
1029
1030 // Add all mutator Array functions to the wrapper.
1031 each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
1032 var method = ArrayProto[name];
1033 wrapper.prototype[name] = function() {
1034 var wrapped = this._wrapped;
1035 method.apply(wrapped, arguments);
1036 var length = wrapped.length;
1037 if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
1038 return result(wrapped, this._chain);
1039 };
1040 });
1041
1042 // Add all accessor Array functions to the wrapper.
1043 each(['concat', 'join', 'slice'], function(name) {
1044 var method = ArrayProto[name];
1045 wrapper.prototype[name] = function() {
1046 return result(method.apply(this._wrapped, arguments), this._chain);
1047 };
1048 });
1049
1050 // Start chaining a wrapped Underscore object.
1051 wrapper.prototype.chain = function() {
1052 this._chain = true;
1053 return this;
1054 };
1055
1056 // Extracts the result from a wrapped and chained object.
1057 wrapper.prototype.value = function() {
1058 return this._wrapped;
1059 };
1060
1061 }).call(this);
1062