tolaria 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4450bf6abdde6f868ccb6b701f304cf9aceaf682
4
- data.tar.gz: bc67b331bb75c30b437cfc5af44fc0e3bc976174
3
+ metadata.gz: f72ecaf99c8d0f57914a8fcd621ca087c14406f0
4
+ data.tar.gz: 681f402268c1440a79b1d8bb19a4c6c28c597194
5
5
  SHA512:
6
- metadata.gz: 91095ce63931a301e5cd84e230414bc497d762d049efe3f13907f17f59f6a39cfa87d9c6af762ff6c8150c32360a64bb4dd6551e7686f375d77ea1caa91a12a4
7
- data.tar.gz: 83bbbd13e2765cbfadf037114f5b09aaf2364ded8ebcdda56be987effb1eceffe02b9ae3649e7edbeb402f03357834270e7cf21128655d346f6b22f286d334e1
6
+ metadata.gz: 7cc57c634c9d114fe3d8fcc12a1c9740051248a51e09efd41b09d628f2cb903da3d7ca40a54d96cc759eae16deb19b84d3aa0c10ce76eec906742904f515136b
7
+ data.tar.gz: 88de63e2ed3b799fdbf9dca3b415a0b812c98ac33eda8d3c895169b05bd05d7f7e107ffbb9840beafb409a2c937024c7cd7035683dd02ad6ae932ed9cc869e95
@@ -1,36 +1,33 @@
1
- // Backbone 1.2.3
1
+ // Backbone 1.3.3
2
2
  // https://github.com/jashkenas/backbone
3
3
  //
4
- // Copyright (c) Jeremy Ashkenas, DocumentCloud, and
5
- // Investigative Reporters & Editors
4
+ // Copyright © Jeremy Ashkenas, DocumentCloud, and Investigative Reporters & Editors
6
5
  //
7
- // Permission is hereby granted, free of charge, to any person
8
- // obtaining a copy of this software and associated documentation
9
- // files (the "Software"), to deal in the Software without
10
- // restriction, including without limitation the rights to use,
11
- // copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- // copies of the Software, and to permit persons to whom the
13
- // Software is furnished to do so, subject to the following
14
- // conditions:
6
+ // Permission is hereby granted, free of charge, to any person obtaining
7
+ // a copy of this software and associated documentation files
8
+ // (the "Software"), to deal in the Software without restriction,
9
+ // including without limitation the rights to use, copy, modify, merge,
10
+ // publish, distribute, sublicense, and/or sell copies of the Software,
11
+ // and to permit persons to whom the Software is furnished to do so,
12
+ // subject to the following conditions:
15
13
  //
16
14
  // The above copyright notice and this permission notice shall be
17
15
  // included in all copies or substantial portions of the Software.
18
16
  //
19
17
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21
- // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23
- // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24
- // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26
- // OTHER DEALINGS IN THE SOFTWARE.
18
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
21
+ // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
23
+ // THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
24
 
28
25
  (function(factory) {
29
26
 
30
27
  // Establish the root object, `window` (`self`) in the browser, or `global` on the server.
31
28
  // We use `self` instead of `window` for `WebWorker` support.
32
- var root = (typeof self == 'object' && self.self == self && self) ||
33
- (typeof global == 'object' && global.global == global && global);
29
+ var root = (typeof self == 'object' && self.self === self && self) ||
30
+ (typeof global == 'object' && global.global === global && global);
34
31
 
35
32
  // Set up Backbone appropriately for the environment. Start with AMD.
36
33
  if (typeof define === 'function' && define.amd) {
@@ -43,7 +40,7 @@
43
40
  // Next for Node.js or CommonJS. jQuery may not be needed as a module.
44
41
  } else if (typeof exports !== 'undefined') {
45
42
  var _ = require('underscore'), $;
46
- try { $ = require('jquery'); } catch(e) {}
43
+ try { $ = require('jquery'); } catch (e) {}
47
44
  factory(root, exports, _, $);
48
45
 
49
46
  // Finally, as a browser global.
@@ -51,7 +48,7 @@
51
48
  root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
52
49
  }
53
50
 
54
- }(function(root, Backbone, _, $) {
51
+ })(function(root, Backbone, _, $) {
55
52
 
56
53
  // Initial Setup
57
54
  // -------------
@@ -64,7 +61,7 @@
64
61
  var slice = Array.prototype.slice;
65
62
 
66
63
  // Current version of the library. Keep in sync with `package.json`.
67
- Backbone.VERSION = '1.2.3';
64
+ Backbone.VERSION = '1.3.3';
68
65
 
69
66
  // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
70
67
  // the `$` variable.
@@ -166,7 +163,7 @@
166
163
  events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
167
164
  }
168
165
  } else if (name && eventSplitter.test(name)) {
169
- // Handle space separated event names by delegating them individually.
166
+ // Handle space-separated event names by delegating them individually.
170
167
  for (names = name.split(eventSplitter); i < names.length; i++) {
171
168
  events = iteratee(events, names[i], callback, opts);
172
169
  }
@@ -186,9 +183,9 @@
186
183
  // Guard the `listening` argument from the public API.
187
184
  var internalOn = function(obj, name, callback, context, listening) {
188
185
  obj._events = eventsApi(onApi, obj._events || {}, name, callback, {
189
- context: context,
190
- ctx: obj,
191
- listening: listening
186
+ context: context,
187
+ ctx: obj,
188
+ listening: listening
192
189
  });
193
190
 
194
191
  if (listening) {
@@ -202,7 +199,7 @@
202
199
  // Inversion-of-control versions of `on`. Tell *this* object to listen to
203
200
  // an event in another object... keeping track of what it's listening to
204
201
  // for easier unbinding later.
205
- Events.listenTo = function(obj, name, callback) {
202
+ Events.listenTo = function(obj, name, callback) {
206
203
  if (!obj) return this;
207
204
  var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
208
205
  var listeningTo = this._listeningTo || (this._listeningTo = {});
@@ -227,7 +224,7 @@
227
224
  var context = options.context, ctx = options.ctx, listening = options.listening;
228
225
  if (listening) listening.count++;
229
226
 
230
- handlers.push({ callback: callback, context: context, ctx: context || ctx, listening: listening });
227
+ handlers.push({callback: callback, context: context, ctx: context || ctx, listening: listening});
231
228
  }
232
229
  return events;
233
230
  };
@@ -236,18 +233,18 @@
236
233
  // callbacks with that function. If `callback` is null, removes all
237
234
  // callbacks for the event. If `name` is null, removes all bound
238
235
  // callbacks for all events.
239
- Events.off = function(name, callback, context) {
236
+ Events.off = function(name, callback, context) {
240
237
  if (!this._events) return this;
241
238
  this._events = eventsApi(offApi, this._events, name, callback, {
242
- context: context,
243
- listeners: this._listeners
239
+ context: context,
240
+ listeners: this._listeners
244
241
  });
245
242
  return this;
246
243
  };
247
244
 
248
245
  // Tell this object to stop listening to either specific events ... or
249
246
  // to every object it's currently listening to.
250
- Events.stopListening = function(obj, name, callback) {
247
+ Events.stopListening = function(obj, name, callback) {
251
248
  var listeningTo = this._listeningTo;
252
249
  if (!listeningTo) return this;
253
250
 
@@ -262,7 +259,6 @@
262
259
 
263
260
  listening.obj.off(name, callback, this);
264
261
  }
265
- if (_.isEmpty(listeningTo)) this._listeningTo = void 0;
266
262
 
267
263
  return this;
268
264
  };
@@ -319,21 +315,22 @@
319
315
  delete events[name];
320
316
  }
321
317
  }
322
- if (_.size(events)) return events;
318
+ return events;
323
319
  };
324
320
 
325
321
  // Bind an event to only be triggered a single time. After the first time
326
322
  // the callback is invoked, its listener will be removed. If multiple events
327
323
  // are passed in using the space-separated syntax, the handler will fire
328
324
  // once for each event, not once for a combination of all events.
329
- Events.once = function(name, callback, context) {
325
+ Events.once = function(name, callback, context) {
330
326
  // Map the event into a `{event: once}` object.
331
327
  var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this));
332
- return this.on(events, void 0, context);
328
+ if (typeof name === 'string' && context == null) callback = void 0;
329
+ return this.on(events, callback, context);
333
330
  };
334
331
 
335
332
  // Inversion-of-control versions of `once`.
336
- Events.listenToOnce = function(obj, name, callback) {
333
+ Events.listenToOnce = function(obj, name, callback) {
337
334
  // Map the event into a `{event: once}` object.
338
335
  var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj));
339
336
  return this.listenTo(obj, events);
@@ -356,7 +353,7 @@
356
353
  // passed the same arguments as `trigger` is, apart from the event name
357
354
  // (unless you're listening on `"all"`, which will cause your callback to
358
355
  // receive the true name of the event as the first argument).
359
- Events.trigger = function(name) {
356
+ Events.trigger = function(name) {
360
357
  if (!this._events) return this;
361
358
 
362
359
  var length = Math.max(0, arguments.length - 1);
@@ -368,7 +365,7 @@
368
365
  };
369
366
 
370
367
  // Handles triggering the appropriate event callbacks.
371
- var triggerApi = function(objEvents, name, cb, args) {
368
+ var triggerApi = function(objEvents, name, callback, args) {
372
369
  if (objEvents) {
373
370
  var events = objEvents[name];
374
371
  var allEvents = objEvents.all;
@@ -418,7 +415,8 @@
418
415
  this.attributes = {};
419
416
  if (options.collection) this.collection = options.collection;
420
417
  if (options.parse) attrs = this.parse(attrs, options) || {};
421
- attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
418
+ var defaults = _.result(this, 'defaults');
419
+ attrs = _.defaults(_.extend({}, defaults, attrs), defaults);
422
420
  this.set(attrs, options);
423
421
  this.changed = {};
424
422
  this.initialize.apply(this, arguments);
@@ -526,7 +524,7 @@
526
524
  }
527
525
 
528
526
  // Update the `id`.
529
- this.id = this.get(this.idAttribute);
527
+ if (this.idAttribute in attrs) this.id = this.get(this.idAttribute);
530
528
 
531
529
  // Trigger all relevant attribute changes.
532
530
  if (!silent) {
@@ -639,8 +637,8 @@
639
637
  // the model will be valid when the attributes, if any, are set.
640
638
  if (attrs && !wait) {
641
639
  if (!this.set(attrs, options)) return false;
642
- } else {
643
- if (!this._validate(attrs, options)) return false;
640
+ } else if (!this._validate(attrs, options)) {
641
+ return false;
644
642
  }
645
643
 
646
644
  // After a successful server-side save, the client is (optionally)
@@ -734,7 +732,7 @@
734
732
 
735
733
  // Check if the model is currently in a valid state.
736
734
  isValid: function(options) {
737
- return this._validate({}, _.defaults({validate: true}, options));
735
+ return this._validate({}, _.extend({}, options, {validate: true}));
738
736
  },
739
737
 
740
738
  // Run validation against the next complete set of model attributes,
@@ -752,8 +750,8 @@
752
750
 
753
751
  // Underscore methods that we want to implement on the Model, mapped to the
754
752
  // number of arguments they take.
755
- var modelMethods = { keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
756
- omit: 0, chain: 1, isEmpty: 1 };
753
+ var modelMethods = {keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
754
+ omit: 0, chain: 1, isEmpty: 1};
757
755
 
758
756
  // Mix in each Underscore method as a proxy to `Model#attributes`.
759
757
  addUnderscoreMethods(Model, modelMethods, 'attributes');
@@ -789,7 +787,8 @@
789
787
  at = Math.min(Math.max(at, 0), array.length);
790
788
  var tail = Array(array.length - at);
791
789
  var length = insert.length;
792
- for (var i = 0; i < tail.length; i++) tail[i] = array[i + at];
790
+ var i;
791
+ for (i = 0; i < tail.length; i++) tail[i] = array[i + at];
793
792
  for (i = 0; i < length; i++) array[i + at] = insert[i];
794
793
  for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i];
795
794
  };
@@ -827,9 +826,12 @@
827
826
  remove: function(models, options) {
828
827
  options = _.extend({}, options);
829
828
  var singular = !_.isArray(models);
830
- models = singular ? [models] : _.clone(models);
829
+ models = singular ? [models] : models.slice();
831
830
  var removed = this._removeModels(models, options);
832
- if (!options.silent && removed) this.trigger('update', this, options);
831
+ if (!options.silent && removed.length) {
832
+ options.changes = {added: [], merged: [], removed: removed};
833
+ this.trigger('update', this, options);
834
+ }
833
835
  return singular ? removed[0] : removed;
834
836
  },
835
837
 
@@ -840,18 +842,22 @@
840
842
  set: function(models, options) {
841
843
  if (models == null) return;
842
844
 
843
- options = _.defaults({}, options, setOptions);
844
- if (options.parse && !this._isModel(models)) models = this.parse(models, options);
845
+ options = _.extend({}, setOptions, options);
846
+ if (options.parse && !this._isModel(models)) {
847
+ models = this.parse(models, options) || [];
848
+ }
845
849
 
846
850
  var singular = !_.isArray(models);
847
851
  models = singular ? [models] : models.slice();
848
852
 
849
853
  var at = options.at;
850
854
  if (at != null) at = +at;
855
+ if (at > this.length) at = this.length;
851
856
  if (at < 0) at += this.length + 1;
852
857
 
853
858
  var set = [];
854
859
  var toAdd = [];
860
+ var toMerge = [];
855
861
  var toRemove = [];
856
862
  var modelMap = {};
857
863
 
@@ -860,13 +866,13 @@
860
866
  var remove = options.remove;
861
867
 
862
868
  var sort = false;
863
- var sortable = this.comparator && (at == null) && options.sort !== false;
869
+ var sortable = this.comparator && at == null && options.sort !== false;
864
870
  var sortAttr = _.isString(this.comparator) ? this.comparator : null;
865
871
 
866
872
  // Turn bare objects into model references, and prevent invalid models
867
873
  // from being added.
868
- var model;
869
- for (var i = 0; i < models.length; i++) {
874
+ var model, i;
875
+ for (i = 0; i < models.length; i++) {
870
876
  model = models[i];
871
877
 
872
878
  // If a duplicate is found, prevent it from being added and
@@ -877,6 +883,7 @@
877
883
  var attrs = this._isModel(model) ? model.attributes : model;
878
884
  if (options.parse) attrs = existing.parse(attrs, options);
879
885
  existing.set(attrs, options);
886
+ toMerge.push(existing);
880
887
  if (sortable && !sort) sort = existing.hasChanged(sortAttr);
881
888
  }
882
889
  if (!modelMap[existing.cid]) {
@@ -910,8 +917,8 @@
910
917
  var orderChanged = false;
911
918
  var replace = !sortable && add && remove;
912
919
  if (set.length && replace) {
913
- orderChanged = this.length != set.length || _.some(this.models, function(model, index) {
914
- return model !== set[index];
920
+ orderChanged = this.length !== set.length || _.some(this.models, function(m, index) {
921
+ return m !== set[index];
915
922
  });
916
923
  this.models.length = 0;
917
924
  splice(this.models, set, 0);
@@ -925,7 +932,7 @@
925
932
  // Silently sort the collection if appropriate.
926
933
  if (sort) this.sort({silent: true});
927
934
 
928
- // Unless silenced, it's time to fire all appropriate add/sort events.
935
+ // Unless silenced, it's time to fire all appropriate add/sort/update events.
929
936
  if (!options.silent) {
930
937
  for (i = 0; i < toAdd.length; i++) {
931
938
  if (at != null) options.index = at + i;
@@ -933,7 +940,14 @@
933
940
  model.trigger('add', model, this, options);
934
941
  }
935
942
  if (sort || orderChanged) this.trigger('sort', this, options);
936
- if (toAdd.length || toRemove.length) this.trigger('update', this, options);
943
+ if (toAdd.length || toRemove.length || toMerge.length) {
944
+ options.changes = {
945
+ added: toAdd,
946
+ removed: toRemove,
947
+ merged: toMerge
948
+ };
949
+ this.trigger('update', this, options);
950
+ }
937
951
  }
938
952
 
939
953
  // Return the added (or merged) model (or models).
@@ -983,11 +997,18 @@
983
997
  return slice.apply(this.models, arguments);
984
998
  },
985
999
 
986
- // Get a model from the set by id.
1000
+ // Get a model from the set by id, cid, model object with id or cid
1001
+ // properties, or an attributes object that is transformed through modelId.
987
1002
  get: function(obj) {
988
1003
  if (obj == null) return void 0;
989
- var id = this.modelId(this._isModel(obj) ? obj.attributes : obj);
990
- return this._byId[obj] || this._byId[id] || this._byId[obj.cid];
1004
+ return this._byId[obj] ||
1005
+ this._byId[this.modelId(obj.attributes || obj)] ||
1006
+ obj.cid && this._byId[obj.cid];
1007
+ },
1008
+
1009
+ // Returns `true` if the model is in the collection.
1010
+ has: function(obj) {
1011
+ return this.get(obj) != null;
991
1012
  },
992
1013
 
993
1014
  // Get the model at the given index.
@@ -1031,7 +1052,7 @@
1031
1052
 
1032
1053
  // Pluck an attribute from each model in the collection.
1033
1054
  pluck: function(attr) {
1034
- return _.invoke(this.models, 'get', attr);
1055
+ return this.map(attr + '');
1035
1056
  },
1036
1057
 
1037
1058
  // Fetch the default set of models for this collection, resetting the
@@ -1062,9 +1083,9 @@
1062
1083
  if (!wait) this.add(model, options);
1063
1084
  var collection = this;
1064
1085
  var success = options.success;
1065
- options.success = function(model, resp, callbackOpts) {
1066
- if (wait) collection.add(model, callbackOpts);
1067
- if (success) success.call(callbackOpts.context, model, resp, callbackOpts);
1086
+ options.success = function(m, resp, callbackOpts) {
1087
+ if (wait) collection.add(m, callbackOpts);
1088
+ if (success) success.call(callbackOpts.context, m, resp, callbackOpts);
1068
1089
  };
1069
1090
  model.save(null, options);
1070
1091
  return model;
@@ -1085,7 +1106,7 @@
1085
1106
  },
1086
1107
 
1087
1108
  // Define how to uniquely identify models in the collection.
1088
- modelId: function (attrs) {
1109
+ modelId: function(attrs) {
1089
1110
  return attrs[this.model.prototype.idAttribute || 'id'];
1090
1111
  },
1091
1112
 
@@ -1123,6 +1144,12 @@
1123
1144
  this.models.splice(index, 1);
1124
1145
  this.length--;
1125
1146
 
1147
+ // Remove references before triggering 'remove' event to prevent an
1148
+ // infinite loop. #3693
1149
+ delete this._byId[model.cid];
1150
+ var id = this.modelId(model.attributes);
1151
+ if (id != null) delete this._byId[id];
1152
+
1126
1153
  if (!options.silent) {
1127
1154
  options.index = index;
1128
1155
  model.trigger('remove', model, this, options);
@@ -1131,12 +1158,12 @@
1131
1158
  removed.push(model);
1132
1159
  this._removeReference(model, options);
1133
1160
  }
1134
- return removed.length ? removed : false;
1161
+ return removed;
1135
1162
  },
1136
1163
 
1137
1164
  // Method for checking whether an object should be considered a model for
1138
1165
  // the purposes of adding to the collection.
1139
- _isModel: function (model) {
1166
+ _isModel: function(model) {
1140
1167
  return model instanceof Model;
1141
1168
  },
1142
1169
 
@@ -1162,14 +1189,16 @@
1162
1189
  // events simply proxy through. "add" and "remove" events that originate
1163
1190
  // in other collections are ignored.
1164
1191
  _onModelEvent: function(event, model, collection, options) {
1165
- if ((event === 'add' || event === 'remove') && collection !== this) return;
1166
- if (event === 'destroy') this.remove(model, options);
1167
- if (event === 'change') {
1168
- var prevId = this.modelId(model.previousAttributes());
1169
- var id = this.modelId(model.attributes);
1170
- if (prevId !== id) {
1171
- if (prevId != null) delete this._byId[prevId];
1172
- if (id != null) this._byId[id] = model;
1192
+ if (model) {
1193
+ if ((event === 'add' || event === 'remove') && collection !== this) return;
1194
+ if (event === 'destroy') this.remove(model, options);
1195
+ if (event === 'change') {
1196
+ var prevId = this.modelId(model.previousAttributes());
1197
+ var id = this.modelId(model.attributes);
1198
+ if (prevId !== id) {
1199
+ if (prevId != null) delete this._byId[prevId];
1200
+ if (id != null) this._byId[id] = model;
1201
+ }
1173
1202
  }
1174
1203
  }
1175
1204
  this.trigger.apply(this, arguments);
@@ -1180,14 +1209,14 @@
1180
1209
  // Underscore methods that we want to implement on the Collection.
1181
1210
  // 90% of the core usefulness of Backbone Collections is actually implemented
1182
1211
  // right here:
1183
- var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4,
1184
- foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3,
1212
+ var collectionMethods = {forEach: 3, each: 3, map: 3, collect: 3, reduce: 0,
1213
+ foldl: 0, inject: 0, reduceRight: 0, foldr: 0, find: 3, detect: 3, filter: 3,
1185
1214
  select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3,
1186
1215
  contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3,
1187
1216
  head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3,
1188
1217
  without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3,
1189
1218
  isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3,
1190
- sortBy: 3, indexBy: 3};
1219
+ sortBy: 3, indexBy: 3, findIndex: 3, findLastIndex: 3};
1191
1220
 
1192
1221
  // Mix in each Underscore method as a proxy to `Collection#models`.
1193
1222
  addUnderscoreMethods(Collection, collectionMethods, 'models');
@@ -1437,9 +1466,9 @@
1437
1466
  var methodMap = {
1438
1467
  'create': 'POST',
1439
1468
  'update': 'PUT',
1440
- 'patch': 'PATCH',
1469
+ 'patch': 'PATCH',
1441
1470
  'delete': 'DELETE',
1442
- 'read': 'GET'
1471
+ 'read': 'GET'
1443
1472
  };
1444
1473
 
1445
1474
  // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
@@ -1596,8 +1625,8 @@
1596
1625
  // Does the pathname match the root?
1597
1626
  matchRoot: function() {
1598
1627
  var path = this.decodeFragment(this.location.pathname);
1599
- var root = path.slice(0, this.root.length - 1) + '/';
1600
- return root === this.root;
1628
+ var rootPath = path.slice(0, this.root.length - 1) + '/';
1629
+ return rootPath === this.root;
1601
1630
  },
1602
1631
 
1603
1632
  // Unicode characters in `location.pathname` are percent encoded so they're
@@ -1669,8 +1698,8 @@
1669
1698
  // If we've started off with a route from a `pushState`-enabled
1670
1699
  // browser, but we're currently in a browser that doesn't support it...
1671
1700
  if (!this._hasPushState && !this.atRoot()) {
1672
- var root = this.root.slice(0, -1) || '/';
1673
- this.location.replace(root + '#' + this.getPath());
1701
+ var rootPath = this.root.slice(0, -1) || '/';
1702
+ this.location.replace(rootPath + '#' + this.getPath());
1674
1703
  // Return immediately as browser will do redirect to new url
1675
1704
  return true;
1676
1705
 
@@ -1699,7 +1728,7 @@
1699
1728
  }
1700
1729
 
1701
1730
  // Add a cross-platform `addEventListener` shim for older browsers.
1702
- var addEventListener = window.addEventListener || function (eventName, listener) {
1731
+ var addEventListener = window.addEventListener || function(eventName, listener) {
1703
1732
  return attachEvent('on' + eventName, listener);
1704
1733
  };
1705
1734
 
@@ -1720,7 +1749,7 @@
1720
1749
  // but possibly useful for unit testing Routers.
1721
1750
  stop: function() {
1722
1751
  // Add a cross-platform `removeEventListener` shim for older browsers.
1723
- var removeEventListener = window.removeEventListener || function (eventName, listener) {
1752
+ var removeEventListener = window.removeEventListener || function(eventName, listener) {
1724
1753
  return detachEvent('on' + eventName, listener);
1725
1754
  };
1726
1755
 
@@ -1794,11 +1823,11 @@
1794
1823
  fragment = this.getFragment(fragment || '');
1795
1824
 
1796
1825
  // Don't include a trailing slash on the root.
1797
- var root = this.root;
1826
+ var rootPath = this.root;
1798
1827
  if (fragment === '' || fragment.charAt(0) === '?') {
1799
- root = root.slice(0, -1) || '/';
1828
+ rootPath = rootPath.slice(0, -1) || '/';
1800
1829
  }
1801
- var url = root + fragment;
1830
+ var url = rootPath + fragment;
1802
1831
 
1803
1832
  // Strip the hash and decode for matching.
1804
1833
  fragment = this.decodeFragment(fragment.replace(pathStripper, ''));
@@ -1814,7 +1843,7 @@
1814
1843
  // fragment to store history.
1815
1844
  } else if (this._wantsHashChange) {
1816
1845
  this._updateHash(this.location, fragment, options.replace);
1817
- if (this.iframe && (fragment !== this.getHash(this.iframe.contentWindow))) {
1846
+ if (this.iframe && fragment !== this.getHash(this.iframe.contentWindow)) {
1818
1847
  var iWindow = this.iframe.contentWindow;
1819
1848
 
1820
1849
  // Opening and closing the iframe tricks IE7 and earlier to push a
@@ -1876,14 +1905,9 @@
1876
1905
  _.extend(child, parent, staticProps);
1877
1906
 
1878
1907
  // Set the prototype chain to inherit from `parent`, without calling
1879
- // `parent` constructor function.
1880
- var Surrogate = function(){ this.constructor = child; };
1881
- Surrogate.prototype = parent.prototype;
1882
- child.prototype = new Surrogate;
1883
-
1884
- // Add prototype properties (instance properties) to the subclass,
1885
- // if supplied.
1886
- if (protoProps) _.extend(child.prototype, protoProps);
1908
+ // `parent`'s constructor function and add the prototype properties.
1909
+ child.prototype = _.create(parent.prototype, protoProps);
1910
+ child.prototype.constructor = child;
1887
1911
 
1888
1912
  // Set a convenience property in case the parent's prototype is needed
1889
1913
  // later.
@@ -1910,5 +1934,4 @@
1910
1934
  };
1911
1935
 
1912
1936
  return Backbone;
1913
-
1914
- }));
1937
+ });