Tag: JavaScript框架

  • WordPress 源代码——主干(underscore-1.4.4.js)

    WordPress 源代码——主干(underscore-1.4.4.js)

    1	//     Underscore.js 1.4.4
    2	//     http://underscorejs.org
    3	//     (c) 2009-2013 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.4';
    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	    var isFunc = _.isFunction(method);
    228	    return _.map(obj, function(value) {
    229	      return (isFunc ? method : value[method]).apply(value, args);
    230	    });
    231	  };
    232	
    233	  // Convenience version of a common use case of `map`: fetching a property.
    234	  _.pluck = function(obj, key) {
    235	    return _.map(obj, function(value){ return value[key]; });
    236	  };
    237	
    238	  // Convenience version of a common use case of `filter`: selecting only objects
    239	  // containing specific `key:value` pairs.
    240	  _.where = function(obj, attrs, first) {
    241	    if (_.isEmpty(attrs)) return first ? null : [];
    242	    return _[first ? 'find' : 'filter'](obj, function(value) {
    243	      for (var key in attrs) {
    244	        if (attrs[key] !== value[key]) return false;
    245	      }
    246	      return true;
    247	    });
    248	  };
    249	
    250	  // Convenience version of a common use case of `find`: getting the first object
    251	  // containing specific `key:value` pairs.
    252	  _.findWhere = function(obj, attrs) {
    253	    return _.where(obj, attrs, true);
    254	  };
    255	
    256	  // Return the maximum element or (element-based computation).
    257	  // Can't optimize arrays of integers longer than 65,535 elements.
    258	  // See: https://bugs.webkit.org/show_bug.cgi?id=80797
    259	  _.max = function(obj, iterator, context) {
    260	    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
    261	      return Math.max.apply(Math, obj);
    262	    }
    263	    if (!iterator && _.isEmpty(obj)) return -Infinity;
    264	    var result = {computed : -Infinity, value: -Infinity};
    265	    each(obj, function(value, index, list) {
    266	      var computed = iterator ? iterator.call(context, value, index, list) : value;
    267	      computed >= result.computed && (result = {value : value, computed : computed});
    268	    });
    269	    return result.value;
    270	  };
    271	
    272	  // Return the minimum element (or element-based computation).
    273	  _.min = function(obj, iterator, context) {
    274	    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
    275	      return Math.min.apply(Math, obj);
    276	    }
    277	    if (!iterator && _.isEmpty(obj)) return Infinity;
    278	    var result = {computed : Infinity, value: Infinity};
    279	    each(obj, function(value, index, list) {
    280	      var computed = iterator ? iterator.call(context, value, index, list) : value;
    281	      computed < result.computed && (result = {value : value, computed : computed});
    282	    });
    283	    return result.value;
    284	  };
    285	
    286	  // Shuffle an array.
    287	  _.shuffle = function(obj) {
    288	    var rand;
    289	    var index = 0;
    290	    var shuffled = [];
    291	    each(obj, function(value) {
    292	      rand = _.random(index++);
    293	      shuffled[index - 1] = shuffled[rand];
    294	      shuffled[rand] = value;
    295	    });
    296	    return shuffled;
    297	  };
    298	
    299	  // An internal function to generate lookup iterators.
    300	  var lookupIterator = function(value) {
    301	    return _.isFunction(value) ? value : function(obj){ return obj[value]; };
    302	  };
    303	
    304	  // Sort the object's values by a criterion produced by an iterator.
    305	  _.sortBy = function(obj, value, context) {
    306	    var iterator = lookupIterator(value);
    307	    return _.pluck(_.map(obj, function(value, index, list) {
    308	      return {
    309	        value : value,
    310	        index : index,
    311	        criteria : iterator.call(context, value, index, list)
    312	      };
    313	    }).sort(function(left, right) {
    314	      var a = left.criteria;
    315	      var b = right.criteria;
    316	      if (a !== b) {
    317	        if (a > b || a === void 0) return 1;
    318	        if (a < b || b === void 0) return -1;
    319	      }
    320	      return left.index < right.index ? -1 : 1;
    321	    }), 'value');
    322	  };
    323	
    324	  // An internal function used for aggregate "group by" operations.
    325	  var group = function(obj, value, context, behavior) {
    326	    var result = {};
    327	    var iterator = lookupIterator(value || _.identity);
    328	    each(obj, function(value, index) {
    329	      var key = iterator.call(context, value, index, obj);
    330	      behavior(result, key, value);
    331	    });
    332	    return result;
    333	  };
    334	
    335	  // Groups the object's values by a criterion. Pass either a string attribute
    336	  // to group by, or a function that returns the criterion.
    337	  _.groupBy = function(obj, value, context) {
    338	    return group(obj, value, context, function(result, key, value) {
    339	      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
    340	    });
    341	  };
    342	
    343	  // Counts instances of an object that group by a certain criterion. Pass
    344	  // either a string attribute to count by, or a function that returns the
    345	  // criterion.
    346	  _.countBy = function(obj, value, context) {
    347	    return group(obj, value, context, function(result, key) {
    348	      if (!_.has(result, key)) result[key] = 0;
    349	      result[key]++;
    350	    });
    351	  };
    352	
    353	  // Use a comparator function to figure out the smallest index at which
    354	  // an object should be inserted so as to maintain order. Uses binary search.
    355	  _.sortedIndex = function(array, obj, iterator, context) {
    356	    iterator = iterator == null ? _.identity : lookupIterator(iterator);
    357	    var value = iterator.call(context, obj);
    358	    var low = 0, high = array.length;
    359	    while (low < high) {
    360	      var mid = (low + high) >>> 1;
    361	      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
    362	    }
    363	    return low;
    364	  };
    365	
    366	  // Safely convert anything iterable into a real, live array.
    367	  _.toArray = function(obj) {
    368	    if (!obj) return [];
    369	    if (_.isArray(obj)) return slice.call(obj);
    370	    if (obj.length === +obj.length) return _.map(obj, _.identity);
    371	    return _.values(obj);
    372	  };
    373	
    374	  // Return the number of elements in an object.
    375	  _.size = function(obj) {
    376	    if (obj == null) return 0;
    377	    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
    378	  };
    379	
    380	  // Array Functions
    381	  // ---------------
    382	
    383	  // Get the first element of an array. Passing **n** will return the first N
    384	  // values in the array. Aliased as `head` and `take`. The **guard** check
    385	  // allows it to work with `_.map`.
    386	  _.first = _.head = _.take = function(array, n, guard) {
    387	    if (array == null) return void 0;
    388	    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
    389	  };
    390	
    391	  // Returns everything but the last entry of the array. Especially useful on
    392	  // the arguments object. Passing **n** will return all the values in
    393	  // the array, excluding the last N. The **guard** check allows it to work with
    394	  // `_.map`.
    395	  _.initial = function(array, n, guard) {
    396	    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
    397	  };
    398	
    399	  // Get the last element of an array. Passing **n** will return the last N
    400	  // values in the array. The **guard** check allows it to work with `_.map`.
    401	  _.last = function(array, n, guard) {
    402	    if (array == null) return void 0;
    403	    if ((n != null) && !guard) {
    404	      return slice.call(array, Math.max(array.length - n, 0));
    405	    } else {
    406	      return array[array.length - 1];
    407	    }
    408	  };
    409	
    410	  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
    411	  // Especially useful on the arguments object. Passing an **n** will return
    412	  // the rest N values in the array. The **guard**
    413	  // check allows it to work with `_.map`.
    414	  _.rest = _.tail = _.drop = function(array, n, guard) {
    415	    return slice.call(array, (n == null) || guard ? 1 : n);
    416	  };
    417	
    418	  // Trim out all falsy values from an array.
    419	  _.compact = function(array) {
    420	    return _.filter(array, _.identity);
    421	  };
    422	
    423	  // Internal implementation of a recursive `flatten` function.
    424	  var flatten = function(input, shallow, output) {
    425	    each(input, function(value) {
    426	      if (_.isArray(value)) {
    427	        shallow ? push.apply(output, value) : flatten(value, shallow, output);
    428	      } else {
    429	        output.push(value);
    430	      }
    431	    });
    432	    return output;
    433	  };
    434	
    435	  // Return a completely flattened version of an array.
    436	  _.flatten = function(array, shallow) {
    437	    return flatten(array, shallow, []);
    438	  };
    439	
    440	  // Return a version of the array that does not contain the specified value(s).
    441	  _.without = function(array) {
    442	    return _.difference(array, slice.call(arguments, 1));
    443	  };
    444	
    445	  // Produce a duplicate-free version of the array. If the array has already
    446	  // been sorted, you have the option of using a faster algorithm.
    447	  // Aliased as `unique`.
    448	  _.uniq = _.unique = function(array, isSorted, iterator, context) {
    449	    if (_.isFunction(isSorted)) {
    450	      context = iterator;
    451	      iterator = isSorted;
    452	      isSorted = false;
    453	    }
    454	    var initial = iterator ? _.map(array, iterator, context) : array;
    455	    var results = [];
    456	    var seen = [];
    457	    each(initial, function(value, index) {
    458	      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
    459	        seen.push(value);
    460	        results.push(array[index]);
    461	      }
    462	    });
    463	    return results;
    464	  };
    465	
    466	  // Produce an array that contains the union: each distinct element from all of
    467	  // the passed-in arrays.
    468	  _.union = function() {
    469	    return _.uniq(concat.apply(ArrayProto, arguments));
    470	  };
    471	
    472	  // Produce an array that contains every item shared between all the
    473	  // passed-in arrays.
    474	  _.intersection = function(array) {
    475	    var rest = slice.call(arguments, 1);
    476	    return _.filter(_.uniq(array), function(item) {
    477	      return _.every(rest, function(other) {
    478	        return _.indexOf(other, item) >= 0;
    479	      });
    480	    });
    481	  };
    482	
    483	  // Take the difference between one array and a number of other arrays.
    484	  // Only the elements present in just the first array will remain.
    485	  _.difference = function(array) {
    486	    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
    487	    return _.filter(array, function(value){ return !_.contains(rest, value); });
    488	  };
    489	
    490	  // Zip together multiple lists into a single array -- elements that share
    491	  // an index go together.
    492	  _.zip = function() {
    493	    var args = slice.call(arguments);
    494	    var length = _.max(_.pluck(args, 'length'));
    495	    var results = new Array(length);
    496	    for (var i = 0; i < length; i++) {
    497	      results[i] = _.pluck(args, "" + i);
    498	    }
    499	    return results;
    500	  };
    501	
    502	  // Converts lists into objects. Pass either a single array of `[key, value]`
    503	  // pairs, or two parallel arrays of the same length -- one of keys, and one of
    504	  // the corresponding values.
    505	  _.object = function(list, values) {
    506	    if (list == null) return {};
    507	    var result = {};
    508	    for (var i = 0, l = list.length; i < l; i++) {
    509	      if (values) {
    510	        result[list[i]] = values[i];
    511	      } else {
    512	        result[list[i][0]] = list[i][1];
    513	      }
    514	    }
    515	    return result;
    516	  };
    517	
    518	  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
    519	  // we need this function. Return the position of the first occurrence of an
    520	  // item in an array, or -1 if the item is not included in the array.
    521	  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
    522	  // If the array is large and already in sort order, pass `true`
    523	  // for **isSorted** to use binary search.
    524	  _.indexOf = function(array, item, isSorted) {
    525	    if (array == null) return -1;
    526	    var i = 0, l = array.length;
    527	    if (isSorted) {
    528	      if (typeof isSorted == 'number') {
    529	        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
    530	      } else {
    531	        i = _.sortedIndex(array, item);
    532	        return array[i] === item ? i : -1;
    533	      }
    534	    }
    535	    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
    536	    for (; i < l; i++) if (array[i] === item) return i;
    537	    return -1;
    538	  };
    539	
    540	  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
    541	  _.lastIndexOf = function(array, item, from) {
    542	    if (array == null) return -1;
    543	    var hasIndex = from != null;
    544	    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
    545	      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
    546	    }
    547	    var i = (hasIndex ? from : array.length);
    548	    while (i--) if (array[i] === item) return i;
    549	    return -1;
    550	  };
    551	
    552	  // Generate an integer Array containing an arithmetic progression. A port of
    553	  // the native Python `range()` function. See
    554	  // [the Python documentation](http://docs.python.org/library/functions.html#range).
    555	  _.range = function(start, stop, step) {
    556	    if (arguments.length <= 1) {
    557	      stop = start || 0;
    558	      start = 0;
    559	    }
    560	    step = arguments[2] || 1;
    561	
    562	    var len = Math.max(Math.ceil((stop - start) / step), 0);
    563	    var idx = 0;
    564	    var range = new Array(len);
    565	
    566	    while(idx < len) {
    567	      range[idx++] = start;
    568	      start += step;
    569	    }
    570	
    571	    return range;
    572	  };
    573	
    574	  // Function (ahem) Functions
    575	  // ------------------
    576	
    577	  // Create a function bound to a given object (assigning `this`, and arguments,
    578	  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
    579	  // available.
    580	  _.bind = function(func, context) {
    581	    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
    582	    var args = slice.call(arguments, 2);
    583	    return function() {
    584	      return func.apply(context, args.concat(slice.call(arguments)));
    585	    };
    586	  };
    587	
    588	  // Partially apply a function by creating a version that has had some of its
    589	  // arguments pre-filled, without changing its dynamic `this` context.
    590	  _.partial = function(func) {
    591	    var args = slice.call(arguments, 1);
    592	    return function() {
    593	      return func.apply(this, args.concat(slice.call(arguments)));
    594	    };
    595	  };
    596	
    597	  // Bind all of an object's methods to that object. Useful for ensuring that
    598	  // all callbacks defined on an object belong to it.
    599	  _.bindAll = function(obj) {
    600	    var funcs = slice.call(arguments, 1);
    601	    if (funcs.length === 0) funcs = _.functions(obj);
    602	    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
    603	    return obj;
    604	  };
    605	
    606	  // Memoize an expensive function by storing its results.
    607	  _.memoize = function(func, hasher) {
    608	    var memo = {};
    609	    hasher || (hasher = _.identity);
    610	    return function() {
    611	      var key = hasher.apply(this, arguments);
    612	      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
    613	    };
    614	  };
    615	
    616	  // Delays a function for the given number of milliseconds, and then calls
    617	  // it with the arguments supplied.
    618	  _.delay = function(func, wait) {
    619	    var args = slice.call(arguments, 2);
    620	    return setTimeout(function(){ return func.apply(null, args); }, wait);
    621	  };
    622	
    623	  // Defers a function, scheduling it to run after the current call stack has
    624	  // cleared.
    625	  _.defer = function(func) {
    626	    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
    627	  };
    628	
    629	  // Returns a function, that, when invoked, will only be triggered at most once
    630	  // during a given window of time.
    631	  _.throttle = function(func, wait) {
    632	    var context, args, timeout, result;
    633	    var previous = 0;
    634	    var later = function() {
    635	      previous = new Date;
    636	      timeout = null;
    637	      result = func.apply(context, args);
    638	    };
    639	    return function() {
    640	      var now = new Date;
    641	      var remaining = wait - (now - previous);
    642	      context = this;
    643	      args = arguments;
    644	      if (remaining <= 0) {
    645	        clearTimeout(timeout);
    646	        timeout = null;
    647	        previous = now;
    648	        result = func.apply(context, args);
    649	      } else if (!timeout) {
    650	        timeout = setTimeout(later, remaining);
    651	      }
    652	      return result;
    653	    };
    654	  };
    655	
    656	  // Returns a function, that, as long as it continues to be invoked, will not
    657	  // be triggered. The function will be called after it stops being called for
    658	  // N milliseconds. If `immediate` is passed, trigger the function on the
    659	  // leading edge, instead of the trailing.
    660	  _.debounce = function(func, wait, immediate) {
    661	    var timeout, result;
    662	    return function() {
    663	      var context = this, args = arguments;
    664	      var later = function() {
    665	        timeout = null;
    666	        if (!immediate) result = func.apply(context, args);
    667	      };
    668	      var callNow = immediate && !timeout;
    669	      clearTimeout(timeout);
    670	      timeout = setTimeout(later, wait);
    671	      if (callNow) result = func.apply(context, args);
    672	      return result;
    673	    };
    674	  };
    675	
    676	  // Returns a function that will be executed at most one time, no matter how
    677	  // often you call it. Useful for lazy initialization.
    678	  _.once = function(func) {
    679	    var ran = false, memo;
    680	    return function() {
    681	      if (ran) return memo;
    682	      ran = true;
    683	      memo = func.apply(this, arguments);
    684	      func = null;
    685	      return memo;
    686	    };
    687	  };
    688	
    689	  // Returns the first function passed as an argument to the second,
    690	  // allowing you to adjust arguments, run code before and after, and
    691	  // conditionally execute the original function.
    692	  _.wrap = function(func, wrapper) {
    693	    return function() {
    694	      var args = [func];
    695	      push.apply(args, arguments);
    696	      return wrapper.apply(this, args);
    697	    };
    698	  };
    699	
    700	  // Returns a function that is the composition of a list of functions, each
    701	  // consuming the return value of the function that follows.
    702	  _.compose = function() {
    703	    var funcs = arguments;
    704	    return function() {
    705	      var args = arguments;
    706	      for (var i = funcs.length - 1; i >= 0; i--) {
    707	        args = [funcs[i].apply(this, args)];
    708	      }
    709	      return args[0];
    710	    };
    711	  };
    712	
    713	  // Returns a function that will only be executed after being called N times.
    714	  _.after = function(times, func) {
    715	    if (times <= 0) return func();
    716	    return function() {
    717	      if (--times < 1) {
    718	        return func.apply(this, arguments);
    719	      }
    720	    };
    721	  };
    722	
    723	  // Object Functions
    724	  // ----------------
    725	
    726	  // Retrieve the names of an object's properties.
    727	  // Delegates to **ECMAScript 5**'s native `Object.keys`
    728	  _.keys = nativeKeys || function(obj) {
    729	    if (obj !== Object(obj)) throw new TypeError('Invalid object');
    730	    var keys = [];
    731	    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
    732	    return keys;
    733	  };
    734	
    735	  // Retrieve the values of an object's properties.
    736	  _.values = function(obj) {
    737	    var values = [];
    738	    for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
    739	    return values;
    740	  };
    741	
    742	  // Convert an object into a list of `[key, value]` pairs.
    743	  _.pairs = function(obj) {
    744	    var pairs = [];
    745	    for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
    746	    return pairs;
    747	  };
    748	
    749	  // Invert the keys and values of an object. The values must be serializable.
    750	  _.invert = function(obj) {
    751	    var result = {};
    752	    for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
    753	    return result;
    754	  };
    755	
    756	  // Return a sorted list of the function names available on the object.
    757	  // Aliased as `methods`
    758	  _.functions = _.methods = function(obj) {
    759	    var names = [];
    760	    for (var key in obj) {
    761	      if (_.isFunction(obj[key])) names.push(key);
    762	    }
    763	    return names.sort();
    764	  };
    765	
    766	  // Extend a given object with all the properties in passed-in object(s).
    767	  _.extend = function(obj) {
    768	    each(slice.call(arguments, 1), function(source) {
    769	      if (source) {
    770	        for (var prop in source) {
    771	          obj[prop] = source[prop];
    772	        }
    773	      }
    774	    });
    775	    return obj;
    776	  };
    777	
    778	  // Return a copy of the object only containing the whitelisted properties.
    779	  _.pick = function(obj) {
    780	    var copy = {};
    781	    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
    782	    each(keys, function(key) {
    783	      if (key in obj) copy[key] = obj[key];
    784	    });
    785	    return copy;
    786	  };
    787	
    788	   // Return a copy of the object without the blacklisted properties.
    789	  _.omit = function(obj) {
    790	    var copy = {};
    791	    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
    792	    for (var key in obj) {
    793	      if (!_.contains(keys, key)) copy[key] = obj[key];
    794	    }
    795	    return copy;
    796	  };
    797	
    798	  // Fill in a given object with default properties.
    799	  _.defaults = function(obj) {
    800	    each(slice.call(arguments, 1), function(source) {
    801	      if (source) {
    802	        for (var prop in source) {
    803	          if (obj[prop] == null) obj[prop] = source[prop];
    804	        }
    805	      }
    806	    });
    807	    return obj;
    808	  };
    809	
    810	  // Create a (shallow-cloned) duplicate of an object.
    811	  _.clone = function(obj) {
    812	    if (!_.isObject(obj)) return obj;
    813	    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
    814	  };
    815	
    816	  // Invokes interceptor with the obj, and then returns obj.
    817	  // The primary purpose of this method is to "tap into" a method chain, in
    818	  // order to perform operations on intermediate results within the chain.
    819	  _.tap = function(obj, interceptor) {
    820	    interceptor(obj);
    821	    return obj;
    822	  };
    823	
    824	  // Internal recursive comparison function for `isEqual`.
    825	  var eq = function(a, b, aStack, bStack) {
    826	    // Identical objects are equal. `0 === -0`, but they aren't identical.
    827	    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
    828	    if (a === b) return a !== 0 || 1 / a == 1 / b;
    829	    // A strict comparison is necessary because `null == undefined`.
    830	    if (a == null || b == null) return a === b;
    831	    // Unwrap any wrapped objects.
    832	    if (a instanceof _) a = a._wrapped;
    833	    if (b instanceof _) b = b._wrapped;
    834	    // Compare `[[Class]]` names.
    835	    var className = toString.call(a);
    836	    if (className != toString.call(b)) return false;
    837	    switch (className) {
    838	      // Strings, numbers, dates, and booleans are compared by value.
    839	      case '[object String]':
    840	        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
    841	        // equivalent to `new String("5")`.
    842	        return a == String(b);
    843	      case '[object Number]':
    844	        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
    845	        // other numeric values.
    846	        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
    847	      case '[object Date]':
    848	      case '[object Boolean]':
    849	        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
    850	        // millisecond representations. Note that invalid dates with millisecond representations
    851	        // of `NaN` are not equivalent.
    852	        return +a == +b;
    853	      // RegExps are compared by their source patterns and flags.
    854	      case '[object RegExp]':
    855	        return a.source == b.source &&
    856	               a.global == b.global &&
    857	               a.multiline == b.multiline &&
    858	               a.ignoreCase == b.ignoreCase;
    859	    }
    860	    if (typeof a != 'object' || typeof b != 'object') return false;
    861	    // Assume equality for cyclic structures. The algorithm for detecting cyclic
    862	    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
    863	    var length = aStack.length;
    864	    while (length--) {
    865	      // Linear search. Performance is inversely proportional to the number of
    866	      // unique nested structures.
    867	      if (aStack[length] == a) return bStack[length] == b;
    868	    }
    869	    // Add the first object to the stack of traversed objects.
    870	    aStack.push(a);
    871	    bStack.push(b);
    872	    var size = 0, result = true;
    873	    // Recursively compare objects and arrays.
    874	    if (className == '[object Array]') {
    875	      // Compare array lengths to determine if a deep comparison is necessary.
    876	      size = a.length;
    877	      result = size == b.length;
    878	      if (result) {
    879	        // Deep compare the contents, ignoring non-numeric properties.
    880	        while (size--) {
    881	          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
    882	        }
    883	      }
    884	    } else {
    885	      // Objects with different constructors are not equivalent, but `Object`s
    886	      // from different frames are.
    887	      var aCtor = a.constructor, bCtor = b.constructor;
    888	      if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
    889	                               _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
    890	        return false;
    891	      }
    892	      // Deep compare objects.
    893	      for (var key in a) {
    894	        if (_.has(a, key)) {
    895	          // Count the expected number of properties.
    896	          size++;
    897	          // Deep compare each member.
    898	          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
    899	        }
    900	      }
    901	      // Ensure that both objects contain the same number of properties.
    902	      if (result) {
    903	        for (key in b) {
    904	          if (_.has(b, key) && !(size--)) break;
    905	        }
    906	        result = !size;
    907	      }
    908	    }
    909	    // Remove the first object from the stack of traversed objects.
    910	    aStack.pop();
    911	    bStack.pop();
    912	    return result;
    913	  };
    914	
    915	  // Perform a deep comparison to check if two objects are equal.
    916	  _.isEqual = function(a, b) {
    917	    return eq(a, b, [], []);
    918	  };
    919	
    920	  // Is a given array, string, or object empty?
    921	  // An "empty" object has no enumerable own-properties.
    922	  _.isEmpty = function(obj) {
    923	    if (obj == null) return true;
    924	    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
    925	    for (var key in obj) if (_.has(obj, key)) return false;
    926	    return true;
    927	  };
    928	
    929	  // Is a given value a DOM element?
    930	  _.isElement = function(obj) {
    931	    return !!(obj && obj.nodeType === 1);
    932	  };
    933	
    934	  // Is a given value an array?
    935	  // Delegates to ECMA5's native Array.isArray
    936	  _.isArray = nativeIsArray || function(obj) {
    937	    return toString.call(obj) == '[object Array]';
    938	  };
    939	
    940	  // Is a given variable an object?
    941	  _.isObject = function(obj) {
    942	    return obj === Object(obj);
    943	  };
    944	
    945	  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
    946	  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
    947	    _['is' + name] = function(obj) {
    948	      return toString.call(obj) == '[object ' + name + ']';
    949	    };
    950	  });
    951	
    952	  // Define a fallback version of the method in browsers (ahem, IE), where
    953	  // there isn't any inspectable "Arguments" type.
    954	  if (!_.isArguments(arguments)) {
    955	    _.isArguments = function(obj) {
    956	      return !!(obj && _.has(obj, 'callee'));
    957	    };
    958	  }
    959	
    960	  // Optimize `isFunction` if appropriate.
    961	  if (typeof (/./) !== 'function') {
    962	    _.isFunction = function(obj) {
    963	      return typeof obj === 'function';
    964	    };
    965	  }
    966	
    967	  // Is a given object a finite number?
    968	  _.isFinite = function(obj) {
    969	    return isFinite(obj) && !isNaN(parseFloat(obj));
    970	  };
    971	
    972	  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
    973	  _.isNaN = function(obj) {
    974	    return _.isNumber(obj) && obj != +obj;
    975	  };
    976	
    977	  // Is a given value a boolean?
    978	  _.isBoolean = function(obj) {
    979	    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
    980	  };
    981	
    982	  // Is a given value equal to null?
    983	  _.isNull = function(obj) {
    984	    return obj === null;
    985	  };
    986	
    987	  // Is a given variable undefined?
    988	  _.isUndefined = function(obj) {
    989	    return obj === void 0;
    990	  };
    991	
    992	  // Shortcut function for checking if an object has a given property directly
    993	  // on itself (in other words, not on a prototype).
    994	  _.has = function(obj, key) {
    995	    return hasOwnProperty.call(obj, key);
    996	  };
    997	
    998	  // Utility Functions
    999	  // -----------------
    1000	
    1001	  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
    1002	  // previous owner. Returns a reference to the Underscore object.
    1003	  _.noConflict = function() {
    1004	    root._ = previousUnderscore;
    1005	    return this;
    1006	  };
    1007	
    1008	  // Keep the identity function around for default iterators.
    1009	  _.identity = function(value) {
    1010	    return value;
    1011	  };
    1012	
    1013	  // Run a function **n** times.
    1014	  _.times = function(n, iterator, context) {
    1015	    var accum = Array(n);
    1016	    for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
    1017	    return accum;
    1018	  };
    1019	
    1020	  // Return a random integer between min and max (inclusive).
    1021	  _.random = function(min, max) {
    1022	    if (max == null) {
    1023	      max = min;
    1024	      min = 0;
    1025	    }
    1026	    return min + Math.floor(Math.random() * (max - min + 1));
    1027	  };
    1028	
    1029	  // List of HTML entities for escaping.
    1030	  var entityMap = {
    1031	    escape: {
    1032	      '&': '&amp;',
    1033	      '<': '&lt;',
    1034	      '>': '&gt;',
    1035	      '"': '&quot;',
    1036	      "'": '&#x27;',
    1037	      '/': '&#x2F;'
    1038	    }
    1039	  };
    1040	  entityMap.unescape = _.invert(entityMap.escape);
    1041	
    1042	  // Regexes containing the keys and values listed immediately above.
    1043	  var entityRegexes = {
    1044	    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
    1045	    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
    1046	  };
    1047	
    1048	  // Functions for escaping and unescaping strings to/from HTML interpolation.
    1049	  _.each(['escape', 'unescape'], function(method) {
    1050	    _[method] = function(string) {
    1051	      if (string == null) return '';
    1052	      return ('' + string).replace(entityRegexes[method], function(match) {
    1053	        return entityMap[method][match];
    1054	      });
    1055	    };
    1056	  });
    1057	
    1058	  // If the value of the named property is a function then invoke it;
    1059	  // otherwise, return it.
    1060	  _.result = function(object, property) {
    1061	    if (object == null) return null;
    1062	    var value = object[property];
    1063	    return _.isFunction(value) ? value.call(object) : value;
    1064	  };
    1065	
    1066	  // Add your own custom functions to the Underscore object.
    1067	  _.mixin = function(obj) {
    1068	    each(_.functions(obj), function(name){
    1069	      var func = _[name] = obj[name];
    1070	      _.prototype[name] = function() {
    1071	        var args = [this._wrapped];
    1072	        push.apply(args, arguments);
    1073	        return result.call(this, func.apply(_, args));
    1074	      };
    1075	    });
    1076	  };
    1077	
    1078	  // Generate a unique integer id (unique within the entire client session).
    1079	  // Useful for temporary DOM ids.
    1080	  var idCounter = 0;
    1081	  _.uniqueId = function(prefix) {
    1082	    var id = ++idCounter + '';
    1083	    return prefix ? prefix + id : id;
    1084	  };
    1085	
    1086	  // By default, Underscore uses ERB-style template delimiters, change the
    1087	  // following template settings to use alternative delimiters.
    1088	  _.templateSettings = {
    1089	    evaluate    : /<%([\s\S]+?)%>/g,
    1090	    interpolate : /<%=([\s\S]+?)%>/g,
    1091	    escape      : /<%-([\s\S]+?)%>/g
    1092	  };
    1093	
    1094	  // When customizing `templateSettings`, if you don't want to define an
    1095	  // interpolation, evaluation or escaping regex, we need one that is
    1096	  // guaranteed not to match.
    1097	  var noMatch = /(.)^/;
    1098	
    1099	  // Certain characters need to be escaped so that they can be put into a
    1100	  // string literal.
    1101	  var escapes = {
    1102	    "'":      "'",
    1103	    '\\':     '\\',
    1104	    '\r':     'r',
    1105	    '\n':     'n',
    1106	    '\t':     't',
    1107	    '\u2028': 'u2028',
    1108	    '\u2029': 'u2029'
    1109	  };
    1110	
    1111	  var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
    1112	
    1113	  // JavaScript micro-templating, similar to John Resig's implementation.
    1114	  // Underscore templating handles arbitrary delimiters, preserves whitespace,
    1115	  // and correctly escapes quotes within interpolated code.
    1116	  _.template = function(text, data, settings) {
    1117	    var render;
    1118	    settings = _.defaults({}, settings, _.templateSettings);
    1119	
    1120	    // Combine delimiters into one regular expression via alternation.
    1121	    var matcher = new RegExp([
    1122	      (settings.escape || noMatch).source,
    1123	      (settings.interpolate || noMatch).source,
    1124	      (settings.evaluate || noMatch).source
    1125	    ].join('|') + '|$', 'g');
    1126	
    1127	    // Compile the template source, escaping string literals appropriately.
    1128	    var index = 0;
    1129	    var source = "__p+='";
    1130	    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
    1131	      source += text.slice(index, offset)
    1132	        .replace(escaper, function(match) { return '\\' + escapes[match]; });
    1133	
    1134	      if (escape) {
    1135	        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
    1136	      }
    1137	      if (interpolate) {
    1138	        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
    1139	      }
    1140	      if (evaluate) {
    1141	        source += "';\n" + evaluate + "\n__p+='";
    1142	      }
    1143	      index = offset + match.length;
    1144	      return match;
    1145	    });
    1146	    source += "';\n";
    1147	
    1148	    // If a variable is not specified, place data values in local scope.
    1149	    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
    1150	
    1151	    source = "var __t,__p='',__j=Array.prototype.join," +
    1152	      "print=function(){__p+=__j.call(arguments,'');};\n" +
    1153	      source + "return __p;\n";
    1154	
    1155	    try {
    1156	      render = new Function(settings.variable || 'obj', '_', source);
    1157	    } catch (e) {
    1158	      e.source = source;
    1159	      throw e;
    1160	    }
    1161	
    1162	    if (data) return render(data, _);
    1163	    var template = function(data) {
    1164	      return render.call(this, data, _);
    1165	    };
    1166	
    1167	    // Provide the compiled function source as a convenience for precompilation.
    1168	    template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
    1169	
    1170	    return template;
    1171	  };
    1172	
    1173	  // Add a "chain" function, which will delegate to the wrapper.
    1174	  _.chain = function(obj) {
    1175	    return _(obj).chain();
    1176	  };
    1177	
    1178	  // OOP
    1179	  // ---------------
    1180	  // If Underscore is called as a function, it returns a wrapped object that
    1181	  // can be used OO-style. This wrapper holds altered versions of all the
    1182	  // underscore functions. Wrapped objects may be chained.
    1183	
    1184	  // Helper function to continue chaining intermediate results.
    1185	  var result = function(obj) {
    1186	    return this._chain ? _(obj).chain() : obj;
    1187	  };
    1188	
    1189	  // Add all of the Underscore functions to the wrapper object.
    1190	  _.mixin(_);
    1191	
    1192	  // Add all mutator Array functions to the wrapper.
    1193	  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
    1194	    var method = ArrayProto[name];
    1195	    _.prototype[name] = function() {
    1196	      var obj = this._wrapped;
    1197	      method.apply(obj, arguments);
    1198	      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
    1199	      return result.call(this, obj);
    1200	    };
    1201	  });
    1202	
    1203	  // Add all accessor Array functions to the wrapper.
    1204	  each(['concat', 'join', 'slice'], function(name) {
    1205	    var method = ArrayProto[name];
    1206	    _.prototype[name] = function() {
    1207	      return result.call(this, method.apply(this._wrapped, arguments));
    1208	    };
    1209	  });
    1210	
    1211	  _.extend(_.prototype, {
    1212	
    1213	    // Start chaining a wrapped Underscore object.
    1214	    chain: function() {
    1215	      this._chain = true;
    1216	      return this;
    1217	    },
    1218	
    1219	    // Extracts the result from a wrapped and chained object.
    1220	    value: function() {
    1221	      return this._wrapped;
    1222	    }
    1223	
    1224	  });
    1225	
    1226	}).call(this);
  • WordPress 源代码——主干(underscore-1.4.1.js)

    WordPress 源代码——主干(underscore-1.4.1.js)

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

    WordPress 源代码——主干(backbone-0.9.2.js)

    //     Backbone.js 0.9.2
    2	
    3	//     (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
    4	//     Backbone may be freely distributed under the MIT license.
    5	//     For all details and documentation:
    6	//     http://backbonejs.org
    7	
    8	(function(){
    9	
    10	  // Initial Setup
    11	  // -------------
    12	
    13	  // Save a reference to the global object (`window` in the browser, `global`
    14	  // on the server).
    15	  var root = this;
    16	
    17	  // Save the previous value of the `Backbone` variable, so that it can be
    18	  // restored later on, if `noConflict` is used.
    19	  var previousBackbone = root.Backbone;
    20	
    21	  // Create a local reference to slice/splice.
    22	  var slice = Array.prototype.slice;
    23	  var splice = Array.prototype.splice;
    24	
    25	  // The top-level namespace. All public Backbone classes and modules will
    26	  // be attached to this. Exported for both CommonJS and the browser.
    27	  var Backbone;
    28	  if (typeof exports !== 'undefined') {
    29	    Backbone = exports;
    30	  } else {
    31	    Backbone = root.Backbone = {};
    32	  }
    33	
    34	  // Current version of the library. Keep in sync with `package.json`.
    35	  Backbone.VERSION = '0.9.2';
    36	
    37	  // Require Underscore, if we're on the server, and it's not already present.
    38	  var _ = root._;
    39	  if (!_ && (typeof require !== 'undefined')) _ = require('underscore');
    40	
    41	  // For Backbone's purposes, jQuery, Zepto, or Ender owns the `$` variable.
    42	  var $ = root.jQuery || root.Zepto || root.ender;
    43	
    44	  // Set the JavaScript library that will be used for DOM manipulation and
    45	  // Ajax calls (a.k.a. the `$` variable). By default Backbone will use: jQuery,
    46	  // Zepto, or Ender; but the `setDomLibrary()` method lets you inject an
    47	  // alternate JavaScript library (or a mock library for testing your views
    48	  // outside of a browser).
    49	  Backbone.setDomLibrary = function(lib) {
    50	    $ = lib;
    51	  };
    52	
    53	  // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
    54	  // to its previous owner. Returns a reference to this Backbone object.
    55	  Backbone.noConflict = function() {
    56	    root.Backbone = previousBackbone;
    57	    return this;
    58	  };
    59	
    60	  // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
    61	  // will fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and
    62	  // set a `X-Http-Method-Override` header.
    63	  Backbone.emulateHTTP = false;
    64	
    65	  // Turn on `emulateJSON` to support legacy servers that can't deal with direct
    66	  // `application/json` requests ... will encode the body as
    67	  // `application/x-www-form-urlencoded` instead and will send the model in a
    68	  // form param named `model`.
    69	  Backbone.emulateJSON = false;
    70	
    71	  // Backbone.Events
    72	  // -----------------
    73	
    74	  // Regular expression used to split event strings
    75	  var eventSplitter = /\s+/;
    76	
    77	  // A module that can be mixed in to *any object* in order to provide it with
    78	  // custom events. You may bind with `on` or remove with `off` callback functions
    79	  // to an event; trigger`-ing an event fires all callbacks in succession.
    80	  //
    81	  //     var object = {};
    82	  //     _.extend(object, Backbone.Events);
    83	  //     object.on('expand', function(){ alert('expanded'); });
    84	  //     object.trigger('expand');
    85	  //
    86	  var Events = Backbone.Events = {
    87	
    88	    // Bind one or more space separated events, `events`, to a `callback`
    89	    // function. Passing `"all"` will bind the callback to all events fired.
    90	    on: function(events, callback, context) {
    91	
    92	      var calls, event, node, tail, list;
    93	      if (!callback) return this;
    94	      events = events.split(eventSplitter);
    95	      calls = this._callbacks || (this._callbacks = {});
    96	
    97	      // Create an immutable callback list, allowing traversal during
    98	      // modification.  The tail is an empty object that will always be used
    99	      // as the next node.
    100	      while (event = events.shift()) {
    101	        list = calls[event];
    102	        node = list ? list.tail : {};
    103	        node.next = tail = {};
    104	        node.context = context;
    105	        node.callback = callback;
    106	        calls[event] = {tail: tail, next: list ? list.next : node};
    107	      }
    108	
    109	      return this;
    110	    },
    111	
    112	    // Remove one or many callbacks. If `context` is null, removes all callbacks
    113	    // with that function. If `callback` is null, removes all callbacks for the
    114	    // event. If `events` is null, removes all bound callbacks for all events.
    115	    off: function(events, callback, context) {
    116	      var event, calls, node, tail, cb, ctx;
    117	
    118	      // No events, or removing *all* events.
    119	      if (!(calls = this._callbacks)) return;
    120	      if (!(events || callback || context)) {
    121	        delete this._callbacks;
    122	        return this;
    123	      }
    124	
    125	      // Loop through the listed events and contexts, splicing them out of the
    126	      // linked list of callbacks if appropriate.
    127	      events = events ? events.split(eventSplitter) : _.keys(calls);
    128	      while (event = events.shift()) {
    129	        node = calls[event];
    130	        delete calls[event];
    131	        if (!node || !(callback || context)) continue;
    132	        // Create a new list, omitting the indicated callbacks.
    133	        tail = node.tail;
    134	        while ((node = node.next) !== tail) {
    135	          cb = node.callback;
    136	          ctx = node.context;
    137	          if ((callback && cb !== callback) || (context && ctx !== context)) {
    138	            this.on(event, cb, ctx);
    139	          }
    140	        }
    141	      }
    142	
    143	      return this;
    144	    },
    145	
    146	    // Trigger one or many events, firing all bound callbacks. Callbacks are
    147	    // passed the same arguments as `trigger` is, apart from the event name
    148	    // (unless you're listening on `"all"`, which will cause your callback to
    149	    // receive the true name of the event as the first argument).
    150	    trigger: function(events) {
    151	      var event, node, calls, tail, args, all, rest;
    152	      if (!(calls = this._callbacks)) return this;
    153	      all = calls.all;
    154	      events = events.split(eventSplitter);
    155	      rest = slice.call(arguments, 1);
    156	
    157	      // For each event, walk through the linked list of callbacks twice,
    158	      // first to trigger the event, then to trigger any `"all"` callbacks.
    159	      while (event = events.shift()) {
    160	        if (node = calls[event]) {
    161	          tail = node.tail;
    162	          while ((node = node.next) !== tail) {
    163	            node.callback.apply(node.context || this, rest);
    164	          }
    165	        }
    166	        if (node = all) {
    167	          tail = node.tail;
    168	          args = [event].concat(rest);
    169	          while ((node = node.next) !== tail) {
    170	            node.callback.apply(node.context || this, args);
    171	          }
    172	        }
    173	      }
    174	
    175	      return this;
    176	    }
    177	
    178	  };
    179	
    180	  // Aliases for backwards compatibility.
    181	  Events.bind   = Events.on;
    182	  Events.unbind = Events.off;
    183	
    184	  // Backbone.Model
    185	  // --------------
    186	
    187	  // Create a new model, with defined attributes. A client id (`cid`)
    188	  // is automatically generated and assigned for you.
    189	  var Model = Backbone.Model = function(attributes, options) {
    190	    var defaults;
    191	    attributes || (attributes = {});
    192	    if (options && options.parse) attributes = this.parse(attributes);
    193	    if (defaults = getValue(this, 'defaults')) {
    194	      attributes = _.extend({}, defaults, attributes);
    195	    }
    196	    if (options && options.collection) this.collection = options.collection;
    197	    this.attributes = {};
    198	    this._escapedAttributes = {};
    199	    this.cid = _.uniqueId('c');
    200	    this.changed = {};
    201	    this._silent = {};
    202	    this._pending = {};
    203	    this.set(attributes, {silent: true});
    204	    // Reset change tracking.
    205	    this.changed = {};
    206	    this._silent = {};
    207	    this._pending = {};
    208	    this._previousAttributes = _.clone(this.attributes);
    209	    this.initialize.apply(this, arguments);
    210	  };
    211	
    212	  // Attach all inheritable methods to the Model prototype.
    213	  _.extend(Model.prototype, Events, {
    214	
    215	    // A hash of attributes whose current and previous value differ.
    216	    changed: null,
    217	
    218	    // A hash of attributes that have silently changed since the last time
    219	    // `change` was called.  Will become pending attributes on the next call.
    220	    _silent: null,
    221	
    222	    // A hash of attributes that have changed since the last `'change'` event
    223	    // began.
    224	    _pending: null,
    225	
    226	    // The default name for the JSON `id` attribute is `"id"`. MongoDB and
    227	    // CouchDB users may want to set this to `"_id"`.
    228	    idAttribute: 'id',
    229	
    230	    // Initialize is an empty function by default. Override it with your own
    231	    // initialization logic.
    232	    initialize: function(){},
    233	
    234	    // Return a copy of the model's `attributes` object.
    235	    toJSON: function(options) {
    236	      return _.clone(this.attributes);
    237	    },
    238	
    239	    // Get the value of an attribute.
    240	    get: function(attr) {
    241	      return this.attributes[attr];
    242	    },
    243	
    244	    // Get the HTML-escaped value of an attribute.
    245	    escape: function(attr) {
    246	      var html;
    247	      if (html = this._escapedAttributes[attr]) return html;
    248	      var val = this.get(attr);
    249	      return this._escapedAttributes[attr] = _.escape(val == null ? '' : '' + val);
    250	    },
    251	
    252	    // Returns `true` if the attribute contains a value that is not null
    253	    // or undefined.
    254	    has: function(attr) {
    255	      return this.get(attr) != null;
    256	    },
    257	
    258	    // Set a hash of model attributes on the object, firing `"change"` unless
    259	    // you choose to silence it.
    260	    set: function(key, value, options) {
    261	      var attrs, attr, val;
    262	
    263	      // Handle both `"key", value` and `{key: value}` -style arguments.
    264	      if (_.isObject(key) || key == null) {
    265	        attrs = key;
    266	        options = value;
    267	      } else {
    268	        attrs = {};
    269	        attrs[key] = value;
    270	      }
    271	
    272	      // Extract attributes and options.
    273	      options || (options = {});
    274	      if (!attrs) return this;
    275	      if (attrs instanceof Model) attrs = attrs.attributes;
    276	      if (options.unset) for (attr in attrs) attrs[attr] = void 0;
    277	
    278	      // Run validation.
    279	      if (!this._validate(attrs, options)) return false;
    280	
    281	      // Check for changes of `id`.
    282	      if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
    283	
    284	      var changes = options.changes = {};
    285	      var now = this.attributes;
    286	      var escaped = this._escapedAttributes;
    287	      var prev = this._previousAttributes || {};
    288	
    289	      // For each `set` attribute...
    290	      for (attr in attrs) {
    291	        val = attrs[attr];
    292	
    293	        // If the new and current value differ, record the change.
    294	        if (!_.isEqual(now[attr], val) || (options.unset && _.has(now, attr))) {
    295	          delete escaped[attr];
    296	          (options.silent ? this._silent : changes)[attr] = true;
    297	        }
    298	
    299	        // Update or delete the current value.
    300	        options.unset ? delete now[attr] : now[attr] = val;
    301	
    302	        // If the new and previous value differ, record the change.  If not,
    303	        // then remove changes for this attribute.
    304	        if (!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) {
    305	          this.changed[attr] = val;
    306	          if (!options.silent) this._pending[attr] = true;
    307	        } else {
    308	          delete this.changed[attr];
    309	          delete this._pending[attr];
    310	        }
    311	      }
    312	
    313	      // Fire the `"change"` events.
    314	      if (!options.silent) this.change(options);
    315	      return this;
    316	    },
    317	
    318	    // Remove an attribute from the model, firing `"change"` unless you choose
    319	    // to silence it. `unset` is a noop if the attribute doesn't exist.
    320	    unset: function(attr, options) {
    321	      (options || (options = {})).unset = true;
    322	      return this.set(attr, null, options);
    323	    },
    324	
    325	    // Clear all attributes on the model, firing `"change"` unless you choose
    326	    // to silence it.
    327	    clear: function(options) {
    328	      (options || (options = {})).unset = true;
    329	      return this.set(_.clone(this.attributes), options);
    330	    },
    331	
    332	    // Fetch the model from the server. If the server's representation of the
    333	    // model differs from its current attributes, they will be overriden,
    334	    // triggering a `"change"` event.
    335	    fetch: function(options) {
    336	      options = options ? _.clone(options) : {};
    337	      var model = this;
    338	      var success = options.success;
    339	      options.success = function(resp, status, xhr) {
    340	        if (!model.set(model.parse(resp, xhr), options)) return false;
    341	        if (success) success(model, resp);
    342	      };
    343	      options.error = Backbone.wrapError(options.error, model, options);
    344	      return (this.sync || Backbone.sync).call(this, 'read', this, options);
    345	    },
    346	
    347	    // Set a hash of model attributes, and sync the model to the server.
    348	    // If the server returns an attributes hash that differs, the model's
    349	    // state will be `set` again.
    350	    save: function(key, value, options) {
    351	      var attrs, current;
    352	
    353	      // Handle both `("key", value)` and `({key: value})` -style calls.
    354	      if (_.isObject(key) || key == null) {
    355	        attrs = key;
    356	        options = value;
    357	      } else {
    358	        attrs = {};
    359	        attrs[key] = value;
    360	      }
    361	      options = options ? _.clone(options) : {};
    362	
    363	      // If we're "wait"-ing to set changed attributes, validate early.
    364	      if (options.wait) {
    365	        if (!this._validate(attrs, options)) return false;
    366	        current = _.clone(this.attributes);
    367	      }
    368	
    369	      // Regular saves `set` attributes before persisting to the server.
    370	      var silentOptions = _.extend({}, options, {silent: true});
    371	      if (attrs && !this.set(attrs, options.wait ? silentOptions : options)) {
    372	        return false;
    373	      }
    374	
    375	      // After a successful server-side save, the client is (optionally)
    376	      // updated with the server-side state.
    377	      var model = this;
    378	      var success = options.success;
    379	      options.success = function(resp, status, xhr) {
    380	        var serverAttrs = model.parse(resp, xhr);
    381	        if (options.wait) {
    382	          delete options.wait;
    383	          serverAttrs = _.extend(attrs || {}, serverAttrs);
    384	        }
    385	        if (!model.set(serverAttrs, options)) return false;
    386	        if (success) {
    387	          success(model, resp);
    388	        } else {
    389	          model.trigger('sync', model, resp, options);
    390	        }
    391	      };
    392	
    393	      // Finish configuring and sending the Ajax request.
    394	      options.error = Backbone.wrapError(options.error, model, options);
    395	      var method = this.isNew() ? 'create' : 'update';
    396	      var xhr = (this.sync || Backbone.sync).call(this, method, this, options);
    397	      if (options.wait) this.set(current, silentOptions);
    398	      return xhr;
    399	    },
    400	
    401	    // Destroy this model on the server if it was already persisted.
    402	    // Optimistically removes the model from its collection, if it has one.
    403	    // If `wait: true` is passed, waits for the server to respond before removal.
    404	    destroy: function(options) {
    405	      options = options ? _.clone(options) : {};
    406	      var model = this;
    407	      var success = options.success;
    408	
    409	      var triggerDestroy = function() {
    410	        model.trigger('destroy', model, model.collection, options);
    411	      };
    412	
    413	      if (this.isNew()) {
    414	        triggerDestroy();
    415	        return false;
    416	      }
    417	
    418	      options.success = function(resp) {
    419	        if (options.wait) triggerDestroy();
    420	        if (success) {
    421	          success(model, resp);
    422	        } else {
    423	          model.trigger('sync', model, resp, options);
    424	        }
    425	      };
    426	
    427	      options.error = Backbone.wrapError(options.error, model, options);
    428	      var xhr = (this.sync || Backbone.sync).call(this, 'delete', this, options);
    429	      if (!options.wait) triggerDestroy();
    430	      return xhr;
    431	    },
    432	
    433	    // Default URL for the model's representation on the server -- if you're
    434	    // using Backbone's restful methods, override this to change the endpoint
    435	    // that will be called.
    436	    url: function() {
    437	      var base = getValue(this, 'urlRoot') || getValue(this.collection, 'url') || urlError();
    438	      if (this.isNew()) return base;
    439	      return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id);
    440	    },
    441	
    442	    // **parse** converts a response into the hash of attributes to be `set` on
    443	    // the model. The default implementation is just to pass the response along.
    444	    parse: function(resp, xhr) {
    445	      return resp;
    446	    },
    447	
    448	    // Create a new model with identical attributes to this one.
    449	    clone: function() {
    450	      return new this.constructor(this.attributes);
    451	    },
    452	
    453	    // A model is new if it has never been saved to the server, and lacks an id.
    454	    isNew: function() {
    455	      return this.id == null;
    456	    },
    457	
    458	    // Call this method to manually fire a `"change"` event for this model and
    459	    // a `"change:attribute"` event for each changed attribute.
    460	    // Calling this will cause all objects observing the model to update.
    461	    change: function(options) {
    462	      options || (options = {});
    463	      var changing = this._changing;
    464	      this._changing = true;
    465	
    466	      // Silent changes become pending changes.
    467	      for (var attr in this._silent) this._pending[attr] = true;
    468	
    469	      // Silent changes are triggered.
    470	      var changes = _.extend({}, options.changes, this._silent);
    471	      this._silent = {};
    472	      for (var attr in changes) {
    473	        this.trigger('change:' + attr, this, this.get(attr), options);
    474	      }
    475	      if (changing) return this;
    476	
    477	      // Continue firing `"change"` events while there are pending changes.
    478	      while (!_.isEmpty(this._pending)) {
    479	        this._pending = {};
    480	        this.trigger('change', this, options);
    481	        // Pending and silent changes still remain.
    482	        for (var attr in this.changed) {
    483	          if (this._pending[attr] || this._silent[attr]) continue;
    484	          delete this.changed[attr];
    485	        }
    486	        this._previousAttributes = _.clone(this.attributes);
    487	      }
    488	
    489	      this._changing = false;
    490	      return this;
    491	    },
    492	
    493	    // Determine if the model has changed since the last `"change"` event.
    494	    // If you specify an attribute name, determine if that attribute has changed.
    495	    hasChanged: function(attr) {
    496	      if (!arguments.length) return !_.isEmpty(this.changed);
    497	      return _.has(this.changed, attr);
    498	    },
    499	
    500	    // Return an object containing all the attributes that have changed, or
    501	    // false if there are no changed attributes. Useful for determining what
    502	    // parts of a view need to be updated and/or what attributes need to be
    503	    // persisted to the server. Unset attributes will be set to undefined.
    504	    // You can also pass an attributes object to diff against the model,
    505	    // determining if there *would be* a change.
    506	    changedAttributes: function(diff) {
    507	      if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
    508	      var val, changed = false, old = this._previousAttributes;
    509	      for (var attr in diff) {
    510	        if (_.isEqual(old[attr], (val = diff[attr]))) continue;
    511	        (changed || (changed = {}))[attr] = val;
    512	      }
    513	      return changed;
    514	    },
    515	
    516	    // Get the previous value of an attribute, recorded at the time the last
    517	    // `"change"` event was fired.
    518	    previous: function(attr) {
    519	      if (!arguments.length || !this._previousAttributes) return null;
    520	      return this._previousAttributes[attr];
    521	    },
    522	
    523	    // Get all of the attributes of the model at the time of the previous
    524	    // `"change"` event.
    525	    previousAttributes: function() {
    526	      return _.clone(this._previousAttributes);
    527	    },
    528	
    529	    // Check if the model is currently in a valid state. It's only possible to
    530	    // get into an *invalid* state if you're using silent changes.
    531	    isValid: function() {
    532	      return !this.validate(this.attributes);
    533	    },
    534	
    535	    // Run validation against the next complete set of model attributes,
    536	    // returning `true` if all is well. If a specific `error` callback has
    537	    // been passed, call that instead of firing the general `"error"` event.
    538	    _validate: function(attrs, options) {
    539	      if (options.silent || !this.validate) return true;
    540	      attrs = _.extend({}, this.attributes, attrs);
    541	      var error = this.validate(attrs, options);
    542	      if (!error) return true;
    543	      if (options && options.error) {
    544	        options.error(this, error, options);
    545	      } else {
    546	        this.trigger('error', this, error, options);
    547	      }
    548	      return false;
    549	    }
    550	
    551	  });
    552	
    553	  // Backbone.Collection
    554	  // -------------------
    555	
    556	  // Provides a standard collection class for our sets of models, ordered
    557	  // or unordered. If a `comparator` is specified, the Collection will maintain
    558	  // its models in sort order, as they're added and removed.
    559	  var Collection = Backbone.Collection = function(models, options) {
    560	    options || (options = {});
    561	    if (options.model) this.model = options.model;
    562	    if (options.comparator) this.comparator = options.comparator;
    563	    this._reset();
    564	    this.initialize.apply(this, arguments);
    565	    if (models) this.reset(models, {silent: true, parse: options.parse});
    566	  };
    567	
    568	  // Define the Collection's inheritable methods.
    569	  _.extend(Collection.prototype, Events, {
    570	
    571	    // The default model for a collection is just a **Backbone.Model**.
    572	    // This should be overridden in most cases.
    573	    model: Model,
    574	
    575	    // Initialize is an empty function by default. Override it with your own
    576	    // initialization logic.
    577	    initialize: function(){},
    578	
    579	    // The JSON representation of a Collection is an array of the
    580	    // models' attributes.
    581	    toJSON: function(options) {
    582	      return this.map(function(model){ return model.toJSON(options); });
    583	    },
    584	
    585	    // Add a model, or list of models to the set. Pass **silent** to avoid
    586	    // firing the `add` event for every new model.
    587	    add: function(models, options) {
    588	      var i, index, length, model, cid, id, cids = {}, ids = {}, dups = [];
    589	      options || (options = {});
    590	      models = _.isArray(models) ? models.slice() : [models];
    591	
    592	      // Begin by turning bare objects into model references, and preventing
    593	      // invalid models or duplicate models from being added.
    594	      for (i = 0, length = models.length; i < length; i++) {
    595	        if (!(model = models[i] = this._prepareModel(models[i], options))) {
    596	          throw new Error("Can't add an invalid model to a collection");
    597	        }
    598	        cid = model.cid;
    599	        id = model.id;
    600	        if (cids[cid] || this._byCid[cid] || ((id != null) && (ids[id] || this._byId[id]))) {
    601	          dups.push(i);
    602	          continue;
    603	        }
    604	        cids[cid] = ids[id] = model;
    605	      }
    606	
    607	      // Remove duplicates.
    608	      i = dups.length;
    609	      while (i--) {
    610	        models.splice(dups[i], 1);
    611	      }
    612	
    613	      // Listen to added models' events, and index models for lookup by
    614	      // `id` and by `cid`.
    615	      for (i = 0, length = models.length; i < length; i++) {
    616	        (model = models[i]).on('all', this._onModelEvent, this);
    617	        this._byCid[model.cid] = model;
    618	        if (model.id != null) this._byId[model.id] = model;
    619	      }
    620	
    621	      // Insert models into the collection, re-sorting if needed, and triggering
    622	      // `add` events unless silenced.
    623	      this.length += length;
    624	      index = options.at != null ? options.at : this.models.length;
    625	      splice.apply(this.models, [index, 0].concat(models));
    626	      if (this.comparator) this.sort({silent: true});
    627	      if (options.silent) return this;
    628	      for (i = 0, length = this.models.length; i < length; i++) {
    629	        if (!cids[(model = this.models[i]).cid]) continue;
    630	        options.index = i;
    631	        model.trigger('add', model, this, options);
    632	      }
    633	      return this;
    634	    },
    635	
    636	    // Remove a model, or a list of models from the set. Pass silent to avoid
    637	    // firing the `remove` event for every model removed.
    638	    remove: function(models, options) {
    639	      var i, l, index, model;
    640	      options || (options = {});
    641	      models = _.isArray(models) ? models.slice() : [models];
    642	      for (i = 0, l = models.length; i < l; i++) {
    643	        model = this.getByCid(models[i]) || this.get(models[i]);
    644	        if (!model) continue;
    645	        delete this._byId[model.id];
    646	        delete this._byCid[model.cid];
    647	        index = this.indexOf(model);
    648	        this.models.splice(index, 1);
    649	        this.length--;
    650	        if (!options.silent) {
    651	          options.index = index;
    652	          model.trigger('remove', model, this, options);
    653	        }
    654	        this._removeReference(model);
    655	      }
    656	      return this;
    657	    },
    658	
    659	    // Add a model to the end of the collection.
    660	    push: function(model, options) {
    661	      model = this._prepareModel(model, options);
    662	      this.add(model, options);
    663	      return model;
    664	    },
    665	
    666	    // Remove a model from the end of the collection.
    667	    pop: function(options) {
    668	      var model = this.at(this.length - 1);
    669	      this.remove(model, options);
    670	      return model;
    671	    },
    672	
    673	    // Add a model to the beginning of the collection.
    674	    unshift: function(model, options) {
    675	      model = this._prepareModel(model, options);
    676	      this.add(model, _.extend({at: 0}, options));
    677	      return model;
    678	    },
    679	
    680	    // Remove a model from the beginning of the collection.
    681	    shift: function(options) {
    682	      var model = this.at(0);
    683	      this.remove(model, options);
    684	      return model;
    685	    },
    686	
    687	    // Get a model from the set by id.
    688	    get: function(id) {
    689	      if (id == null) return void 0;
    690	      return this._byId[id.id != null ? id.id : id];
    691	    },
    692	
    693	    // Get a model from the set by client id.
    694	    getByCid: function(cid) {
    695	      return cid && this._byCid[cid.cid || cid];
    696	    },
    697	
    698	    // Get the model at the given index.
    699	    at: function(index) {
    700	      return this.models[index];
    701	    },
    702	
    703	    // Return models with matching attributes. Useful for simple cases of `filter`.
    704	    where: function(attrs) {
    705	      if (_.isEmpty(attrs)) return [];
    706	      return this.filter(function(model) {
    707	        for (var key in attrs) {
    708	          if (attrs[key] !== model.get(key)) return false;
    709	        }
    710	        return true;
    711	      });
    712	    },
    713	
    714	    // Force the collection to re-sort itself. You don't need to call this under
    715	    // normal circumstances, as the set will maintain sort order as each item
    716	    // is added.
    717	    sort: function(options) {
    718	      options || (options = {});
    719	      if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
    720	      var boundComparator = _.bind(this.comparator, this);
    721	      if (this.comparator.length == 1) {
    722	        this.models = this.sortBy(boundComparator);
    723	      } else {
    724	        this.models.sort(boundComparator);
    725	      }
    726	      if (!options.silent) this.trigger('reset', this, options);
    727	      return this;
    728	    },
    729	
    730	    // Pluck an attribute from each model in the collection.
    731	    pluck: function(attr) {
    732	      return _.map(this.models, function(model){ return model.get(attr); });
    733	    },
    734	
    735	    // When you have more items than you want to add or remove individually,
    736	    // you can reset the entire set with a new list of models, without firing
    737	    // any `add` or `remove` events. Fires `reset` when finished.
    738	    reset: function(models, options) {
    739	      models  || (models = []);
    740	      options || (options = {});
    741	      for (var i = 0, l = this.models.length; i < l; i++) {
    742	        this._removeReference(this.models[i]);
    743	      }
    744	      this._reset();
    745	      this.add(models, _.extend({silent: true}, options));
    746	      if (!options.silent) this.trigger('reset', this, options);
    747	      return this;
    748	    },
    749	
    750	    // Fetch the default set of models for this collection, resetting the
    751	    // collection when they arrive. If `add: true` is passed, appends the
    752	    // models to the collection instead of resetting.
    753	    fetch: function(options) {
    754	      options = options ? _.clone(options) : {};
    755	      if (options.parse === undefined) options.parse = true;
    756	      var collection = this;
    757	      var success = options.success;
    758	      options.success = function(resp, status, xhr) {
    759	        collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options);
    760	        if (success) success(collection, resp);
    761	      };
    762	      options.error = Backbone.wrapError(options.error, collection, options);
    763	      return (this.sync || Backbone.sync).call(this, 'read', this, options);
    764	    },
    765	
    766	    // Create a new instance of a model in this collection. Add the model to the
    767	    // collection immediately, unless `wait: true` is passed, in which case we
    768	    // wait for the server to agree.
    769	    create: function(model, options) {
    770	      var coll = this;
    771	      options = options ? _.clone(options) : {};
    772	      model = this._prepareModel(model, options);
    773	      if (!model) return false;
    774	      if (!options.wait) coll.add(model, options);
    775	      var success = options.success;
    776	      options.success = function(nextModel, resp, xhr) {
    777	        if (options.wait) coll.add(nextModel, options);
    778	        if (success) {
    779	          success(nextModel, resp);
    780	        } else {
    781	          nextModel.trigger('sync', model, resp, options);
    782	        }
    783	      };
    784	      model.save(null, options);
    785	      return model;
    786	    },
    787	
    788	    // **parse** converts a response into a list of models to be added to the
    789	    // collection. The default implementation is just to pass it through.
    790	    parse: function(resp, xhr) {
    791	      return resp;
    792	    },
    793	
    794	    // Proxy to _'s chain. Can't be proxied the same way the rest of the
    795	    // underscore methods are proxied because it relies on the underscore
    796	    // constructor.
    797	    chain: function () {
    798	      return _(this.models).chain();
    799	    },
    800	
    801	    // Reset all internal state. Called when the collection is reset.
    802	    _reset: function(options) {
    803	      this.length = 0;
    804	      this.models = [];
    805	      this._byId  = {};
    806	      this._byCid = {};
    807	    },
    808	
    809	    // Prepare a model or hash of attributes to be added to this collection.
    810	    _prepareModel: function(model, options) {
    811	      options || (options = {});
    812	      if (!(model instanceof Model)) {
    813	        var attrs = model;
    814	        options.collection = this;
    815	        model = new this.model(attrs, options);
    816	        if (!model._validate(model.attributes, options)) model = false;
    817	      } else if (!model.collection) {
    818	        model.collection = this;
    819	      }
    820	      return model;
    821	    },
    822	
    823	    // Internal method to remove a model's ties to a collection.
    824	    _removeReference: function(model) {
    825	      if (this == model.collection) {
    826	        delete model.collection;
    827	      }
    828	      model.off('all', this._onModelEvent, this);
    829	    },
    830	
    831	    // Internal method called every time a model in the set fires an event.
    832	    // Sets need to update their indexes when models change ids. All other
    833	    // events simply proxy through. "add" and "remove" events that originate
    834	    // in other collections are ignored.
    835	    _onModelEvent: function(event, model, collection, options) {
    836	      if ((event == 'add' || event == 'remove') && collection != this) return;
    837	      if (event == 'destroy') {
    838	        this.remove(model, options);
    839	      }
    840	      if (model && event === 'change:' + model.idAttribute) {
    841	        delete this._byId[model.previous(model.idAttribute)];
    842	        this._byId[model.id] = model;
    843	      }
    844	      this.trigger.apply(this, arguments);
    845	    }
    846	
    847	  });
    848	
    849	  // Underscore methods that we want to implement on the Collection.
    850	  var methods = ['forEach', 'each', 'map', 'reduce', 'reduceRight', 'find',
    851	    'detect', 'filter', 'select', 'reject', 'every', 'all', 'some', 'any',
    852	    'include', 'contains', 'invoke', 'max', 'min', 'sortBy', 'sortedIndex',
    853	    'toArray', 'size', 'first', 'initial', 'rest', 'last', 'without', 'indexOf',
    854	    'shuffle', 'lastIndexOf', 'isEmpty', 'groupBy'];
    855	
    856	  // Mix in each Underscore method as a proxy to `Collection#models`.
    857	  _.each(methods, function(method) {
    858	    Collection.prototype[method] = function() {
    859	      return _[method].apply(_, [this.models].concat(_.toArray(arguments)));
    860	    };
    861	  });
    862	
    863	  // Backbone.Router
    864	  // -------------------
    865	
    866	  // Routers map faux-URLs to actions, and fire events when routes are
    867	  // matched. Creating a new one sets its `routes` hash, if not set statically.
    868	  var Router = Backbone.Router = function(options) {
    869	    options || (options = {});
    870	    if (options.routes) this.routes = options.routes;
    871	    this._bindRoutes();
    872	    this.initialize.apply(this, arguments);
    873	  };
    874	
    875	  // Cached regular expressions for matching named param parts and splatted
    876	  // parts of route strings.
    877	  var namedParam    = /:\w+/g;
    878	  var splatParam    = /\*\w+/g;
    879	  var escapeRegExp  = /[-[\]{}()+?.,\\^$|#\s]/g;
    880	
    881	  // Set up all inheritable **Backbone.Router** properties and methods.
    882	  _.extend(Router.prototype, Events, {
    883	
    884	    // Initialize is an empty function by default. Override it with your own
    885	    // initialization logic.
    886	    initialize: function(){},
    887	
    888	    // Manually bind a single named route to a callback. For example:
    889	    //
    890	    //     this.route('search/:query/p:num', 'search', function(query, num) {
    891	    //       ...
    892	    //     });
    893	    //
    894	    route: function(route, name, callback) {
    895	      Backbone.history || (Backbone.history = new History);
    896	      if (!_.isRegExp(route)) route = this._routeToRegExp(route);
    897	      if (!callback) callback = this[name];
    898	      Backbone.history.route(route, _.bind(function(fragment) {
    899	        var args = this._extractParameters(route, fragment);
    900	        callback && callback.apply(this, args);
    901	        this.trigger.apply(this, ['route:' + name].concat(args));
    902	        Backbone.history.trigger('route', this, name, args);
    903	      }, this));
    904	      return this;
    905	    },
    906	
    907	    // Simple proxy to `Backbone.history` to save a fragment into the history.
    908	    navigate: function(fragment, options) {
    909	      Backbone.history.navigate(fragment, options);
    910	    },
    911	
    912	    // Bind all defined routes to `Backbone.history`. We have to reverse the
    913	    // order of the routes here to support behavior where the most general
    914	    // routes can be defined at the bottom of the route map.
    915	    _bindRoutes: function() {
    916	      if (!this.routes) return;
    917	      var routes = [];
    918	      for (var route in this.routes) {
    919	        routes.unshift([route, this.routes[route]]);
    920	      }
    921	      for (var i = 0, l = routes.length; i < l; i++) {
    922	        this.route(routes[i][0], routes[i][1], this[routes[i][1]]);
    923	      }
    924	    },
    925	
    926	    // Convert a route string into a regular expression, suitable for matching
    927	    // against the current location hash.
    928	    _routeToRegExp: function(route) {
    929	      route = route.replace(escapeRegExp, '\\$&')
    930	                   .replace(namedParam, '([^\/]+)')
    931	                   .replace(splatParam, '(.*?)');
    932	      return new RegExp('^' + route + '$');
    933	    },
    934	
    935	    // Given a route, and a URL fragment that it matches, return the array of
    936	    // extracted parameters.
    937	    _extractParameters: function(route, fragment) {
    938	      return route.exec(fragment).slice(1);
    939	    }
    940	
    941	  });
    942	
    943	  // Backbone.History
    944	  // ----------------
    945	
    946	  // Handles cross-browser history management, based on URL fragments. If the
    947	  // browser does not support `onhashchange`, falls back to polling.
    948	  var History = Backbone.History = function() {
    949	    this.handlers = [];
    950	    _.bindAll(this, 'checkUrl');
    951	  };
    952	
    953	  // Cached regex for cleaning leading hashes and slashes .
    954	  var routeStripper = /^[#\/]/;
    955	
    956	  // Cached regex for detecting MSIE.
    957	  var isExplorer = /msie [\w.]+/;
    958	
    959	  // Has the history handling already been started?
    960	  History.started = false;
    961	
    962	  // Set up all inheritable **Backbone.History** properties and methods.
    963	  _.extend(History.prototype, Events, {
    964	
    965	    // The default interval to poll for hash changes, if necessary, is
    966	    // twenty times a second.
    967	    interval: 50,
    968	
    969	    // Gets the true hash value. Cannot use location.hash directly due to bug
    970	    // in Firefox where location.hash will always be decoded.
    971	    getHash: function(windowOverride) {
    972	      var loc = windowOverride ? windowOverride.location : window.location;
    973	      var match = loc.href.match(/#(.*)$/);
    974	      return match ? match[1] : '';
    975	    },
    976	
    977	    // Get the cross-browser normalized URL fragment, either from the URL,
    978	    // the hash, or the override.
    979	    getFragment: function(fragment, forcePushState) {
    980	      if (fragment == null) {
    981	        if (this._hasPushState || forcePushState) {
    982	          fragment = window.location.pathname;
    983	          var search = window.location.search;
    984	          if (search) fragment += search;
    985	        } else {
    986	          fragment = this.getHash();
    987	        }
    988	      }
    989	      if (!fragment.indexOf(this.options.root)) fragment = fragment.substr(this.options.root.length);
    990	      return fragment.replace(routeStripper, '');
    991	    },
    992	
    993	    // Start the hash change handling, returning `true` if the current URL matches
    994	    // an existing route, and `false` otherwise.
    995	    start: function(options) {
    996	      if (History.started) throw new Error("Backbone.history has already been started");
    997	      History.started = true;
    998	
    999	      // Figure out the initial configuration. Do we need an iframe?
    1000	      // Is pushState desired ... is it available?
    1001	      this.options          = _.extend({}, {root: '/'}, this.options, options);
    1002	      this._wantsHashChange = this.options.hashChange !== false;
    1003	      this._wantsPushState  = !!this.options.pushState;
    1004	      this._hasPushState    = !!(this.options.pushState && window.history && window.history.pushState);
    1005	      var fragment          = this.getFragment();
    1006	      var docMode           = document.documentMode;
    1007	      var oldIE             = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
    1008	
    1009	      if (oldIE) {
    1010	        this.iframe = $('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
    1011	        this.navigate(fragment);
    1012	      }
    1013	
    1014	      // Depending on whether we're using pushState or hashes, and whether
    1015	      // 'onhashchange' is supported, determine how we check the URL state.
    1016	      if (this._hasPushState) {
    1017	        $(window).bind('popstate', this.checkUrl);
    1018	      } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {
    1019	        $(window).bind('hashchange', this.checkUrl);
    1020	      } else if (this._wantsHashChange) {
    1021	        this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
    1022	      }
    1023	
    1024	      // Determine if we need to change the base url, for a pushState link
    1025	      // opened by a non-pushState browser.
    1026	      this.fragment = fragment;
    1027	      var loc = window.location;
    1028	      var atRoot  = loc.pathname == this.options.root;
    1029	
    1030	      // If we've started off with a route from a `pushState`-enabled browser,
    1031	      // but we're currently in a browser that doesn't support it...
    1032	      if (this._wantsHashChange && this._wantsPushState && !this._hasPushState && !atRoot) {
    1033	        this.fragment = this.getFragment(null, true);
    1034	        window.location.replace(this.options.root + '#' + this.fragment);
    1035	        // Return immediately as browser will do redirect to new url
    1036	        return true;
    1037	
    1038	      // Or if we've started out with a hash-based route, but we're currently
    1039	      // in a browser where it could be `pushState`-based instead...
    1040	      } else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {
    1041	        this.fragment = this.getHash().replace(routeStripper, '');
    1042	        window.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment);
    1043	      }
    1044	
    1045	      if (!this.options.silent) {
    1046	        return this.loadUrl();
    1047	      }
    1048	    },
    1049	
    1050	    // Disable Backbone.history, perhaps temporarily. Not useful in a real app,
    1051	    // but possibly useful for unit testing Routers.
    1052	    stop: function() {
    1053	      $(window).unbind('popstate', this.checkUrl).unbind('hashchange', this.checkUrl);
    1054	      clearInterval(this._checkUrlInterval);
    1055	      History.started = false;
    1056	    },
    1057	
    1058	    // Add a route to be tested when the fragment changes. Routes added later
    1059	    // may override previous routes.
    1060	    route: function(route, callback) {
    1061	      this.handlers.unshift({route: route, callback: callback});
    1062	    },
    1063	
    1064	    // Checks the current URL to see if it has changed, and if it has,
    1065	    // calls `loadUrl`, normalizing across the hidden iframe.
    1066	    checkUrl: function(e) {
    1067	      var current = this.getFragment();
    1068	      if (current == this.fragment && this.iframe) current = this.getFragment(this.getHash(this.iframe));
    1069	      if (current == this.fragment) return false;
    1070	      if (this.iframe) this.navigate(current);
    1071	      this.loadUrl() || this.loadUrl(this.getHash());
    1072	    },
    1073	
    1074	    // Attempt to load the current URL fragment. If a route succeeds with a
    1075	    // match, returns `true`. If no defined routes matches the fragment,
    1076	    // returns `false`.
    1077	    loadUrl: function(fragmentOverride) {
    1078	      var fragment = this.fragment = this.getFragment(fragmentOverride);
    1079	      var matched = _.any(this.handlers, function(handler) {
    1080	        if (handler.route.test(fragment)) {
    1081	          handler.callback(fragment);
    1082	          return true;
    1083	        }
    1084	      });
    1085	      return matched;
    1086	    },
    1087	
    1088	    // Save a fragment into the hash history, or replace the URL state if the
    1089	    // 'replace' option is passed. You are responsible for properly URL-encoding
    1090	    // the fragment in advance.
    1091	    //
    1092	    // The options object can contain `trigger: true` if you wish to have the
    1093	    // route callback be fired (not usually desirable), or `replace: true`, if
    1094	    // you wish to modify the current URL without adding an entry to the history.
    1095	    navigate: function(fragment, options) {
    1096	      if (!History.started) return false;
    1097	      if (!options || options === true) options = {trigger: options};
    1098	      var frag = (fragment || '').replace(routeStripper, '');
    1099	      if (this.fragment == frag) return;
    1100	
    1101	      // If pushState is available, we use it to set the fragment as a real URL.
    1102	      if (this._hasPushState) {
    1103	        if (frag.indexOf(this.options.root) != 0) frag = this.options.root + frag;
    1104	        this.fragment = frag;
    1105	        window.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, frag);
    1106	
    1107	      // If hash changes haven't been explicitly disabled, update the hash
    1108	      // fragment to store history.
    1109	      } else if (this._wantsHashChange) {
    1110	        this.fragment = frag;
    1111	        this._updateHash(window.location, frag, options.replace);
    1112	        if (this.iframe && (frag != this.getFragment(this.getHash(this.iframe)))) {
    1113	          // Opening and closing the iframe tricks IE7 and earlier to push a history entry on hash-tag change.
    1114	          // When replace is true, we don't want this.
    1115	          if(!options.replace) this.iframe.document.open().close();
    1116	          this._updateHash(this.iframe.location, frag, options.replace);
    1117	        }
    1118	
    1119	      // If you've told us that you explicitly don't want fallback hashchange-
    1120	      // based history, then `navigate` becomes a page refresh.
    1121	      } else {
    1122	        window.location.assign(this.options.root + fragment);
    1123	      }
    1124	      if (options.trigger) this.loadUrl(fragment);
    1125	    },
    1126	
    1127	    // Update the hash location, either replacing the current entry, or adding
    1128	    // a new one to the browser history.
    1129	    _updateHash: function(location, fragment, replace) {
    1130	      if (replace) {
    1131	        location.replace(location.toString().replace(/(javascript:|#).*$/, '') + '#' + fragment);
    1132	      } else {
    1133	        location.hash = fragment;
    1134	      }
    1135	    }
    1136	  });
    1137	
    1138	  // Backbone.View
    1139	  // -------------
    1140	
    1141	  // Creating a Backbone.View creates its initial element outside of the DOM,
    1142	  // if an existing element is not provided...
    1143	  var View = Backbone.View = function(options) {
    1144	    this.cid = _.uniqueId('view');
    1145	    this._configure(options || {});
    1146	    this._ensureElement();
    1147	    this.initialize.apply(this, arguments);
    1148	    this.delegateEvents();
    1149	  };
    1150	
    1151	  // Cached regex to split keys for `delegate`.
    1152	  var delegateEventSplitter = /^(\S+)\s*(.*)$/;
    1153	
    1154	  // List of view options to be merged as properties.
    1155	  var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName'];
    1156	
    1157	  // Set up all inheritable **Backbone.View** properties and methods.
    1158	  _.extend(View.prototype, Events, {
    1159	
    1160	    // The default `tagName` of a View's element is `"div"`.
    1161	    tagName: 'div',
    1162	
    1163	    // jQuery delegate for element lookup, scoped to DOM elements within the
    1164	    // current view. This should be prefered to global lookups where possible.
    1165	    $: function(selector) {
    1166	      return this.$el.find(selector);
    1167	    },
    1168	
    1169	    // Initialize is an empty function by default. Override it with your own
    1170	    // initialization logic.
    1171	    initialize: function(){},
    1172	
    1173	    // **render** is the core function that your view should override, in order
    1174	    // to populate its element (`this.el`), with the appropriate HTML. The
    1175	    // convention is for **render** to always return `this`.
    1176	    render: function() {
    1177	      return this;
    1178	    },
    1179	
    1180	    // Remove this view from the DOM. Note that the view isn't present in the
    1181	    // DOM by default, so calling this method may be a no-op.
    1182	    remove: function() {
    1183	      this.$el.remove();
    1184	      return this;
    1185	    },
    1186	
    1187	    // For small amounts of DOM Elements, where a full-blown template isn't
    1188	    // needed, use **make** to manufacture elements, one at a time.
    1189	    //
    1190	    //     var el = this.make('li', {'class': 'row'}, this.model.escape('title'));
    1191	    //
    1192	    make: function(tagName, attributes, content) {
    1193	      var el = document.createElement(tagName);
    1194	      if (attributes) $(el).attr(attributes);
    1195	      if (content) $(el).html(content);
    1196	      return el;
    1197	    },
    1198	
    1199	    // Change the view's element (`this.el` property), including event
    1200	    // re-delegation.
    1201	    setElement: function(element, delegate) {
    1202	      if (this.$el) this.undelegateEvents();
    1203	      this.$el = (element instanceof $) ? element : $(element);
    1204	      this.el = this.$el[0];
    1205	      if (delegate !== false) this.delegateEvents();
    1206	      return this;
    1207	    },
    1208	
    1209	    // Set callbacks, where `this.events` is a hash of
    1210	    //
    1211	    // *{"event selector": "callback"}*
    1212	    //
    1213	    //     {
    1214	    //       'mousedown .title':  'edit',
    1215	    //       'click .button':     'save'
    1216	    //       'click .open':       function(e) { ... }
    1217	    //     }
    1218	    //
    1219	    // pairs. Callbacks will be bound to the view, with `this` set properly.
    1220	    // Uses event delegation for efficiency.
    1221	    // Omitting the selector binds the event to `this.el`.
    1222	    // This only works for delegate-able events: not `focus`, `blur`, and
    1223	    // not `change`, `submit`, and `reset` in Internet Explorer.
    1224	    delegateEvents: function(events) {
    1225	      if (!(events || (events = getValue(this, 'events')))) return;
    1226	      this.undelegateEvents();
    1227	      for (var key in events) {
    1228	        var method = events[key];
    1229	        if (!_.isFunction(method)) method = this[events[key]];
    1230	        if (!method) throw new Error('Method "' + events[key] + '" does not exist');
    1231	        var match = key.match(delegateEventSplitter);
    1232	        var eventName = match[1], selector = match[2];
    1233	        method = _.bind(method, this);
    1234	        eventName += '.delegateEvents' + this.cid;
    1235	        if (selector === '') {
    1236	          this.$el.bind(eventName, method);
    1237	        } else {
    1238	          this.$el.delegate(selector, eventName, method);
    1239	        }
    1240	      }
    1241	    },
    1242	
    1243	    // Clears all callbacks previously bound to the view with `delegateEvents`.
    1244	    // You usually don't need to use this, but may wish to if you have multiple
    1245	    // Backbone views attached to the same DOM element.
    1246	    undelegateEvents: function() {
    1247	      this.$el.unbind('.delegateEvents' + this.cid);
    1248	    },
    1249	
    1250	    // Performs the initial configuration of a View with a set of options.
    1251	    // Keys with special meaning *(model, collection, id, className)*, are
    1252	    // attached directly to the view.
    1253	    _configure: function(options) {
    1254	      if (this.options) options = _.extend({}, this.options, options);
    1255	      for (var i = 0, l = viewOptions.length; i < l; i++) {
    1256	        var attr = viewOptions[i];
    1257	        if (options[attr]) this[attr] = options[attr];
    1258	      }
    1259	      this.options = options;
    1260	    },
    1261	
    1262	    // Ensure that the View has a DOM element to render into.
    1263	    // If `this.el` is a string, pass it through `$()`, take the first
    1264	    // matching element, and re-assign it to `el`. Otherwise, create
    1265	    // an element from the `id`, `className` and `tagName` properties.
    1266	    _ensureElement: function() {
    1267	      if (!this.el) {
    1268	        var attrs = getValue(this, 'attributes') || {};
    1269	        if (this.id) attrs.id = this.id;
    1270	        if (this.className) attrs['class'] = this.className;
    1271	        this.setElement(this.make(this.tagName, attrs), false);
    1272	      } else {
    1273	        this.setElement(this.el, false);
    1274	      }
    1275	    }
    1276	
    1277	  });
    1278	
    1279	  // The self-propagating extend function that Backbone classes use.
    1280	  var extend = function (protoProps, classProps) {
    1281	    var child = inherits(this, protoProps, classProps);
    1282	    child.extend = this.extend;
    1283	    return child;
    1284	  };
    1285	
    1286	  // Set up inheritance for the model, collection, and view.
    1287	  Model.extend = Collection.extend = Router.extend = View.extend = extend;
    1288	
    1289	  // Backbone.sync
    1290	  // -------------
    1291	
    1292	  // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
    1293	  var methodMap = {
    1294	    'create': 'POST',
    1295	    'update': 'PUT',
    1296	    'delete': 'DELETE',
    1297	    'read':   'GET'
    1298	  };
    1299	
    1300	  // Override this function to change the manner in which Backbone persists
    1301	  // models to the server. You will be passed the type of request, and the
    1302	  // model in question. By default, makes a RESTful Ajax request
    1303	  // to the model's `url()`. Some possible customizations could be:
    1304	  //
    1305	  // * Use `setTimeout` to batch rapid-fire updates into a single request.
    1306	  // * Send up the models as XML instead of JSON.
    1307	  // * Persist models via WebSockets instead of Ajax.
    1308	  //
    1309	  // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
    1310	  // as `POST`, with a `_method` parameter containing the true HTTP method,
    1311	  // as well as all requests with the body as `application/x-www-form-urlencoded`
    1312	  // instead of `application/json` with the model in a param named `model`.
    1313	  // Useful when interfacing with server-side languages like **PHP** that make
    1314	  // it difficult to read the body of `PUT` requests.
    1315	  Backbone.sync = function(method, model, options) {
    1316	    var type = methodMap[method];
    1317	
    1318	    // Default options, unless specified.
    1319	    options || (options = {});
    1320	
    1321	    // Default JSON-request options.
    1322	    var params = {type: type, dataType: 'json'};
    1323	
    1324	    // Ensure that we have a URL.
    1325	    if (!options.url) {
    1326	      params.url = getValue(model, 'url') || urlError();
    1327	    }
    1328	
    1329	    // Ensure that we have the appropriate request data.
    1330	    if (!options.data && model && (method == 'create' || method == 'update')) {
    1331	      params.contentType = 'application/json';
    1332	      params.data = JSON.stringify(model.toJSON());
    1333	    }
    1334	
    1335	    // For older servers, emulate JSON by encoding the request into an HTML-form.
    1336	    if (Backbone.emulateJSON) {
    1337	      params.contentType = 'application/x-www-form-urlencoded';
    1338	      params.data = params.data ? {model: params.data} : {};
    1339	    }
    1340	
    1341	    // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
    1342	    // And an `X-HTTP-Method-Override` header.
    1343	    if (Backbone.emulateHTTP) {
    1344	      if (type === 'PUT' || type === 'DELETE') {
    1345	        if (Backbone.emulateJSON) params.data._method = type;
    1346	        params.type = 'POST';
    1347	        params.beforeSend = function(xhr) {
    1348	          xhr.setRequestHeader('X-HTTP-Method-Override', type);
    1349	        };
    1350	      }
    1351	    }
    1352	
    1353	    // Don't process data on a non-GET request.
    1354	    if (params.type !== 'GET' && !Backbone.emulateJSON) {
    1355	      params.processData = false;
    1356	    }
    1357	
    1358	    // Make the request, allowing the user to override any Ajax options.
    1359	    return $.ajax(_.extend(params, options));
    1360	  };
    1361	
    1362	  // Wrap an optional error callback with a fallback error event.
    1363	  Backbone.wrapError = function(onError, originalModel, options) {
    1364	    return function(model, resp) {
    1365	      resp = model === originalModel ? resp : model;
    1366	      if (onError) {
    1367	        onError(originalModel, resp, options);
    1368	      } else {
    1369	        originalModel.trigger('error', originalModel, resp, options);
    1370	      }
    1371	    };
    1372	  };
    1373	
    1374	  // Helpers
    1375	  // -------
    1376	
    1377	  // Shared empty constructor function to aid in prototype-chain creation.
    1378	  var ctor = function(){};
    1379	
    1380	  // Helper function to correctly set up the prototype chain, for subclasses.
    1381	  // Similar to `goog.inherits`, but uses a hash of prototype properties and
    1382	  // class properties to be extended.
    1383	  var inherits = function(parent, protoProps, staticProps) {
    1384	    var child;
    1385	
    1386	    // The constructor function for the new subclass is either defined by you
    1387	    // (the "constructor" property in your `extend` definition), or defaulted
    1388	    // by us to simply call the parent's constructor.
    1389	    if (protoProps && protoProps.hasOwnProperty('constructor')) {
    1390	      child = protoProps.constructor;
    1391	    } else {
    1392	      child = function(){ parent.apply(this, arguments); };
    1393	    }
    1394	
    1395	    // Inherit class (static) properties from parent.
    1396	    _.extend(child, parent);
    1397	
    1398	    // Set the prototype chain to inherit from `parent`, without calling
    1399	    // `parent`'s constructor function.
    1400	    ctor.prototype = parent.prototype;
    1401	    child.prototype = new ctor();
    1402	
    1403	    // Add prototype properties (instance properties) to the subclass,
    1404	    // if supplied.
    1405	    if (protoProps) _.extend(child.prototype, protoProps);
    1406	
    1407	    // Add static properties to the constructor function, if supplied.
    1408	    if (staticProps) _.extend(child, staticProps);
    1409	
    1410	    // Correctly set child's `prototype.constructor`.
    1411	    child.prototype.constructor = child;
    1412	
    1413	    // Set a convenience property in case the parent's prototype is needed later.
    1414	    child.__super__ = parent.prototype;
    1415	
    1416	    return child;
    1417	  };
    1418	
    1419	  // Helper function to get a value from a Backbone object as a property
    1420	  // or as a function.
    1421	  var getValue = function(object, prop) {
    1422	    if (!(object && object[prop])) return null;
    1423	    return _.isFunction(object[prop]) ? object[prop]() : object[prop];
    1424	  };
    1425	
    1426	  // Throw an error when a URL is needed, and none is supplied.
    1427	  var urlError = function() {
    1428	    throw new Error('A "url" property or function must be specified');
    1429	  };
    1430	
    1431	}).call(this);