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 +4 -4
- data/app/assets/javascripts/admin/lib/backbone.js +125 -102
- data/app/assets/javascripts/admin/lib/jquery.chosen.js +31 -20
- data/app/assets/javascripts/admin/lib/jquery.js +4225 -4502
- data/app/assets/javascripts/admin/lib/moment.js +10748 -1989
- data/app/assets/javascripts/admin/lib/underscore.js +14 -17
- data/lib/generators/tolaria/install/templates/administrators_migration.rb +1 -5
- data/lib/tolaria.rb +0 -1
- data/lib/tolaria/version.rb +1 -1
- data/test/demo/db/migrate/20150601202901_create_administrators.rb +2 -6
- data/test/demo/db/migrate/20150603204006_add_testing_models.rb +1 -1
- data/test/demo/db/migrate/20150609232013_create_footnotes.rb +1 -1
- data/test/demo/db/migrate/20150610135235_create_additional_demo_objects.rb +1 -1
- data/tolaria.gemspec +1 -1
- metadata +4 -5
- data/lib/tolaria/ransack.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f72ecaf99c8d0f57914a8fcd621ca087c14406f0
|
4
|
+
data.tar.gz: 681f402268c1440a79b1d8bb19a4c6c28c597194
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7cc57c634c9d114fe3d8fcc12a1c9740051248a51e09efd41b09d628f2cb903da3d7ca40a54d96cc759eae16deb19b84d3aa0c10ce76eec906742904f515136b
|
7
|
+
data.tar.gz: 88de63e2ed3b799fdbf9dca3b415a0b812c98ac33eda8d3c895169b05bd05d7f7e107ffbb9840beafb409a2c937024c7cd7035683dd02ad6ae932ed9cc869e95
|
@@ -1,36 +1,33 @@
|
|
1
|
-
// Backbone 1.
|
1
|
+
// Backbone 1.3.3
|
2
2
|
// https://github.com/jashkenas/backbone
|
3
3
|
//
|
4
|
-
// Copyright
|
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
|
-
//
|
9
|
-
//
|
10
|
-
//
|
11
|
-
//
|
12
|
-
//
|
13
|
-
//
|
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
|
-
//
|
22
|
-
//
|
23
|
-
//
|
24
|
-
//
|
25
|
-
//
|
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
|
33
|
-
(typeof global == 'object' && 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.
|
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
|
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
|
-
|
190
|
-
|
191
|
-
|
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 =
|
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({
|
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 =
|
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
|
-
|
243
|
-
|
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 =
|
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
|
-
|
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 =
|
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
|
-
|
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 =
|
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 =
|
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,
|
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
|
-
|
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
|
-
|
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({}, _.
|
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 = {
|
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
|
-
|
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] :
|
829
|
+
models = singular ? [models] : models.slice();
|
831
830
|
var removed = this._removeModels(models, options);
|
832
|
-
if (!options.silent && removed)
|
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 = _.
|
844
|
-
if (options.parse && !this._isModel(models))
|
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 &&
|
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 (
|
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
|
914
|
-
return
|
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
|
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
|
-
|
990
|
-
|
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
|
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(
|
1066
|
-
if (wait) collection.add(
|
1067
|
-
if (success) success.call(callbackOpts.context,
|
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
|
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
|
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
|
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 (
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
if (prevId
|
1172
|
-
|
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 = {
|
1184
|
-
foldl:
|
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':
|
1469
|
+
'patch': 'PATCH',
|
1441
1470
|
'delete': 'DELETE',
|
1442
|
-
'read':
|
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
|
1600
|
-
return
|
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
|
1673
|
-
this.location.replace(
|
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
|
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
|
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
|
1826
|
+
var rootPath = this.root;
|
1798
1827
|
if (fragment === '' || fragment.charAt(0) === '?') {
|
1799
|
-
|
1828
|
+
rootPath = rootPath.slice(0, -1) || '/';
|
1800
1829
|
}
|
1801
|
-
var url =
|
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 &&
|
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
|
-
|
1881
|
-
|
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
|
+
});
|