marionette-rails 0.10.2 → 1.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/vendor/assets/javascripts/backbone.marionette.js +285 -217
- metadata +35 -51
@@ -1,65 +1,65 @@
|
|
1
|
-
// Backbone.Marionette,
|
1
|
+
// Backbone.Marionette, v1.0.0-beta1
|
2
2
|
// Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
|
3
3
|
// Distributed under MIT license
|
4
|
-
// http://github.com/
|
5
|
-
Backbone.Marionette = (function(Backbone, _, $){
|
4
|
+
// http://github.com/marionettejs/backbone.marionette
|
5
|
+
Backbone.Marionette = Marionette = (function(Backbone, _, $){
|
6
6
|
var Marionette = {};
|
7
7
|
|
8
|
-
//
|
9
|
-
//
|
10
|
-
|
11
|
-
// The event binder facilitates the binding and unbinding of events
|
12
|
-
// from objects that extend `Backbone.Events`. It makes
|
13
|
-
// unbinding events, even with anonymous callback functions,
|
14
|
-
// easy.
|
15
|
-
//
|
16
|
-
// Inspired by [Johnny Oshika](http://stackoverflow.com/questions/7567404/backbone-js-repopulate-or-recreate-the-view/7607853#7607853)
|
17
|
-
|
18
|
-
Marionette.EventBinder = function(){
|
19
|
-
this._eventBindings = [];
|
20
|
-
};
|
8
|
+
// Helpers
|
9
|
+
// -------
|
21
10
|
|
22
|
-
|
23
|
-
|
24
|
-
// easily, at a later point in time.
|
25
|
-
bindTo: function (obj, eventName, callback, context) {
|
26
|
-
context = context || this;
|
27
|
-
obj.on(eventName, callback, context);
|
28
|
-
|
29
|
-
var binding = {
|
30
|
-
obj: obj,
|
31
|
-
eventName: eventName,
|
32
|
-
callback: callback,
|
33
|
-
context: context
|
34
|
-
};
|
11
|
+
// For slicing `arguments` in functions
|
12
|
+
var slice = Array.prototype.slice;
|
35
13
|
|
36
|
-
|
14
|
+
// Borrow the Backbone `extend` method so we can use it as needed
|
15
|
+
Marionette.extend = Backbone.Model.extend;
|
37
16
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
17
|
+
// Trigger an event and a corresponding method name. Examples:
|
18
|
+
//
|
19
|
+
// `this.triggerMethod("foo")` will trigger the "foo" event and
|
20
|
+
// call the "onFoo" method.
|
21
|
+
//
|
22
|
+
// `this.triggerMethod("foo:bar") will trigger the "foo:bar" event and
|
23
|
+
// call the "onFooBar" method.
|
24
|
+
Marionette.triggerMethod = function(){
|
25
|
+
var args = Array.prototype.slice.apply(arguments);
|
26
|
+
var eventName = args[0];
|
27
|
+
var segments = eventName.split(":");
|
28
|
+
var segment, capLetter, methodName = "on";
|
29
|
+
|
30
|
+
for (var i = 0; i < segments.length; i++){
|
31
|
+
segment = segments[i];
|
32
|
+
capLetter = segment.charAt(0).toUpperCase();
|
33
|
+
methodName += capLetter + segment.slice(1);
|
34
|
+
}
|
47
35
|
|
48
|
-
|
49
|
-
unbindAll: function () {
|
50
|
-
var that = this;
|
36
|
+
this.trigger.apply(this, arguments);
|
51
37
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
_.each(bindings, function (binding, index) {
|
56
|
-
that.unbindFrom(binding);
|
57
|
-
});
|
38
|
+
if (_.isFunction(this[methodName])){
|
39
|
+
args.shift();
|
40
|
+
this[methodName].apply(this, args);
|
58
41
|
}
|
59
|
-
}
|
42
|
+
};
|
60
43
|
|
61
|
-
//
|
62
|
-
|
44
|
+
// EventBinder
|
45
|
+
// -----------
|
46
|
+
// Import the event binder from it's new home
|
47
|
+
// https://github.com/marionettejs/backbone.eventbinder
|
48
|
+
Marionette.EventBinder = Backbone.EventBinder;
|
49
|
+
|
50
|
+
// Add the EventBinder methods to the view directly,
|
51
|
+
// but keep them bound to the EventBinder instance so they work properly.
|
52
|
+
// This allows the event binder's implementation to vary independently
|
53
|
+
// of it being attached to the view... for example the internal structure
|
54
|
+
// used to store the events can change without worry about it interfering
|
55
|
+
// with Marionette's views.
|
56
|
+
Marionette.addEventBinder = function(target){
|
57
|
+
var eventBinder = new Marionette.EventBinder();
|
58
|
+
target.eventBinder = eventBinder;
|
59
|
+
target.bindTo = _.bind(eventBinder.bindTo, eventBinder);
|
60
|
+
target.unbindFrom = _.bind(eventBinder.unbindFrom, eventBinder);
|
61
|
+
target.unbindAll = _.bind(eventBinder.unbindAll, eventBinder);
|
62
|
+
};
|
63
63
|
|
64
64
|
// Marionette.View
|
65
65
|
// ---------------
|
@@ -68,8 +68,8 @@ Marionette.EventBinder.extend = Backbone.View.extend;
|
|
68
68
|
Marionette.View = Backbone.View.extend({
|
69
69
|
|
70
70
|
constructor: function(){
|
71
|
-
|
72
|
-
|
71
|
+
_.bindAll(this, "render");
|
72
|
+
Marionette.addEventBinder(this);
|
73
73
|
|
74
74
|
Backbone.View.prototype.constructor.apply(this, arguments);
|
75
75
|
|
@@ -79,6 +79,10 @@ Marionette.View = Backbone.View.extend({
|
|
79
79
|
this.bindTo(this, "show", this.onShowCalled, this);
|
80
80
|
},
|
81
81
|
|
82
|
+
// import the "triggerMethod" to trigger events with corresponding
|
83
|
+
// methods if the method exists
|
84
|
+
triggerMethod: Marionette.triggerMethod,
|
85
|
+
|
82
86
|
// Get the template for this view
|
83
87
|
// instance. You can set a `template` attribute in the view
|
84
88
|
// definition or pass a `template: "whatever"` parameter in
|
@@ -97,27 +101,6 @@ Marionette.View = Backbone.View.extend({
|
|
97
101
|
return template;
|
98
102
|
},
|
99
103
|
|
100
|
-
// Serialize the model or collection for the view. If a model is
|
101
|
-
// found, `.toJSON()` is called. If a collection is found, `.toJSON()`
|
102
|
-
// is also called, but is used to populate an `items` array in the
|
103
|
-
// resulting data. If both are found, defaults to the model.
|
104
|
-
// You can override the `serializeData` method in your own view
|
105
|
-
// definition, to provide custom serialization for your view's data.
|
106
|
-
serializeData: function(){
|
107
|
-
var data;
|
108
|
-
|
109
|
-
if (this.model) {
|
110
|
-
data = this.model.toJSON();
|
111
|
-
}
|
112
|
-
else if (this.collection) {
|
113
|
-
data = { items: this.collection.toJSON() };
|
114
|
-
}
|
115
|
-
|
116
|
-
data = this.mixinTemplateHelpers(data);
|
117
|
-
|
118
|
-
return data;
|
119
|
-
},
|
120
|
-
|
121
104
|
// Mix in template helper methods. Looks for a
|
122
105
|
// `templateHelpers` attribute, which can either be an
|
123
106
|
// object literal, or a function that returns an object
|
@@ -180,14 +163,15 @@ Marionette.View = Backbone.View.extend({
|
|
180
163
|
// for you. You can specify an `onClose` method in your view to
|
181
164
|
// add custom code that is called after the view is closed.
|
182
165
|
close: function(){
|
183
|
-
if (this.
|
166
|
+
if (this.isClosed) { return; }
|
184
167
|
|
185
|
-
this.
|
168
|
+
this.triggerMethod("before:close");
|
186
169
|
|
187
|
-
|
188
|
-
this.trigger('close');
|
170
|
+
this.remove();
|
189
171
|
this.unbindAll();
|
190
|
-
|
172
|
+
|
173
|
+
this.triggerMethod("close");
|
174
|
+
this.isClosed = true;
|
191
175
|
},
|
192
176
|
|
193
177
|
// This method binds the elements specified in the "ui" hash inside the view's code with
|
@@ -243,15 +227,37 @@ Marionette.ItemView = Marionette.View.extend({
|
|
243
227
|
}
|
244
228
|
},
|
245
229
|
|
230
|
+
// Serialize the model or collection for the view. If a model is
|
231
|
+
// found, `.toJSON()` is called. If a collection is found, `.toJSON()`
|
232
|
+
// is also called, but is used to populate an `items` array in the
|
233
|
+
// resulting data. If both are found, defaults to the model.
|
234
|
+
// You can override the `serializeData` method in your own view
|
235
|
+
// definition, to provide custom serialization for your view's data.
|
236
|
+
serializeData: function(){
|
237
|
+
var data;
|
238
|
+
|
239
|
+
if (this.model) {
|
240
|
+
data = this.model.toJSON();
|
241
|
+
}
|
242
|
+
else if (this.collection) {
|
243
|
+
data = { items: this.collection.toJSON() };
|
244
|
+
}
|
245
|
+
|
246
|
+
data = this.mixinTemplateHelpers(data);
|
247
|
+
|
248
|
+
return data;
|
249
|
+
},
|
250
|
+
|
246
251
|
// Render the view, defaulting to underscore.js templates.
|
247
252
|
// You can override this in your view definition to provide
|
248
253
|
// a very specific rendering for your view. In general, though,
|
249
254
|
// you should override the `Marionette.Renderer` object to
|
250
255
|
// change how Marionette renders views.
|
251
256
|
render: function(){
|
252
|
-
|
253
|
-
|
254
|
-
this.
|
257
|
+
this.isClosed = false;
|
258
|
+
|
259
|
+
this.triggerMethod("before:render", this);
|
260
|
+
this.triggerMethod("item:before:render", this);
|
255
261
|
|
256
262
|
var data = this.serializeData();
|
257
263
|
var template = this.getTemplate();
|
@@ -259,18 +265,20 @@ Marionette.ItemView = Marionette.View.extend({
|
|
259
265
|
this.$el.html(html);
|
260
266
|
this.bindUIElements();
|
261
267
|
|
262
|
-
|
263
|
-
this.
|
264
|
-
|
268
|
+
this.triggerMethod("render", this);
|
269
|
+
this.triggerMethod("item:rendered", this);
|
270
|
+
|
265
271
|
return this;
|
266
272
|
},
|
267
273
|
|
268
274
|
// Override the default close event to add a few
|
269
275
|
// more events that are triggered.
|
270
276
|
close: function(){
|
271
|
-
this.
|
277
|
+
if (this.isClosed){ return; }
|
278
|
+
|
279
|
+
this.triggerMethod('item:before:close');
|
272
280
|
Marionette.View.prototype.close.apply(this, arguments);
|
273
|
-
this.
|
281
|
+
this.triggerMethod('item:closed');
|
274
282
|
}
|
275
283
|
});
|
276
284
|
|
@@ -281,8 +289,8 @@ Marionette.ItemView = Marionette.View.extend({
|
|
281
289
|
// and renders an individual ItemView for each model.
|
282
290
|
Marionette.CollectionView = Marionette.View.extend({
|
283
291
|
constructor: function(){
|
284
|
-
Marionette.View.prototype.constructor.apply(this, arguments);
|
285
292
|
this.initChildViewStorage();
|
293
|
+
Marionette.View.prototype.constructor.apply(this, arguments);
|
286
294
|
this.initialEvents();
|
287
295
|
this.onShowCallbacks = new Marionette.Callbacks();
|
288
296
|
},
|
@@ -302,7 +310,15 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
302
310
|
addChildView: function(item, collection, options){
|
303
311
|
this.closeEmptyView();
|
304
312
|
var ItemView = this.getItemView(item);
|
305
|
-
|
313
|
+
|
314
|
+
var index;
|
315
|
+
if(options && options.index){
|
316
|
+
index = options.index;
|
317
|
+
} else {
|
318
|
+
index = 0;
|
319
|
+
}
|
320
|
+
|
321
|
+
return this.addItemView(item, ItemView, index);
|
306
322
|
},
|
307
323
|
|
308
324
|
// Override from `Marionette.View` to guarantee the `onShow` method
|
@@ -314,23 +330,23 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
314
330
|
// Internal method to trigger the before render callbacks
|
315
331
|
// and events
|
316
332
|
triggerBeforeRender: function(){
|
317
|
-
|
318
|
-
this.
|
319
|
-
this.trigger("collection:before:render", this);
|
333
|
+
this.triggerMethod("before:render", this);
|
334
|
+
this.triggerMethod("collection:before:render", this);
|
320
335
|
},
|
321
336
|
|
322
337
|
// Internal method to trigger the rendered callbacks and
|
323
338
|
// events
|
324
339
|
triggerRendered: function(){
|
325
|
-
|
326
|
-
this.
|
327
|
-
this.trigger("collection:rendered", this);
|
340
|
+
this.triggerMethod("render", this);
|
341
|
+
this.triggerMethod("collection:rendered", this);
|
328
342
|
},
|
329
343
|
|
330
344
|
// Render the collection of items. Override this method to
|
331
345
|
// provide your own implementation of a render function for
|
332
346
|
// the collection view.
|
333
347
|
render: function(){
|
348
|
+
this.isClosed = false;
|
349
|
+
|
334
350
|
this.triggerBeforeRender();
|
335
351
|
this.closeEmptyView();
|
336
352
|
this.closeChildren();
|
@@ -403,8 +419,7 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
403
419
|
// Store the child view itself so we can properly
|
404
420
|
// remove and/or close it later
|
405
421
|
this.storeChild(view);
|
406
|
-
|
407
|
-
this.trigger("item:added", view);
|
422
|
+
this.triggerMethod("item:added", view);
|
408
423
|
|
409
424
|
// Render it and show it
|
410
425
|
var renderResult = this.renderItemView(view, index);
|
@@ -421,7 +436,7 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
421
436
|
args[0] = "itemview:" + args[0];
|
422
437
|
args.splice(1, 0, view);
|
423
438
|
|
424
|
-
that.
|
439
|
+
that.triggerMethod.apply(that, args);
|
425
440
|
});
|
426
441
|
|
427
442
|
// Store all child event bindings so we can unbind
|
@@ -470,7 +485,7 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
470
485
|
this.showEmptyView();
|
471
486
|
}
|
472
487
|
|
473
|
-
this.
|
488
|
+
this.triggerMethod("item:removed", view);
|
474
489
|
},
|
475
490
|
|
476
491
|
// Append the HTML to the collection's `el`.
|
@@ -495,9 +510,11 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
495
510
|
// Handle cleanup and other closing needs for
|
496
511
|
// the collection of views.
|
497
512
|
close: function(){
|
498
|
-
this.
|
513
|
+
if (this.isClosed){ return; }
|
514
|
+
|
515
|
+
this.triggerMethod("collection:before:close");
|
499
516
|
this.closeChildren();
|
500
|
-
this.
|
517
|
+
this.triggerMethod("collection:closed");
|
501
518
|
Marionette.View.prototype.close.apply(this, arguments);
|
502
519
|
},
|
503
520
|
|
@@ -553,31 +570,49 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
|
|
553
570
|
return itemView;
|
554
571
|
},
|
555
572
|
|
573
|
+
// Serialize the collection for the view.
|
574
|
+
// You can override the `serializeData` method in your own view
|
575
|
+
// definition, to provide custom serialization for your view's data.
|
576
|
+
serializeData: function(){
|
577
|
+
var data = {};
|
578
|
+
|
579
|
+
if (this.model){
|
580
|
+
data = this.model.toJSON();
|
581
|
+
}
|
582
|
+
|
583
|
+
data = this.mixinTemplateHelpers(data);
|
584
|
+
|
585
|
+
return data;
|
586
|
+
},
|
587
|
+
|
556
588
|
// Renders the model once, and the collection once. Calling
|
557
589
|
// this again will tell the model's view to re-render itself
|
558
590
|
// but the collection will not re-render.
|
559
591
|
render: function(){
|
560
|
-
|
592
|
+
this.isClosed = false;
|
561
593
|
|
562
594
|
this.resetItemViewContainer();
|
563
595
|
|
564
596
|
var html = this.renderModel();
|
565
597
|
this.$el.html(html);
|
566
|
-
|
598
|
+
|
599
|
+
// the ui bindings is done here and not at the end of render since they
|
600
|
+
// will not be available until after the model is rendered, but should be
|
567
601
|
// available before the collection is rendered.
|
568
602
|
this.bindUIElements();
|
569
|
-
|
570
|
-
this.
|
603
|
+
|
604
|
+
this.triggerMethod("composite:model:rendered");
|
605
|
+
this.triggerMethod("render");
|
571
606
|
|
572
607
|
this.renderCollection();
|
573
|
-
this.
|
608
|
+
this.triggerMethod("composite:rendered");
|
574
609
|
return this;
|
575
610
|
},
|
576
611
|
|
577
612
|
// Render the collection for the composite view
|
578
613
|
renderCollection: function(){
|
579
614
|
Marionette.CollectionView.prototype.render.apply(this, arguments);
|
580
|
-
this.
|
615
|
+
this.triggerMethod("composite:collection:rendered");
|
581
616
|
},
|
582
617
|
|
583
618
|
// Render an individual model, if we have one, as
|
@@ -603,23 +638,26 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
|
|
603
638
|
// Internal method to ensure an `$itemViewContainer` exists, for the
|
604
639
|
// `appendHtml` method to use.
|
605
640
|
getItemViewContainer: function(containerView){
|
606
|
-
var container;
|
607
641
|
if ("$itemViewContainer" in containerView){
|
608
|
-
|
609
|
-
}
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
642
|
+
return containerView.$itemViewContainer;
|
643
|
+
}
|
644
|
+
|
645
|
+
var container;
|
646
|
+
if (containerView.itemViewContainer){
|
647
|
+
|
648
|
+
var selector = _.result(containerView, "itemViewContainer");
|
649
|
+
container = containerView.$(selector);
|
650
|
+
if (container.length <= 0) {
|
651
|
+
var err = new Error("The specified `itemViewContainer` was not found: " + containerView.itemViewContainer);
|
652
|
+
err.name = "ItemViewContainerMissingError";
|
653
|
+
throw err;
|
620
654
|
}
|
621
|
-
|
655
|
+
|
656
|
+
} else {
|
657
|
+
container = containerView.$el;
|
622
658
|
}
|
659
|
+
|
660
|
+
containerView.$itemViewContainer = container;
|
623
661
|
return container;
|
624
662
|
},
|
625
663
|
|
@@ -634,17 +672,24 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
|
|
634
672
|
|
635
673
|
// Region
|
636
674
|
// ------
|
637
|
-
|
675
|
+
//
|
638
676
|
// Manage the visual regions of your composite application. See
|
639
677
|
// http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/
|
678
|
+
|
640
679
|
Marionette.Region = function(options){
|
641
680
|
this.options = options || {};
|
642
681
|
|
643
|
-
var
|
644
|
-
|
682
|
+
var el = this.options.el;
|
683
|
+
delete this.options.el;
|
684
|
+
|
685
|
+
Marionette.addEventBinder(this);
|
686
|
+
|
687
|
+
if (el){
|
688
|
+
this.el = el;
|
689
|
+
}
|
645
690
|
|
646
691
|
if (!this.el){
|
647
|
-
var err = new Error("An 'el' must be specified");
|
692
|
+
var err = new Error("An 'el' must be specified for a region.");
|
648
693
|
err.name = "NoElError";
|
649
694
|
throw err;
|
650
695
|
}
|
@@ -654,6 +699,76 @@ Marionette.Region = function(options){
|
|
654
699
|
}
|
655
700
|
};
|
656
701
|
|
702
|
+
|
703
|
+
// Region Type methods
|
704
|
+
// -------------------
|
705
|
+
|
706
|
+
_.extend(Marionette.Region, {
|
707
|
+
|
708
|
+
// Build an instance of a region by passing in a configuration object
|
709
|
+
// and a default region type to use if none is specified in the config.
|
710
|
+
//
|
711
|
+
// The config object should either be a string as a jQuery DOM selector,
|
712
|
+
// a Region type directly, or an object literal that specifies both
|
713
|
+
// a selector and regionType:
|
714
|
+
//
|
715
|
+
// ```js
|
716
|
+
// {
|
717
|
+
// selector: "#foo",
|
718
|
+
// regionType: MyCustomRegion
|
719
|
+
// }
|
720
|
+
// ```
|
721
|
+
//
|
722
|
+
buildRegion: function(regionConfig, defaultRegionType){
|
723
|
+
var regionIsString = (typeof regionConfig === "string");
|
724
|
+
var regionSelectorIsString = (typeof regionConfig.selector === "string");
|
725
|
+
var regionTypeIsUndefined = (typeof regionConfig.regionType === "undefined");
|
726
|
+
var regionIsType = (typeof regionConfig === "function");
|
727
|
+
|
728
|
+
if (!regionIsType && !regionIsString && !regionSelectorIsString) {
|
729
|
+
throw new Error("Region must be specified as a Region type, a selector string or an object with selector property");
|
730
|
+
}
|
731
|
+
|
732
|
+
var selector, RegionType;
|
733
|
+
|
734
|
+
// get the selector for the region
|
735
|
+
|
736
|
+
if (regionIsString) {
|
737
|
+
selector = regionConfig;
|
738
|
+
}
|
739
|
+
|
740
|
+
if (regionConfig.selector) {
|
741
|
+
selector = regionConfig.selector;
|
742
|
+
}
|
743
|
+
|
744
|
+
// get the type for the region
|
745
|
+
|
746
|
+
if (regionIsType){
|
747
|
+
RegionType = regionConfig;
|
748
|
+
}
|
749
|
+
|
750
|
+
if (!regionIsType && regionTypeIsUndefined) {
|
751
|
+
RegionType = defaultRegionType;
|
752
|
+
}
|
753
|
+
|
754
|
+
if (regionConfig.regionType) {
|
755
|
+
RegionType = regionConfig.regionType;
|
756
|
+
}
|
757
|
+
|
758
|
+
// build the region instance
|
759
|
+
|
760
|
+
var regionManager = new RegionType({
|
761
|
+
el: selector
|
762
|
+
});
|
763
|
+
|
764
|
+
return regionManager;
|
765
|
+
}
|
766
|
+
|
767
|
+
});
|
768
|
+
|
769
|
+
// Region Instance Methods
|
770
|
+
// -----------------------
|
771
|
+
|
657
772
|
_.extend(Marionette.Region.prototype, Backbone.Events, {
|
658
773
|
|
659
774
|
// Displays a backbone view instance inside of the region.
|
@@ -700,7 +815,7 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
|
|
700
815
|
// current view, it does nothing and returns immediately.
|
701
816
|
close: function(){
|
702
817
|
var view = this.currentView;
|
703
|
-
if (!view){ return; }
|
818
|
+
if (!view || view.isClosed){ return; }
|
704
819
|
|
705
820
|
if (view.close) { view.close(); }
|
706
821
|
this.trigger("view:closed", view);
|
@@ -727,7 +842,7 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
|
|
727
842
|
});
|
728
843
|
|
729
844
|
// Copy the `extend` function used by Backbone's classes
|
730
|
-
Marionette.Region.extend =
|
845
|
+
Marionette.Region.extend = Marionette.extend;
|
731
846
|
|
732
847
|
// Layout
|
733
848
|
// ------
|
@@ -768,6 +883,8 @@ Marionette.Layout = Marionette.ItemView.extend({
|
|
768
883
|
|
769
884
|
// Handle closing regions, and then close the view itself.
|
770
885
|
close: function () {
|
886
|
+
if (this.isClosed){ return; }
|
887
|
+
|
771
888
|
this.closeRegions();
|
772
889
|
this.destroyRegions();
|
773
890
|
Backbone.Marionette.ItemView.prototype.close.call(this, arguments);
|
@@ -785,35 +902,13 @@ Marionette.Layout = Marionette.ItemView.extend({
|
|
785
902
|
}
|
786
903
|
|
787
904
|
var that = this;
|
788
|
-
|
789
|
-
|
790
|
-
var regionSelectorIsString = (typeof region.selector === "string");
|
791
|
-
var regionTypeIsUndefined = (typeof region.regionType === "undefined");
|
792
|
-
|
793
|
-
if (!regionIsString && !regionSelectorIsString) {
|
794
|
-
throw new Error("Region must be specified as a selector string or an object with selector property");
|
795
|
-
}
|
905
|
+
var regions = this.regions || {};
|
906
|
+
_.each(regions, function (region, name) {
|
796
907
|
|
797
|
-
var
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
} else {
|
802
|
-
selector = region.selector;
|
803
|
-
}
|
804
|
-
|
805
|
-
if (regionTypeIsUndefined){
|
806
|
-
RegionType = that.regionType;
|
807
|
-
} else {
|
808
|
-
RegionType = region.regionType;
|
809
|
-
}
|
810
|
-
|
811
|
-
var regionManager = new RegionType({
|
812
|
-
el: selector,
|
813
|
-
getEl: function(selector){
|
814
|
-
return that.$(selector);
|
815
|
-
}
|
816
|
-
});
|
908
|
+
var regionManager = Marionette.Region.buildRegion(region, that.regionType);
|
909
|
+
regionManager.getEl = function(selector){
|
910
|
+
return that.$(selector);
|
911
|
+
};
|
817
912
|
|
818
913
|
that.regionManagers[name] = regionManager;
|
819
914
|
that[name] = regionManager;
|
@@ -864,13 +959,26 @@ Marionette.Layout = Marionette.ItemView.extend({
|
|
864
959
|
Marionette.Application = function(options){
|
865
960
|
this.initCallbacks = new Marionette.Callbacks();
|
866
961
|
this.vent = new Marionette.EventAggregator();
|
962
|
+
this.commands = new Backbone.Wreqr.Commands();
|
963
|
+
this.reqres = new Backbone.Wreqr.RequestResponse();
|
867
964
|
this.submodules = {};
|
868
965
|
|
869
|
-
|
870
|
-
|
966
|
+
_.extend(this, options);
|
967
|
+
|
968
|
+
Marionette.addEventBinder(this);
|
871
969
|
};
|
872
970
|
|
873
971
|
_.extend(Marionette.Application.prototype, Backbone.Events, {
|
972
|
+
// Command execution, facilitated by Backbone.Wreqr.Commands
|
973
|
+
execute: function(){
|
974
|
+
this.commands.execute.apply(this.commands, arguments);
|
975
|
+
},
|
976
|
+
|
977
|
+
// Request/response, facilitated by Backbone.Wreqr.RequestResponse
|
978
|
+
request: function(){
|
979
|
+
return this.reqres.request.apply(this.reqres, arguments);
|
980
|
+
},
|
981
|
+
|
874
982
|
// Add an initializer that is either run at when the `start`
|
875
983
|
// method is called, or run immediately if added after `start`
|
876
984
|
// has already been called.
|
@@ -894,23 +1002,11 @@ _.extend(Marionette.Application.prototype, Backbone.Events, {
|
|
894
1002
|
// addRegions({something: "#someRegion"})
|
895
1003
|
// addRegions{{something: Region.extend({el: "#someRegion"}) });
|
896
1004
|
addRegions: function(regions){
|
897
|
-
var
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
if (typeof RegionValue === "string"){
|
904
|
-
regionObj = new Marionette.Region({
|
905
|
-
el: RegionValue
|
906
|
-
});
|
907
|
-
} else {
|
908
|
-
regionObj = new RegionValue();
|
909
|
-
}
|
910
|
-
|
911
|
-
this[region] = regionObj;
|
912
|
-
}
|
913
|
-
}
|
1005
|
+
var that = this;
|
1006
|
+
_.each(regions, function (region, name) {
|
1007
|
+
var regionManager = Marionette.Region.buildRegion(region, Marionette.Region);
|
1008
|
+
that[name] = regionManager;
|
1009
|
+
});
|
914
1010
|
},
|
915
1011
|
|
916
1012
|
// Removes a region from your app.
|
@@ -934,7 +1030,7 @@ _.extend(Marionette.Application.prototype, Backbone.Events, {
|
|
934
1030
|
});
|
935
1031
|
|
936
1032
|
// Copy the `extend` function used by Backbone's classes
|
937
|
-
Marionette.Application.extend =
|
1033
|
+
Marionette.Application.extend = Marionette.extend;
|
938
1034
|
|
939
1035
|
// AppRouter
|
940
1036
|
// ---------
|
@@ -1008,7 +1104,7 @@ Marionette.AppRouter = Backbone.Router.extend({
|
|
1008
1104
|
|
1009
1105
|
// A simple module system, used to create privacy and encapsulation in
|
1010
1106
|
// Marionette applications
|
1011
|
-
Marionette.Module = function(moduleName, app
|
1107
|
+
Marionette.Module = function(moduleName, app){
|
1012
1108
|
this.moduleName = moduleName;
|
1013
1109
|
|
1014
1110
|
// store sub-modules
|
@@ -1019,12 +1115,9 @@ Marionette.Module = function(moduleName, app, customArgs){
|
|
1019
1115
|
// store the configuration for this module
|
1020
1116
|
this.config = {};
|
1021
1117
|
this.config.app = app;
|
1022
|
-
this.config.customArgs = customArgs;
|
1023
|
-
this.config.definitions = [];
|
1024
1118
|
|
1025
1119
|
// extend this module with an event binder
|
1026
|
-
|
1027
|
-
_.extend(this, eventBinder);
|
1120
|
+
Marionette.addEventBinder(this);
|
1028
1121
|
};
|
1029
1122
|
|
1030
1123
|
// Extend the Module prototype with events / bindTo, so that the module
|
@@ -1082,13 +1175,13 @@ _.extend(Marionette.Module.prototype, Backbone.Events, {
|
|
1082
1175
|
|
1083
1176
|
// Configure the module with a definition function and any custom args
|
1084
1177
|
// that are to be passed in to the definition function
|
1085
|
-
addDefinition: function(moduleDefinition){
|
1086
|
-
this._runModuleDefinition(moduleDefinition);
|
1178
|
+
addDefinition: function(moduleDefinition, customArgs){
|
1179
|
+
this._runModuleDefinition(moduleDefinition, customArgs);
|
1087
1180
|
},
|
1088
1181
|
|
1089
1182
|
// Internal method: run the module definition function with the correct
|
1090
1183
|
// arguments
|
1091
|
-
_runModuleDefinition: function(definition){
|
1184
|
+
_runModuleDefinition: function(definition, customArgs){
|
1092
1185
|
if (!definition){ return; }
|
1093
1186
|
|
1094
1187
|
// build the correct list of arguments for the module definition
|
@@ -1098,7 +1191,7 @@ _.extend(Marionette.Module.prototype, Backbone.Events, {
|
|
1098
1191
|
Backbone,
|
1099
1192
|
Marionette,
|
1100
1193
|
$, _,
|
1101
|
-
|
1194
|
+
customArgs
|
1102
1195
|
]);
|
1103
1196
|
|
1104
1197
|
definition.apply(this, args);
|
@@ -1132,7 +1225,7 @@ _.extend(Marionette.Module, {
|
|
1132
1225
|
_.each(moduleNames, function(moduleName, i){
|
1133
1226
|
var isLastModuleInChain = (i === length-1);
|
1134
1227
|
|
1135
|
-
var module = that._getModuleDefinition(parentModule, moduleName, app
|
1228
|
+
var module = that._getModuleDefinition(parentModule, moduleName, app);
|
1136
1229
|
module.config.options = that._getModuleOptions(parentModule, moduleDefinition);
|
1137
1230
|
|
1138
1231
|
// if it's the first module in the chain, configure it
|
@@ -1145,7 +1238,7 @@ _.extend(Marionette.Module, {
|
|
1145
1238
|
// the last module in a "parent.child.grandchild" hierarchy of
|
1146
1239
|
// module names
|
1147
1240
|
if (isLastModuleInChain && module.config.options.hasDefinition){
|
1148
|
-
module.addDefinition(module.config.options.definition);
|
1241
|
+
module.addDefinition(module.config.options.definition, customArgs);
|
1149
1242
|
}
|
1150
1243
|
|
1151
1244
|
// Reset the parent module so that the next child
|
@@ -1173,13 +1266,13 @@ _.extend(Marionette.Module, {
|
|
1173
1266
|
module.config.autoStartConfigured = true;
|
1174
1267
|
},
|
1175
1268
|
|
1176
|
-
_getModuleDefinition: function(parentModule, moduleName, app
|
1269
|
+
_getModuleDefinition: function(parentModule, moduleName, app){
|
1177
1270
|
// Get an existing module of this name if we have one
|
1178
1271
|
var module = parentModule[moduleName];
|
1179
1272
|
|
1180
1273
|
if (!module){
|
1181
1274
|
// Create a new module if we don't have one
|
1182
|
-
module = new Marionette.Module(moduleName, app
|
1275
|
+
module = new Marionette.Module(moduleName, app);
|
1183
1276
|
parentModule[moduleName] = module;
|
1184
1277
|
// store the module on the parent
|
1185
1278
|
parentModule.submodules[moduleName] = module;
|
@@ -1386,37 +1479,12 @@ _.extend(Marionette.Callbacks.prototype, {
|
|
1386
1479
|
|
1387
1480
|
// Event Aggregator
|
1388
1481
|
// ----------------
|
1389
|
-
|
1390
1482
|
// A pub-sub object that can be used to decouple various parts
|
1391
1483
|
// of an application through event-driven architecture.
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
constructor: function(options){
|
1396
|
-
Marionette.EventBinder.apply(this, arguments);
|
1397
|
-
_.extend(this, options);
|
1398
|
-
},
|
1399
|
-
|
1400
|
-
// Override the `bindTo` method to ensure that the event aggregator
|
1401
|
-
// is used as the event binding storage
|
1402
|
-
bindTo: function(eventName, callback, context){
|
1403
|
-
return Marionette.EventBinder.prototype.bindTo.call(this, this, eventName, callback, context);
|
1404
|
-
}
|
1405
|
-
});
|
1406
|
-
|
1407
|
-
// Copy the basic Backbone.Events on to the event aggregator
|
1408
|
-
_.extend(Marionette.EventAggregator.prototype, Backbone.Events);
|
1409
|
-
|
1410
|
-
// Copy the `extend` function used by Backbone's classes
|
1411
|
-
Marionette.EventAggregator.extend = Backbone.View.extend;
|
1412
|
-
|
1413
|
-
|
1414
|
-
// Helpers
|
1415
|
-
// -------
|
1416
|
-
|
1417
|
-
// For slicing `arguments` in functions
|
1418
|
-
var slice = Array.prototype.slice;
|
1484
|
+
//
|
1485
|
+
// https://github.com/marionettejs/backbone.wreqr
|
1486
|
+
Marionette.EventAggregator = Backbone.Wreqr.EventAggregator;
|
1419
1487
|
|
1420
1488
|
|
1421
1489
|
return Marionette;
|
1422
|
-
})(Backbone, _, window.jQuery || window.Zepto || window.ender);
|
1490
|
+
})(Backbone, _, $ || window.jQuery || window.Zepto || window.ender);
|
metadata
CHANGED
@@ -1,81 +1,65 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: marionette-rails
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 10
|
8
|
-
- 2
|
9
|
-
version: 0.10.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.beta1
|
5
|
+
prerelease: 6
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Godfrey Chan
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2013-02-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: rails
|
22
|
-
|
23
|
-
|
24
|
-
requirements:
|
25
|
-
- -
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
segments:
|
28
|
-
- 3
|
29
|
-
- 1
|
30
|
-
- 0
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
31
21
|
version: 3.1.0
|
32
22
|
type: :runtime
|
33
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.1.0
|
34
30
|
description: Vendors Backbone.Marionette for use with asset pipeline.
|
35
|
-
email:
|
31
|
+
email:
|
36
32
|
- godfreykfc@gmail.com
|
37
33
|
executables: []
|
38
|
-
|
39
34
|
extensions: []
|
40
|
-
|
41
35
|
extra_rdoc_files: []
|
42
|
-
|
43
|
-
files:
|
36
|
+
files:
|
44
37
|
- lib/marionette-rails.rb
|
45
38
|
- vendor/assets/javascripts/backbone.marionette.js
|
46
39
|
- LICENSE
|
47
40
|
- README.md
|
48
|
-
has_rdoc: true
|
49
41
|
homepage: https://github.com/chancancode/marionette-rails
|
50
42
|
licenses: []
|
51
|
-
|
52
43
|
post_install_message:
|
53
44
|
rdoc_options: []
|
54
|
-
|
55
|
-
require_paths:
|
45
|
+
require_paths:
|
56
46
|
- lib
|
57
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
requirements:
|
66
|
-
- -
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
segments:
|
69
|
-
- 1
|
70
|
-
- 3
|
71
|
-
- 6
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
72
58
|
version: 1.3.6
|
73
59
|
requirements: []
|
74
|
-
|
75
60
|
rubyforge_project:
|
76
|
-
rubygems_version: 1.
|
61
|
+
rubygems_version: 1.8.23
|
77
62
|
signing_key:
|
78
63
|
specification_version: 3
|
79
64
|
summary: Backbone.Marionette for Rails
|
80
65
|
test_files: []
|
81
|
-
|