marionette-rails 1.0.0.rc2 → 1.0.0.rc3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/vendor/assets/javascripts/backbone.marionette.js +240 -328
- metadata +1 -1
@@ -1,5 +1,5 @@
|
|
1
|
-
// Backbone.Marionette, v1.0.0-
|
2
|
-
// Copyright (c)
|
1
|
+
// Backbone.Marionette, v1.0.0-rc3
|
2
|
+
// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
|
3
3
|
// Distributed under MIT license
|
4
4
|
// http://github.com/marionettejs/backbone.marionette
|
5
5
|
|
@@ -10,9 +10,6 @@
|
|
10
10
|
*
|
11
11
|
* Includes Wreqr
|
12
12
|
* https://github.com/marionettejs/backbone.wreqr/
|
13
|
-
*
|
14
|
-
* Includes EventBinder
|
15
|
-
* https://github.com/marionettejs/backbone.eventbinder/
|
16
13
|
*/
|
17
14
|
|
18
15
|
|
@@ -210,133 +207,7 @@ Backbone.ChildViewContainer = (function(Backbone, _){
|
|
210
207
|
return Container;
|
211
208
|
})(Backbone, _);
|
212
209
|
|
213
|
-
// Backbone.
|
214
|
-
// Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
|
215
|
-
// Distributed under MIT license
|
216
|
-
// http://github.com/marionettejs/backbone.eventbinder
|
217
|
-
// EventBinder
|
218
|
-
// -----------
|
219
|
-
//
|
220
|
-
// The event binder facilitates the binding and unbinding of events
|
221
|
-
// from objects that extend `Backbone.Events`. It makes
|
222
|
-
// unbinding events, even with anonymous callback functions,
|
223
|
-
// easy.
|
224
|
-
//
|
225
|
-
// Inspired by [Johnny Oshika](http://stackoverflow.com/questions/7567404/backbone-js-repopulate-or-recreate-the-view/7607853#7607853)
|
226
|
-
|
227
|
-
Backbone.EventBinder = (function(Backbone, _){
|
228
|
-
"use strict";
|
229
|
-
|
230
|
-
// A map of objects that support binding/unbinding events.
|
231
|
-
// This allows EventBinder to support events on arbitrary
|
232
|
-
// objects with EB's consistent api.
|
233
|
-
var handlerMap = {
|
234
|
-
// 'default' type accounts for Backbone style objects extending
|
235
|
-
// Backbone.Events
|
236
|
-
"default" : {
|
237
|
-
bindTo : function (obj, eventName, callback, context) {
|
238
|
-
context = context || this;
|
239
|
-
obj.on(eventName, callback, context);
|
240
|
-
|
241
|
-
var binding = {
|
242
|
-
type : 'default',
|
243
|
-
obj: obj,
|
244
|
-
eventName: eventName,
|
245
|
-
callback: callback,
|
246
|
-
context: context
|
247
|
-
};
|
248
|
-
|
249
|
-
return binding;
|
250
|
-
},
|
251
|
-
unbindFrom : function(binding){
|
252
|
-
binding.obj.off(binding.eventName, binding.callback, binding.context);
|
253
|
-
}
|
254
|
-
},
|
255
|
-
|
256
|
-
// 'jquery' style handlers allow us to bind to jQuery
|
257
|
-
// (or compatible) objects
|
258
|
-
jquery : {
|
259
|
-
bindTo : function (obj, eventName, callback, context) {
|
260
|
-
context = context || this;
|
261
|
-
callback = _(callback).bind(context);
|
262
|
-
obj.on(eventName, callback);
|
263
|
-
|
264
|
-
var binding = {
|
265
|
-
type : 'jquery',
|
266
|
-
obj: obj,
|
267
|
-
eventName: eventName,
|
268
|
-
callback: callback,
|
269
|
-
context: context
|
270
|
-
};
|
271
|
-
|
272
|
-
return binding;
|
273
|
-
},
|
274
|
-
unbindFrom : function(binding){
|
275
|
-
binding.obj.off(binding.eventName, binding.callback);
|
276
|
-
}
|
277
|
-
}
|
278
|
-
};
|
279
|
-
|
280
|
-
// Use whatever best logic necessary to determine the type
|
281
|
-
// of the supplied object
|
282
|
-
function getHandlerForObject(obj) {
|
283
|
-
if (_.isUndefined(obj) || _.isNull(obj)) {
|
284
|
-
throw new Error("Can't bindTo undefined");
|
285
|
-
}
|
286
|
-
|
287
|
-
if (obj.jquery) { return handlerMap.jquery; }
|
288
|
-
|
289
|
-
return handlerMap["default"];
|
290
|
-
}
|
291
|
-
|
292
|
-
// Constructor function
|
293
|
-
var EventBinder = function(){
|
294
|
-
this._eventBindings = [];
|
295
|
-
};
|
296
|
-
|
297
|
-
// Copy the `extend` function used by Backbone's classes
|
298
|
-
EventBinder.extend = Backbone.View.extend;
|
299
|
-
|
300
|
-
// Extend the EventBinder with additional methods
|
301
|
-
_.extend(EventBinder.prototype, {
|
302
|
-
|
303
|
-
// Delegate to the bindTo for the appropriate type and
|
304
|
-
// store the event binding in array so it can be unbound
|
305
|
-
// easily, at a later point in time.
|
306
|
-
bindTo: function(/* args... */) {
|
307
|
-
var obj = arguments[0];
|
308
|
-
var handlers = getHandlerForObject(obj);
|
309
|
-
|
310
|
-
var args = Array.prototype.slice.apply(arguments);
|
311
|
-
var binding = handlers.bindTo.apply(this, args);
|
312
|
-
|
313
|
-
this._eventBindings.push(binding);
|
314
|
-
|
315
|
-
return binding;
|
316
|
-
},
|
317
|
-
|
318
|
-
// Unbind from a single binding object. Binding objects are
|
319
|
-
// returned from the `bindTo` method call.
|
320
|
-
unbindFrom: function(binding) {
|
321
|
-
var args = Array.prototype.slice.apply(arguments);
|
322
|
-
handlerMap[binding.type].unbindFrom.apply(this, args);
|
323
|
-
|
324
|
-
this._eventBindings = _.reject(this._eventBindings, function(bind){return bind === binding;});
|
325
|
-
},
|
326
|
-
|
327
|
-
// Unbind all of the events that we have stored.
|
328
|
-
unbindAll: function() {
|
329
|
-
// The `unbindFrom` call removes elements from the array
|
330
|
-
// while it is being iterated, so clone it first.
|
331
|
-
var bindings = _.map(this._eventBindings, _.identity);
|
332
|
-
_.each(bindings, this.unbindFrom, this);
|
333
|
-
}
|
334
|
-
});
|
335
|
-
|
336
|
-
return EventBinder;
|
337
|
-
})(Backbone, _);
|
338
|
-
|
339
|
-
// Backbone.Wreqr, v0.1.0
|
210
|
+
// Backbone.Wreqr, v0.2.0
|
340
211
|
// Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
|
341
212
|
// Distributed under MIT license
|
342
213
|
// http://github.com/marionettejs/backbone.wreqr
|
@@ -451,24 +322,43 @@ Backbone.Wreqr = (function(Backbone, Marionette, _){
|
|
451
322
|
// of an application through event-driven architecture.
|
452
323
|
|
453
324
|
Wreqr.EventAggregator = (function(Backbone, _){
|
454
|
-
"option strict";
|
455
|
-
var EA = function(){};
|
456
325
|
|
457
|
-
//
|
458
|
-
|
326
|
+
// Grab a reference to the original listenTo
|
327
|
+
var listenTo = Backbone.Events.listenTo;
|
459
328
|
|
460
|
-
//
|
461
|
-
|
329
|
+
// Create a version of listenTo that allows contexting binding
|
330
|
+
function contextBoundListenTo(obj, evtSource, events, callback, context){
|
331
|
+
context = context || obj;
|
332
|
+
return listenTo.call(obj, evtSource, events, _.bind(callback, context));
|
333
|
+
}
|
462
334
|
|
463
|
-
|
335
|
+
// Define the EventAggregator
|
336
|
+
function EventAggregator(){}
|
337
|
+
|
338
|
+
// Mix Backbone.Events in to it
|
339
|
+
_.extend(EventAggregator.prototype, Backbone.Events, {
|
340
|
+
// Override the listenTo so that we can have a version that
|
341
|
+
// correctly binds context
|
342
|
+
listenTo: function(evtSource, events, callback, context){
|
343
|
+
return contextBoundListenTo(this, evtSource, events, callback, context);
|
344
|
+
}
|
345
|
+
});
|
346
|
+
|
347
|
+
// Allow it to be extended
|
348
|
+
EventAggregator.extend = Backbone.Model.extend;
|
349
|
+
|
350
|
+
return EventAggregator;
|
464
351
|
})(Backbone, _);
|
465
352
|
|
466
353
|
|
467
354
|
return Wreqr;
|
468
355
|
})(Backbone, Backbone.Marionette, _);
|
469
356
|
|
470
|
-
|
357
|
+
var Marionette = (function(Backbone, _, $){
|
358
|
+
"use strict";
|
359
|
+
|
471
360
|
var Marionette = {};
|
361
|
+
Backbone.Marionette = Marionette;
|
472
362
|
|
473
363
|
// Helpers
|
474
364
|
// -------
|
@@ -608,44 +498,48 @@ Marionette.MonitorDOMRefresh = (function(){
|
|
608
498
|
|
609
499
|
// Export public API
|
610
500
|
return function(view){
|
611
|
-
view.
|
501
|
+
view.listenTo(view, "show", function(){
|
612
502
|
handleShow(view);
|
613
503
|
});
|
614
504
|
|
615
|
-
view.
|
505
|
+
view.listenTo(view, "render", function(){
|
616
506
|
handleRender(view);
|
617
507
|
});
|
618
508
|
};
|
619
509
|
})();
|
620
510
|
|
621
511
|
|
622
|
-
//
|
623
|
-
//
|
624
|
-
//
|
625
|
-
//
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
//
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
512
|
+
// addEventBinder
|
513
|
+
// --------------
|
514
|
+
//
|
515
|
+
// Mixes in Backbone.Events to the target object, if it is not present
|
516
|
+
// already. Also adjusts the listenTo method to accept a 4th parameter
|
517
|
+
// for the callback context.
|
518
|
+
|
519
|
+
(function(Backbone, Marionette, _){
|
520
|
+
|
521
|
+
// grab a reference to the original listenTo
|
522
|
+
var listenTo = Backbone.Events.listenTo;
|
523
|
+
|
524
|
+
// Fix the listenTo method on the target object, allowing the 4th
|
525
|
+
// context parameter to be specified
|
526
|
+
Marionette.addEventBinder = function(target){
|
527
|
+
// If the target is not already extending Backbone.Events,
|
528
|
+
// then extend that on to it first
|
529
|
+
if (!target.on && !target.off && !target.listenTo && !target.stopListening){
|
530
|
+
_.extend(target, Backbone.Events);
|
531
|
+
}
|
532
|
+
|
533
|
+
// Override the built-in listenTo method to make sure we
|
534
|
+
// account for context
|
535
|
+
target.listenTo = function(evtSource, events, callback, context){
|
536
|
+
context = context || this;
|
537
|
+
return listenTo.call(this, evtSource, events, _.bind(callback, context));
|
538
|
+
};
|
644
539
|
};
|
645
540
|
|
646
|
-
|
647
|
-
|
648
|
-
};
|
541
|
+
})(Backbone, Marionette, _);
|
542
|
+
|
649
543
|
|
650
544
|
// Event Aggregator
|
651
545
|
// ----------------
|
@@ -665,13 +559,13 @@ Marionette.EventAggregator = Backbone.Wreqr.EventAggregator.extend({
|
|
665
559
|
|
666
560
|
});
|
667
561
|
|
668
|
-
// Marionette.bindEntityEvents
|
562
|
+
// Marionette.bindEntityEvents & unbindEntityEvents
|
669
563
|
// ---------------------------
|
670
564
|
//
|
671
|
-
//
|
565
|
+
// These methods are used to bind/unbind a backbone "entity" (collection/model)
|
672
566
|
// to methods on a target object.
|
673
567
|
//
|
674
|
-
// The first paremter, `target`, must have a `
|
568
|
+
// The first paremter, `target`, must have a `listenTo` method from the
|
675
569
|
// EventBinder object.
|
676
570
|
//
|
677
571
|
// The second parameter is the entity (Backbone.Model or Backbone.Collection)
|
@@ -680,7 +574,9 @@ Marionette.EventAggregator = Backbone.Wreqr.EventAggregator.extend({
|
|
680
574
|
// The third parameter is a hash of { "event:name": "eventHandler" }
|
681
575
|
// configuration. Multiple handlers can be separated by a space. A
|
682
576
|
// function can be supplied instead of a string handler name.
|
683
|
-
|
577
|
+
|
578
|
+
(function(Marionette){
|
579
|
+
"use strict";
|
684
580
|
|
685
581
|
// Bind the event to handlers specified as a string of
|
686
582
|
// handler names on the target object
|
@@ -694,32 +590,65 @@ Marionette.bindEntityEvents = (function(){
|
|
694
590
|
throw new Error("Method '"+ methodName +"' was configured as an event handler, but does not exist.");
|
695
591
|
}
|
696
592
|
|
697
|
-
target.
|
593
|
+
target.listenTo(entity, evt, method, target);
|
698
594
|
});
|
699
595
|
}
|
700
596
|
|
701
597
|
// Bind the event to a supplied callback function
|
702
598
|
function bindToFunction(target, entity, evt, method){
|
703
|
-
target.
|
599
|
+
target.listenTo(entity, evt, method, target);
|
600
|
+
}
|
601
|
+
|
602
|
+
// Bind the event to handlers specified as a string of
|
603
|
+
// handler names on the target object
|
604
|
+
function unbindFromStrings(target, entity, evt, methods){
|
605
|
+
var methodNames = methods.split(/\s+/);
|
606
|
+
|
607
|
+
_.each(methodNames,function(methodName) {
|
608
|
+
var method = target[method];
|
609
|
+
target.stopListening(entity, evt, method, target);
|
610
|
+
});
|
611
|
+
}
|
612
|
+
|
613
|
+
// Bind the event to a supplied callback function
|
614
|
+
function unbindToFunction(target, entity, evt, method){
|
615
|
+
target.stopListening(entity, evt, method, target);
|
704
616
|
}
|
705
617
|
|
706
|
-
|
707
|
-
|
618
|
+
|
619
|
+
// generic looping function
|
620
|
+
function iterateEvents(target, entity, bindings, functionCallback, stringCallback){
|
708
621
|
if (!entity || !bindings) { return; }
|
709
622
|
|
623
|
+
// allow the bindings to be a function
|
624
|
+
if (_.isFunction(bindings)){
|
625
|
+
bindings = bindings.call(target);
|
626
|
+
}
|
627
|
+
|
628
|
+
// iterate the bindings and bind them
|
710
629
|
_.each(bindings, function(methods, evt){
|
711
630
|
|
712
631
|
// allow for a function as the handler,
|
713
632
|
// or a list of event names as a string
|
714
633
|
if (_.isFunction(methods)){
|
715
|
-
|
634
|
+
functionCallback(target, entity, evt, methods);
|
716
635
|
} else {
|
717
|
-
|
636
|
+
stringCallback(target, entity, evt, methods);
|
718
637
|
}
|
719
638
|
|
720
639
|
});
|
640
|
+
}
|
641
|
+
|
642
|
+
// Export Public API
|
643
|
+
Marionette.bindEntityEvents = function(target, entity, bindings){
|
644
|
+
iterateEvents(target, entity, bindings, bindToFunction, bindFromStrings);
|
721
645
|
};
|
722
|
-
|
646
|
+
|
647
|
+
Marionette.unbindEntityEvents = function(target, entity, bindings){
|
648
|
+
iterateEvents(target, entity, bindings, unbindToFunction, unbindFromStrings);
|
649
|
+
};
|
650
|
+
|
651
|
+
})(Marionette);
|
723
652
|
|
724
653
|
|
725
654
|
// Callbacks
|
@@ -793,7 +722,7 @@ Marionette.Controller.extend = Marionette.extend;
|
|
793
722
|
// Ensure it can trigger events with Backbone.Events
|
794
723
|
_.extend(Marionette.Controller.prototype, Backbone.Events, {
|
795
724
|
close: function(){
|
796
|
-
this.
|
725
|
+
this.stopListening();
|
797
726
|
this.triggerMethod("close");
|
798
727
|
this.unbind();
|
799
728
|
}
|
@@ -1099,11 +1028,8 @@ Marionette.View = Backbone.View.extend({
|
|
1099
1028
|
var args = Array.prototype.slice.apply(arguments);
|
1100
1029
|
Backbone.View.prototype.constructor.apply(this, args);
|
1101
1030
|
|
1102
|
-
Marionette.bindEntityEvents(this, this.model, Marionette.getOption(this, "modelEvents"));
|
1103
|
-
Marionette.bindEntityEvents(this, this.collection, Marionette.getOption(this, "collectionEvents"));
|
1104
|
-
|
1105
1031
|
Marionette.MonitorDOMRefresh(this);
|
1106
|
-
this.
|
1032
|
+
this.listenTo(this, "show", this.onShowCalled, this);
|
1107
1033
|
},
|
1108
1034
|
|
1109
1035
|
// import the "triggerMethod" to trigger events with corresponding
|
@@ -1147,10 +1073,22 @@ Marionette.View = Backbone.View.extend({
|
|
1147
1073
|
// action and stop propagation of DOM events
|
1148
1074
|
_.each(triggers, function(value, key){
|
1149
1075
|
|
1076
|
+
// build the event handler function for the DOM event
|
1150
1077
|
triggerEvents[key] = function(e){
|
1078
|
+
|
1079
|
+
// stop the event in it's tracks
|
1151
1080
|
if (e && e.preventDefault){ e.preventDefault(); }
|
1152
1081
|
if (e && e.stopPropagation){ e.stopPropagation(); }
|
1153
|
-
|
1082
|
+
|
1083
|
+
// buil the args for the event
|
1084
|
+
var args = {
|
1085
|
+
view: this,
|
1086
|
+
model: this.model,
|
1087
|
+
collection: this.collection
|
1088
|
+
};
|
1089
|
+
|
1090
|
+
// trigger the event
|
1091
|
+
that.trigger(value, args);
|
1154
1092
|
};
|
1155
1093
|
|
1156
1094
|
});
|
@@ -1158,9 +1096,16 @@ Marionette.View = Backbone.View.extend({
|
|
1158
1096
|
return triggerEvents;
|
1159
1097
|
},
|
1160
1098
|
|
1161
|
-
// Overriding Backbone.View's delegateEvents
|
1162
|
-
//
|
1099
|
+
// Overriding Backbone.View's delegateEvents to handle
|
1100
|
+
// the `triggers`, `modelEvents`, and `collectionEvents` configuration
|
1163
1101
|
delegateEvents: function(events){
|
1102
|
+
this._delegateDOMEvents(events);
|
1103
|
+
Marionette.bindEntityEvents(this, this.model, Marionette.getOption(this, "modelEvents"));
|
1104
|
+
Marionette.bindEntityEvents(this, this.collection, Marionette.getOption(this, "collectionEvents"));
|
1105
|
+
},
|
1106
|
+
|
1107
|
+
// internal method to delegate DOM events and triggers
|
1108
|
+
_delegateDOMEvents: function(events){
|
1164
1109
|
events = events || this.events;
|
1165
1110
|
if (_.isFunction(events)){ events = events.call(this); }
|
1166
1111
|
|
@@ -1171,6 +1116,16 @@ Marionette.View = Backbone.View.extend({
|
|
1171
1116
|
Backbone.View.prototype.delegateEvents.call(this, combinedEvents);
|
1172
1117
|
},
|
1173
1118
|
|
1119
|
+
// Overriding Backbone.View's undelegateEvents to handle unbinding
|
1120
|
+
// the `triggers`, `modelEvents`, and `collectionEvents` config
|
1121
|
+
undelegateEvents: function(){
|
1122
|
+
var args = Array.prototype.slice.call(arguments);
|
1123
|
+
Backbone.View.prototype.undelegateEvents.apply(this, args);
|
1124
|
+
|
1125
|
+
Marionette.unbindEntityEvents(this, this.model, Marionette.getOption(this, "modelEvents"));
|
1126
|
+
Marionette.unbindEntityEvents(this, this.collection, Marionette.getOption(this, "collectionEvents"));
|
1127
|
+
},
|
1128
|
+
|
1174
1129
|
// Internal method, handles the `show` event.
|
1175
1130
|
onShowCalled: function(){},
|
1176
1131
|
|
@@ -1192,10 +1147,9 @@ Marionette.View = Backbone.View.extend({
|
|
1192
1147
|
// prevent infinite loops within "close" event handlers
|
1193
1148
|
// that are trying to close other views
|
1194
1149
|
this.isClosed = true;
|
1150
|
+
this.triggerMethod("close");
|
1195
1151
|
|
1196
1152
|
this.remove();
|
1197
|
-
this.triggerMethod("close");
|
1198
|
-
this.unbindAll();
|
1199
1153
|
},
|
1200
1154
|
|
1201
1155
|
// This method binds the elements specified in the "ui" hash inside the view's code with
|
@@ -1208,7 +1162,7 @@ Marionette.View = Backbone.View.extend({
|
|
1208
1162
|
if (!this.uiBindings) {
|
1209
1163
|
// We want to store the ui hash in uiBindings, since afterwards the values in the ui hash
|
1210
1164
|
// will be overridden with jQuery selectors.
|
1211
|
-
this.uiBindings = this
|
1165
|
+
this.uiBindings = _.result(this, "ui");
|
1212
1166
|
}
|
1213
1167
|
|
1214
1168
|
// refreshing the associated selectors since they should point to the newly rendered elements.
|
@@ -1230,10 +1184,6 @@ Marionette.ItemView = Marionette.View.extend({
|
|
1230
1184
|
constructor: function(){
|
1231
1185
|
var args = Array.prototype.slice.apply(arguments);
|
1232
1186
|
Marionette.View.prototype.constructor.apply(this, args);
|
1233
|
-
|
1234
|
-
if (this.initialEvents){
|
1235
|
-
this.initialEvents();
|
1236
|
-
}
|
1237
1187
|
},
|
1238
1188
|
|
1239
1189
|
// Serialize the model or collection for the view. If a model is
|
@@ -1306,23 +1256,22 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1306
1256
|
|
1307
1257
|
// constructor
|
1308
1258
|
constructor: function(options){
|
1309
|
-
this.
|
1310
|
-
this.onShowCallbacks = new Marionette.Callbacks();
|
1259
|
+
this._initChildViewStorage();
|
1311
1260
|
|
1312
1261
|
var args = Array.prototype.slice.apply(arguments);
|
1313
1262
|
Marionette.View.prototype.constructor.apply(this, args);
|
1314
1263
|
|
1315
|
-
this.
|
1264
|
+
this._initialEvents();
|
1316
1265
|
},
|
1317
1266
|
|
1318
1267
|
// Configured the initial events that the collection view
|
1319
1268
|
// binds to. Override this method to prevent the initial
|
1320
1269
|
// events, or to add your own initial events.
|
1321
|
-
|
1270
|
+
_initialEvents: function(){
|
1322
1271
|
if (this.collection){
|
1323
|
-
this.
|
1324
|
-
this.
|
1325
|
-
this.
|
1272
|
+
this.listenTo(this.collection, "add", this.addChildView, this);
|
1273
|
+
this.listenTo(this.collection, "remove", this.removeItemView, this);
|
1274
|
+
this.listenTo(this.collection, "reset", this.render, this);
|
1326
1275
|
}
|
1327
1276
|
},
|
1328
1277
|
|
@@ -1330,21 +1279,16 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1330
1279
|
addChildView: function(item, collection, options){
|
1331
1280
|
this.closeEmptyView();
|
1332
1281
|
var ItemView = this.getItemView(item);
|
1333
|
-
|
1334
|
-
|
1335
|
-
if(options && options.index){
|
1336
|
-
index = options.index;
|
1337
|
-
} else {
|
1338
|
-
index = 0;
|
1339
|
-
}
|
1340
|
-
|
1341
|
-
return this.addItemView(item, ItemView, index);
|
1282
|
+
var index = this.collection.indexOf(item);
|
1283
|
+
this.addItemView(item, ItemView, index);
|
1342
1284
|
},
|
1343
1285
|
|
1344
1286
|
// Override from `Marionette.View` to guarantee the `onShow` method
|
1345
1287
|
// of child views is called.
|
1346
1288
|
onShowCalled: function(){
|
1347
|
-
this.
|
1289
|
+
this.children.each(function(child){
|
1290
|
+
Marionette.triggerMethod.call(child, "show");
|
1291
|
+
});
|
1348
1292
|
},
|
1349
1293
|
|
1350
1294
|
// Internal method to trigger the before render callbacks
|
@@ -1454,18 +1398,17 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1454
1398
|
// remove and/or close it later
|
1455
1399
|
this.children.add(view);
|
1456
1400
|
|
1401
|
+
// call the "show" method if the collection view
|
1402
|
+
// has already been shown
|
1403
|
+
if (this._isShown){
|
1404
|
+
Marionette.triggerMethod.call(view, "show");
|
1405
|
+
}
|
1406
|
+
|
1457
1407
|
// Render it and show it
|
1458
1408
|
var renderResult = this.renderItemView(view, index);
|
1459
1409
|
|
1460
1410
|
// this view was added
|
1461
1411
|
this.triggerMethod("after:item:added", view);
|
1462
|
-
|
1463
|
-
// call onShow for child item views
|
1464
|
-
if (view.onShow){
|
1465
|
-
this.onShowCallbacks.add(view.onShow, view);
|
1466
|
-
}
|
1467
|
-
|
1468
|
-
return renderResult;
|
1469
1412
|
},
|
1470
1413
|
|
1471
1414
|
// Set up the child view event forwarding. Uses an "itemview:"
|
@@ -1475,18 +1418,13 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1475
1418
|
|
1476
1419
|
// Forward all child item view events through the parent,
|
1477
1420
|
// prepending "itemview:" to the event name
|
1478
|
-
|
1421
|
+
this.listenTo(view, "all", function(){
|
1479
1422
|
var args = slice.call(arguments);
|
1480
1423
|
args[0] = prefix + ":" + args[0];
|
1481
1424
|
args.splice(1, 0, view);
|
1482
1425
|
|
1483
|
-
|
1426
|
+
Marionette.triggerMethod.apply(this, args);
|
1484
1427
|
}, this);
|
1485
|
-
|
1486
|
-
// Store all child event bindings so we can unbind
|
1487
|
-
// them when removing / closing the child view
|
1488
|
-
this._childBindings = this._childBindings || {};
|
1489
|
-
this._childBindings[view.cid] = childBinding;
|
1490
1428
|
},
|
1491
1429
|
|
1492
1430
|
// render the item view
|
@@ -1502,16 +1440,19 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1502
1440
|
return view;
|
1503
1441
|
},
|
1504
1442
|
|
1505
|
-
//
|
1443
|
+
// get the child view by item it holds, and remove it
|
1506
1444
|
removeItemView: function(item){
|
1507
1445
|
var view = this.children.findByModel(item);
|
1446
|
+
this.removeChildView(view);
|
1447
|
+
},
|
1448
|
+
|
1449
|
+
// Remove the child view and close it
|
1450
|
+
removeChildView: function(view){
|
1508
1451
|
|
1452
|
+
// shut down the child view properly,
|
1453
|
+
// including events that the collection has from it
|
1509
1454
|
if (view){
|
1510
|
-
|
1511
|
-
if (childBinding) {
|
1512
|
-
this.unbindFrom(childBinding);
|
1513
|
-
delete this._childBindings[view.cid];
|
1514
|
-
}
|
1455
|
+
this.stopListening(view);
|
1515
1456
|
|
1516
1457
|
if (view.close){
|
1517
1458
|
view.close();
|
@@ -1520,6 +1461,8 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1520
1461
|
this.children.remove(view);
|
1521
1462
|
}
|
1522
1463
|
|
1464
|
+
// check if we're empty now, and if we are, show the
|
1465
|
+
// empty view
|
1523
1466
|
if (!this.collection || this.collection.length === 0){
|
1524
1467
|
this.showEmptyView();
|
1525
1468
|
}
|
@@ -1536,7 +1479,7 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1536
1479
|
|
1537
1480
|
// Internal method to set up the `children` object for
|
1538
1481
|
// storing all of the child views
|
1539
|
-
|
1482
|
+
_initChildViewStorage: function(){
|
1540
1483
|
this.children = new Backbone.ChildViewContainer();
|
1541
1484
|
},
|
1542
1485
|
|
@@ -1556,10 +1499,12 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1556
1499
|
// Close the child views that this collection view
|
1557
1500
|
// is holding on to, if any
|
1558
1501
|
closeChildren: function(){
|
1559
|
-
|
1560
|
-
|
1502
|
+
this.children.each(function(child){
|
1503
|
+
this.removeChildView(child);
|
1504
|
+
}, this);
|
1505
|
+
|
1561
1506
|
// re-initialize to clean up after ourselves
|
1562
|
-
this.
|
1507
|
+
this._initChildViewStorage();
|
1563
1508
|
}
|
1564
1509
|
});
|
1565
1510
|
|
@@ -1581,11 +1526,11 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
|
|
1581
1526
|
// Configured the initial events that the composite view
|
1582
1527
|
// binds to. Override this method to prevent the initial
|
1583
1528
|
// events, or to add your own initial events.
|
1584
|
-
|
1529
|
+
_initialEvents: function(){
|
1585
1530
|
if (this.collection){
|
1586
|
-
this.
|
1587
|
-
this.
|
1588
|
-
this.
|
1531
|
+
this.listenTo(this.collection, "add", this.addChildView, this);
|
1532
|
+
this.listenTo(this.collection, "remove", this.removeItemView, this);
|
1533
|
+
this.listenTo(this.collection, "reset", this.renderCollection, this);
|
1589
1534
|
}
|
1590
1535
|
},
|
1591
1536
|
|
@@ -1724,7 +1669,7 @@ Marionette.Layout = Marionette.ItemView.extend({
|
|
1724
1669
|
this.initializeRegions();
|
1725
1670
|
|
1726
1671
|
var args = Array.prototype.slice.apply(arguments);
|
1727
|
-
|
1672
|
+
Marionette.ItemView.apply(this, args);
|
1728
1673
|
},
|
1729
1674
|
|
1730
1675
|
// Layout's render will use the existing region objects the
|
@@ -1758,7 +1703,7 @@ Marionette.Layout = Marionette.ItemView.extend({
|
|
1758
1703
|
this.destroyRegions();
|
1759
1704
|
|
1760
1705
|
var args = Array.prototype.slice.apply(arguments);
|
1761
|
-
|
1706
|
+
Marionette.ItemView.prototype.close.apply(this, args);
|
1762
1707
|
},
|
1763
1708
|
|
1764
1709
|
// Initialize the regions that have been defined in a
|
@@ -1988,15 +1933,15 @@ Marionette.Module = function(moduleName, app){
|
|
1988
1933
|
this._setupInitializersAndFinalizers();
|
1989
1934
|
|
1990
1935
|
// store the configuration for this module
|
1991
|
-
this.
|
1992
|
-
this.
|
1936
|
+
this.app = app;
|
1937
|
+
this.startWithParent = true;
|
1993
1938
|
|
1994
1939
|
// extend this module with an event binder
|
1995
1940
|
Marionette.addEventBinder(this);
|
1996
1941
|
this.triggerMethod = Marionette.triggerMethod;
|
1997
1942
|
};
|
1998
1943
|
|
1999
|
-
// Extend the Module prototype with events /
|
1944
|
+
// Extend the Module prototype with events / listenTo, so that the module
|
2000
1945
|
// can be used as an event aggregator or pub/sub.
|
2001
1946
|
_.extend(Marionette.Module.prototype, Backbone.Events, {
|
2002
1947
|
|
@@ -2022,9 +1967,7 @@ _.extend(Marionette.Module.prototype, Backbone.Events, {
|
|
2022
1967
|
_.each(this.submodules, function(mod){
|
2023
1968
|
// check to see if we should start the sub-module with this parent
|
2024
1969
|
var startWithParent = true;
|
2025
|
-
|
2026
|
-
startWithParent = mod.config.options.startWithParent;
|
2027
|
-
}
|
1970
|
+
startWithParent = mod.startWithParent;
|
2028
1971
|
|
2029
1972
|
// start the sub-module
|
2030
1973
|
if (startWithParent){
|
@@ -2078,7 +2021,7 @@ _.extend(Marionette.Module.prototype, Backbone.Events, {
|
|
2078
2021
|
// build the correct list of arguments for the module definition
|
2079
2022
|
var args = _.flatten([
|
2080
2023
|
this,
|
2081
|
-
this.
|
2024
|
+
this.app,
|
2082
2025
|
Backbone,
|
2083
2026
|
Marionette,
|
2084
2027
|
$, _,
|
@@ -2097,79 +2040,39 @@ _.extend(Marionette.Module.prototype, Backbone.Events, {
|
|
2097
2040
|
}
|
2098
2041
|
});
|
2099
2042
|
|
2100
|
-
//
|
2043
|
+
// Type methods to create modules
|
2101
2044
|
_.extend(Marionette.Module, {
|
2102
2045
|
|
2103
2046
|
// Create a module, hanging off the app parameter as the parent object.
|
2104
2047
|
create: function(app, moduleNames, moduleDefinition){
|
2105
2048
|
var that = this;
|
2106
|
-
var
|
2107
|
-
moduleNames = moduleNames.split(".");
|
2049
|
+
var module = app;
|
2108
2050
|
|
2109
2051
|
// get the custom args passed in after the module definition and
|
2110
2052
|
// get rid of the module name and definition function
|
2111
2053
|
var customArgs = slice.apply(arguments);
|
2112
2054
|
customArgs.splice(0, 3);
|
2113
2055
|
|
2114
|
-
//
|
2056
|
+
// split the module names and get the length
|
2057
|
+
moduleNames = moduleNames.split(".");
|
2115
2058
|
var length = moduleNames.length;
|
2116
|
-
_.each(moduleNames, function(moduleName, i){
|
2117
|
-
var isLastModuleInChain = (i === length-1);
|
2118
|
-
var isFirstModuleInChain = (i === 0);
|
2119
|
-
var module = that._getModuleDefinition(parentModule, moduleName, app);
|
2120
|
-
|
2121
|
-
// if this is the last module in the chain, then set up
|
2122
|
-
// all of the module options from the configuration
|
2123
|
-
if (isLastModuleInChain){
|
2124
|
-
module.config.options = that._getModuleOptions(module, parentModule, moduleDefinition);
|
2125
|
-
|
2126
|
-
// Only add a module definition and initializer when this is the last
|
2127
|
-
// module in a "parent.child.grandchild" hierarchy of module names and
|
2128
|
-
// when the module call has a definition function supplied
|
2129
|
-
if (module.config.options.hasDefinition){
|
2130
|
-
module.addDefinition(module.config.options.definition, customArgs);
|
2131
|
-
}
|
2132
|
-
}
|
2133
2059
|
|
2134
|
-
|
2135
|
-
|
2136
|
-
|
2137
|
-
if (isFirstModuleInChain && isLastModuleInChain ){
|
2138
|
-
that._configureStartWithApp(app, module);
|
2139
|
-
}
|
2060
|
+
// store the module definition for the last module in the chain
|
2061
|
+
var moduleDefinitions = [];
|
2062
|
+
moduleDefinitions[length-1] = moduleDefinition;
|
2140
2063
|
|
2141
|
-
|
2142
|
-
|
2143
|
-
parentModule = module;
|
2064
|
+
// Loop through all the parts of the module definition
|
2065
|
+
_.each(moduleNames, function(moduleName, i){
|
2066
|
+
var parentModule = module;
|
2067
|
+
module = that._getModule(parentModule, moduleName, app);
|
2068
|
+
that._addModuleDefinition(parentModule, module, moduleDefinitions[i], customArgs);
|
2144
2069
|
});
|
2145
2070
|
|
2146
2071
|
// Return the last module in the definition chain
|
2147
|
-
return
|
2148
|
-
},
|
2149
|
-
|
2150
|
-
// Only add the initializer if it is set to start with parent (the app),
|
2151
|
-
// and if it has not yet been added
|
2152
|
-
_configureStartWithApp: function(app, module){
|
2153
|
-
// skip this if we have already configured the module to start w/ the app
|
2154
|
-
if (module.config.startWithAppIsConfigured){
|
2155
|
-
return;
|
2156
|
-
}
|
2157
|
-
|
2158
|
-
// start the module when the app starts
|
2159
|
-
app.addInitializer(function(options){
|
2160
|
-
// but only if the module is configured to start w/ parent
|
2161
|
-
if (module.config.options.startWithParent){
|
2162
|
-
module.start(options);
|
2163
|
-
}
|
2164
|
-
});
|
2165
|
-
|
2166
|
-
// prevent this module from being configured for
|
2167
|
-
// auto start again. the first time the module
|
2168
|
-
// is defined, determines it's auto-start
|
2169
|
-
module.config.startWithAppIsConfigured = true;
|
2072
|
+
return module;
|
2170
2073
|
},
|
2171
2074
|
|
2172
|
-
|
2075
|
+
_getModule: function(parentModule, moduleName, app, def, args){
|
2173
2076
|
// Get an existing module of this name if we have one
|
2174
2077
|
var module = parentModule[moduleName];
|
2175
2078
|
|
@@ -2184,45 +2087,54 @@ _.extend(Marionette.Module, {
|
|
2184
2087
|
return module;
|
2185
2088
|
},
|
2186
2089
|
|
2187
|
-
|
2188
|
-
|
2189
|
-
var startWithParent
|
2190
|
-
if (module.config.options && !module.config.options.startWithParent){
|
2191
|
-
startWithParent = false;
|
2192
|
-
}
|
2090
|
+
_addModuleDefinition: function(parentModule, module, def, args){
|
2091
|
+
var fn;
|
2092
|
+
var startWithParent;
|
2193
2093
|
|
2194
|
-
|
2195
|
-
|
2196
|
-
|
2197
|
-
|
2198
|
-
};
|
2094
|
+
if (_.isFunction(def)){
|
2095
|
+
// if a function is supplied for the module definition
|
2096
|
+
fn = def;
|
2097
|
+
startWithParent = true;
|
2199
2098
|
|
2200
|
-
|
2201
|
-
|
2099
|
+
} else if (_.isObject(def)){
|
2100
|
+
// if an object is supplied
|
2101
|
+
fn = def.define;
|
2102
|
+
startWithParent = def.startWithParent;
|
2103
|
+
|
2104
|
+
} else {
|
2105
|
+
// if nothing is supplied
|
2106
|
+
startWithParent = true;
|
2107
|
+
}
|
2202
2108
|
|
2203
|
-
if
|
2204
|
-
|
2205
|
-
|
2206
|
-
|
2109
|
+
// add module definition if needed
|
2110
|
+
if (fn){
|
2111
|
+
module.addDefinition(fn, args);
|
2112
|
+
}
|
2207
2113
|
|
2208
|
-
|
2114
|
+
// `and` the two together, ensuring a single `false` will prevent it
|
2115
|
+
// from starting with the parent
|
2116
|
+
var tmp = module.startWithParent;
|
2117
|
+
module.startWithParent = module.startWithParent && startWithParent;
|
2209
2118
|
|
2210
|
-
|
2119
|
+
// setup auto-start if needed
|
2120
|
+
if (module.startWithParent && !module.startWithParentIsConfigured){
|
2211
2121
|
|
2212
|
-
//
|
2213
|
-
|
2214
|
-
|
2122
|
+
// only configure this once
|
2123
|
+
module.startWithParentIsConfigured = true;
|
2124
|
+
|
2125
|
+
// add the module initializer config
|
2126
|
+
parentModule.addInitializer(function(options){
|
2127
|
+
if (module.startWithParent){
|
2128
|
+
module.start(options);
|
2129
|
+
}
|
2130
|
+
});
|
2215
2131
|
|
2216
|
-
// grab the "startWithParent" attribute if one exists
|
2217
|
-
if (moduleDefinition.hasOwnProperty("startWithParent")){
|
2218
|
-
options.startWithParent = moduleDefinition.startWithParent;
|
2219
|
-
}
|
2220
2132
|
}
|
2221
2133
|
|
2222
|
-
return options;
|
2223
2134
|
}
|
2224
2135
|
});
|
2225
2136
|
|
2226
2137
|
|
2138
|
+
|
2227
2139
|
return Marionette;
|
2228
2140
|
})(Backbone, _, $ || window.jQuery || window.Zepto || window.ender);
|