backbone-marionette-rails 1.0.0.6 → 1.0.1
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.
- checksums.yaml +7 -0
- data/lib/backbone-marionette-rails/version.rb +1 -1
- data/vendor/assets/javascripts/backbone.marionette.js +623 -370
- metadata +7 -9
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0945d593536da471a9ef33e4d2497f62a788e856
|
4
|
+
data.tar.gz: c4764defcd4105080f613a12095165f426cbe4f8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: af35db2132767695a9a5df6d5d8321f1298ad73e829c17f2077f936653ea43c9bb479d283c6c5519522a96236e7c68807a042c10176d8866ded40e2b5d555d31
|
7
|
+
data.tar.gz: e1b7bbb931458a0e760c279ea9140b9e90d2fad27f7b58ebd8325a24e4b8bc9bdbfa621e4befdb8428e74fb39051ea610cef8671dece8adccb35f5ccff563539
|
@@ -1,7 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
// MarionetteJS (Backbone.Marionette)
|
2
|
+
// ----------------------------------
|
3
|
+
// v1.0.1
|
4
|
+
//
|
5
|
+
// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
|
6
|
+
// Distributed under MIT license
|
7
|
+
//
|
8
|
+
// http://marionettejs.com
|
9
|
+
|
5
10
|
|
6
11
|
|
7
12
|
/*!
|
@@ -12,7 +17,6 @@
|
|
12
17
|
* https://github.com/marionettejs/backbone.wreqr/
|
13
18
|
*/
|
14
19
|
|
15
|
-
|
16
20
|
// Backbone.BabySitter, v0.0.4
|
17
21
|
// Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
|
18
22
|
// Distributed under MIT license
|
@@ -207,147 +211,297 @@ Backbone.ChildViewContainer = (function(Backbone, _){
|
|
207
211
|
return Container;
|
208
212
|
})(Backbone, _);
|
209
213
|
|
210
|
-
// Backbone.Wreqr
|
214
|
+
// Backbone.Wreqr (Backbone.Marionette)
|
215
|
+
// ----------------------------------
|
216
|
+
// v0.2.0
|
217
|
+
//
|
211
218
|
// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
|
212
219
|
// Distributed under MIT license
|
220
|
+
//
|
213
221
|
// http://github.com/marionettejs/backbone.wreqr
|
222
|
+
|
223
|
+
|
214
224
|
Backbone.Wreqr = (function(Backbone, Marionette, _){
|
215
225
|
"use strict";
|
216
226
|
var Wreqr = {};
|
217
227
|
|
218
228
|
// Handlers
|
219
|
-
|
220
|
-
|
229
|
+
// --------
|
230
|
+
// A registry of functions to call, given a name
|
231
|
+
|
232
|
+
Wreqr.Handlers = (function(Backbone, _){
|
233
|
+
"use strict";
|
221
234
|
|
222
|
-
|
223
|
-
|
235
|
+
// Constructor
|
236
|
+
// -----------
|
237
|
+
|
238
|
+
var Handlers = function(options){
|
239
|
+
this.options = options;
|
240
|
+
this._wreqrHandlers = {};
|
224
241
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
};
|
246
|
-
|
247
|
-
this._handlers[name] = config;
|
248
|
-
},
|
249
|
-
|
250
|
-
// Get the currently registered handler for
|
251
|
-
// the specified name. Throws an exception if
|
252
|
-
// no handler is found.
|
253
|
-
getHandler: function(name){
|
254
|
-
var config = this._handlers[name];
|
255
|
-
|
256
|
-
if (!config){
|
257
|
-
throw new Error("Handler not found for '" + name + "'");
|
242
|
+
if (_.isFunction(this.initialize)){
|
243
|
+
this.initialize(options);
|
244
|
+
}
|
245
|
+
};
|
246
|
+
|
247
|
+
Handlers.extend = Backbone.Model.extend;
|
248
|
+
|
249
|
+
// Instance Members
|
250
|
+
// ----------------
|
251
|
+
|
252
|
+
_.extend(Handlers.prototype, Backbone.Events, {
|
253
|
+
|
254
|
+
// Add multiple handlers using an object literal configuration
|
255
|
+
setHandlers: function(handlers){
|
256
|
+
_.each(handlers, function(handler, name){
|
257
|
+
var context = null;
|
258
|
+
|
259
|
+
if (_.isObject(handler) && !_.isFunction(handler)){
|
260
|
+
context = handler.context;
|
261
|
+
handler = handler.callback;
|
258
262
|
}
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
+
|
264
|
+
this.setHandler(name, handler, context);
|
265
|
+
}, this);
|
266
|
+
},
|
267
|
+
|
268
|
+
// Add a handler for the given name, with an
|
269
|
+
// optional context to run the handler within
|
270
|
+
setHandler: function(name, handler, context){
|
271
|
+
var config = {
|
272
|
+
callback: handler,
|
273
|
+
context: context
|
274
|
+
};
|
275
|
+
|
276
|
+
this._wreqrHandlers[name] = config;
|
277
|
+
|
278
|
+
this.trigger("handler:add", name, handler, context);
|
279
|
+
},
|
280
|
+
|
281
|
+
// Determine whether or not a handler is registered
|
282
|
+
hasHandler: function(name){
|
283
|
+
return !! this._wreqrHandlers[name];
|
284
|
+
},
|
285
|
+
|
286
|
+
// Get the currently registered handler for
|
287
|
+
// the specified name. Throws an exception if
|
288
|
+
// no handler is found.
|
289
|
+
getHandler: function(name){
|
290
|
+
var config = this._wreqrHandlers[name];
|
291
|
+
|
292
|
+
if (!config){
|
293
|
+
throw new Error("Handler not found for '" + name + "'");
|
294
|
+
}
|
295
|
+
|
296
|
+
return function(){
|
297
|
+
var args = Array.prototype.slice.apply(arguments);
|
298
|
+
return config.callback.apply(config.context, args);
|
299
|
+
};
|
300
|
+
},
|
301
|
+
|
302
|
+
// Remove a handler for the specified name
|
303
|
+
removeHandler: function(name){
|
304
|
+
delete this._wreqrHandlers[name];
|
305
|
+
},
|
306
|
+
|
307
|
+
// Remove all handlers from this registry
|
308
|
+
removeAllHandlers: function(){
|
309
|
+
this._wreqrHandlers = {};
|
310
|
+
}
|
311
|
+
});
|
312
|
+
|
313
|
+
return Handlers;
|
314
|
+
})(Backbone, _);
|
315
|
+
|
316
|
+
// Wreqr.CommandStorage
|
317
|
+
// --------------------
|
318
|
+
//
|
319
|
+
// Store and retrieve commands for execution.
|
320
|
+
Wreqr.CommandStorage = (function(){
|
321
|
+
"use strict";
|
322
|
+
|
323
|
+
// Constructor function
|
324
|
+
var CommandStorage = function(options){
|
325
|
+
this.options = options;
|
326
|
+
this._commands = {};
|
327
|
+
|
328
|
+
if (_.isFunction(this.initialize)){
|
329
|
+
this.initialize(options);
|
330
|
+
}
|
331
|
+
};
|
332
|
+
|
333
|
+
// Instance methods
|
334
|
+
_.extend(CommandStorage.prototype, Backbone.Events, {
|
335
|
+
|
336
|
+
// Get an object literal by command name, that contains
|
337
|
+
// the `commandName` and the `instances` of all commands
|
338
|
+
// represented as an array of arguments to process
|
339
|
+
getCommands: function(commandName){
|
340
|
+
var commands = this._commands[commandName];
|
341
|
+
|
342
|
+
// we don't have it, so add it
|
343
|
+
if (!commands){
|
344
|
+
|
345
|
+
// build the configuration
|
346
|
+
commands = {
|
347
|
+
command: commandName,
|
348
|
+
instances: []
|
263
349
|
};
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
removeHandler: function(name){
|
268
|
-
delete this._handlers[name];
|
269
|
-
},
|
270
|
-
|
271
|
-
// Remove all handlers from this registry
|
272
|
-
removeAllHandlers: function(){
|
273
|
-
this._handlers = {};
|
350
|
+
|
351
|
+
// store it
|
352
|
+
this._commands[commandName] = commands;
|
274
353
|
}
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
354
|
+
|
355
|
+
return commands;
|
356
|
+
},
|
357
|
+
|
358
|
+
// Add a command by name, to the storage and store the
|
359
|
+
// args for the command
|
360
|
+
addCommand: function(commandName, args){
|
361
|
+
var command = this.getCommands(commandName);
|
362
|
+
command.instances.push(args);
|
363
|
+
},
|
364
|
+
|
365
|
+
// Clear all commands for the given `commandName`
|
366
|
+
clearCommands: function(commandName){
|
367
|
+
var command = this.getCommands(commandName);
|
368
|
+
command.instances = [];
|
369
|
+
}
|
370
|
+
});
|
371
|
+
|
372
|
+
return CommandStorage;
|
373
|
+
})();
|
374
|
+
|
280
375
|
// Wreqr.Commands
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
376
|
+
// --------------
|
377
|
+
//
|
378
|
+
// A simple command pattern implementation. Register a command
|
379
|
+
// handler and execute it.
|
380
|
+
Wreqr.Commands = (function(Wreqr){
|
381
|
+
"use strict";
|
382
|
+
|
383
|
+
return Wreqr.Handlers.extend({
|
384
|
+
// default storage type
|
385
|
+
storageType: Wreqr.CommandStorage,
|
386
|
+
|
387
|
+
constructor: function(options){
|
388
|
+
this.options = options || {};
|
389
|
+
|
390
|
+
this._initializeStorage(this.options);
|
391
|
+
this.on("handler:add", this._executeCommands, this);
|
392
|
+
|
393
|
+
var args = Array.prototype.slice.call(arguments);
|
394
|
+
Wreqr.Handlers.prototype.constructor.apply(this, args);
|
395
|
+
},
|
396
|
+
|
397
|
+
// Execute a named command with the supplied args
|
398
|
+
execute: function(name, args){
|
399
|
+
name = arguments[0];
|
400
|
+
args = Array.prototype.slice.call(arguments, 1);
|
401
|
+
|
402
|
+
if (this.hasHandler(name)){
|
293
403
|
this.getHandler(name).apply(this, args);
|
404
|
+
} else {
|
405
|
+
this.storage.addCommand(name, args);
|
294
406
|
}
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
407
|
+
|
408
|
+
},
|
409
|
+
|
410
|
+
// Internal method to handle bulk execution of stored commands
|
411
|
+
_executeCommands: function(name, handler, context){
|
412
|
+
var command = this.storage.getCommands(name);
|
413
|
+
|
414
|
+
// loop through and execute all the stored command instances
|
415
|
+
_.each(command.instances, function(args){
|
416
|
+
handler.apply(context, args);
|
417
|
+
});
|
418
|
+
|
419
|
+
this.storage.clearCommands(name);
|
420
|
+
},
|
421
|
+
|
422
|
+
// Internal method to initialize storage either from the type's
|
423
|
+
// `storageType` or the instance `options.storageType`.
|
424
|
+
_initializeStorage: function(options){
|
425
|
+
var storage;
|
426
|
+
|
427
|
+
var StorageType = options.storageType || this.storageType;
|
428
|
+
if (_.isFunction(StorageType)){
|
429
|
+
storage = new StorageType();
|
430
|
+
} else {
|
431
|
+
storage = StorageType;
|
313
432
|
}
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
433
|
+
|
434
|
+
this.storage = storage;
|
435
|
+
}
|
436
|
+
});
|
437
|
+
|
438
|
+
})(Wreqr);
|
439
|
+
|
440
|
+
// Wreqr.RequestResponse
|
441
|
+
// ---------------------
|
442
|
+
//
|
443
|
+
// A simple request/response implementation. Register a
|
444
|
+
// request handler, and return a response from it
|
445
|
+
Wreqr.RequestResponse = (function(Wreqr){
|
446
|
+
"use strict";
|
447
|
+
|
448
|
+
return Wreqr.Handlers.extend({
|
449
|
+
request: function(){
|
450
|
+
var name = arguments[0];
|
451
|
+
var args = Array.prototype.slice.call(arguments, 1);
|
452
|
+
|
453
|
+
return this.getHandler(name).apply(this, args);
|
454
|
+
}
|
455
|
+
});
|
456
|
+
|
457
|
+
})(Wreqr);
|
458
|
+
|
318
459
|
// Event Aggregator
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
460
|
+
// ----------------
|
461
|
+
// A pub-sub object that can be used to decouple various parts
|
462
|
+
// of an application through event-driven architecture.
|
463
|
+
|
464
|
+
Wreqr.EventAggregator = (function(Backbone, _){
|
465
|
+
"use strict";
|
466
|
+
var EA = function(){};
|
467
|
+
|
468
|
+
// Copy the `extend` function used by Backbone's classes
|
469
|
+
EA.extend = Backbone.Model.extend;
|
470
|
+
|
471
|
+
// Copy the basic Backbone.Events on to the event aggregator
|
472
|
+
_.extend(EA.prototype, Backbone.Events);
|
473
|
+
|
474
|
+
return EA;
|
475
|
+
})(Backbone, _);
|
476
|
+
|
336
477
|
|
337
478
|
return Wreqr;
|
338
479
|
})(Backbone, Backbone.Marionette, _);
|
339
480
|
|
340
|
-
var Marionette = (function(Backbone, _
|
481
|
+
var Marionette = (function(global, Backbone, _){
|
341
482
|
"use strict";
|
342
483
|
|
484
|
+
// Define and export the Marionette namespace
|
343
485
|
var Marionette = {};
|
344
486
|
Backbone.Marionette = Marionette;
|
345
487
|
|
488
|
+
// Get the DOM manipulator for later use
|
489
|
+
Marionette.$ = Backbone.$;
|
490
|
+
|
346
491
|
// Helpers
|
347
492
|
// -------
|
348
493
|
|
349
494
|
// For slicing `arguments` in functions
|
350
|
-
var
|
495
|
+
var protoSlice = Array.prototype.slice;
|
496
|
+
function slice(args) {
|
497
|
+
return protoSlice.call(args);
|
498
|
+
}
|
499
|
+
|
500
|
+
function throwError(message, name) {
|
501
|
+
var error = new Error(message);
|
502
|
+
error.name = name || 'Error';
|
503
|
+
throw error;
|
504
|
+
}
|
351
505
|
|
352
506
|
// Marionette.extend
|
353
507
|
// -----------------
|
@@ -373,55 +527,6 @@ Marionette.getOption = function(target, optionName){
|
|
373
527
|
return value;
|
374
528
|
};
|
375
529
|
|
376
|
-
// Mairionette.createObject
|
377
|
-
// ------------------------
|
378
|
-
|
379
|
-
// A wrapper / shim for `Object.create`. Uses native `Object.create`
|
380
|
-
// if available, otherwise shims it in place for Marionette to use.
|
381
|
-
Marionette.createObject = (function(){
|
382
|
-
var createObject;
|
383
|
-
|
384
|
-
// Define this once, and just replace the .prototype on it as needed,
|
385
|
-
// to improve performance in older / less optimized JS engines
|
386
|
-
function F() {}
|
387
|
-
|
388
|
-
|
389
|
-
// Check for existing native / shimmed Object.create
|
390
|
-
if (typeof Object.create === "function"){
|
391
|
-
|
392
|
-
// found native/shim, so use it
|
393
|
-
createObject = Object.create;
|
394
|
-
|
395
|
-
} else {
|
396
|
-
|
397
|
-
// An implementation of the Boodman/Crockford delegation
|
398
|
-
// w/ Cornford optimization, as suggested by @unscriptable
|
399
|
-
// https://gist.github.com/3959151
|
400
|
-
|
401
|
-
// native/shim not found, so shim it ourself
|
402
|
-
createObject = function (o) {
|
403
|
-
|
404
|
-
// set the prototype of the function
|
405
|
-
// so we will get `o` as the prototype
|
406
|
-
// of the new object instance
|
407
|
-
F.prototype = o;
|
408
|
-
|
409
|
-
// create a new object that inherits from
|
410
|
-
// the `o` parameter
|
411
|
-
var child = new F();
|
412
|
-
|
413
|
-
// clean up just in case o is really large
|
414
|
-
F.prototype = null;
|
415
|
-
|
416
|
-
// send it back
|
417
|
-
return child;
|
418
|
-
};
|
419
|
-
|
420
|
-
}
|
421
|
-
|
422
|
-
return createObject;
|
423
|
-
})();
|
424
|
-
|
425
530
|
// Trigger an event and a corresponding method name. Examples:
|
426
531
|
//
|
427
532
|
// `this.triggerMethod("foo")` will trigger the "foo" event and
|
@@ -429,25 +534,35 @@ Marionette.createObject = (function(){
|
|
429
534
|
//
|
430
535
|
// `this.triggerMethod("foo:bar") will trigger the "foo:bar" event and
|
431
536
|
// call the "onFooBar" method.
|
432
|
-
Marionette.triggerMethod = function(){
|
433
|
-
|
434
|
-
|
435
|
-
var
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
methodName += capLetter + segment.slice(1);
|
537
|
+
Marionette.triggerMethod = (function(){
|
538
|
+
|
539
|
+
// split the event name on the :
|
540
|
+
var splitter = /(^|:)(\w)/gi;
|
541
|
+
|
542
|
+
// take the event section ("section1:section2:section3")
|
543
|
+
// and turn it in to uppercase name
|
544
|
+
function getEventName(match, prefix, eventName) {
|
545
|
+
return eventName.toUpperCase();
|
442
546
|
}
|
443
547
|
|
444
|
-
|
548
|
+
// actual triggerMethod name
|
549
|
+
var triggerMethod = function(event) {
|
550
|
+
// get the method name from the event name
|
551
|
+
var methodName = 'on' + event.replace(splitter, getEventName);
|
552
|
+
var method = this[methodName];
|
445
553
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
554
|
+
// trigger the event
|
555
|
+
this.trigger.apply(this, arguments);
|
556
|
+
|
557
|
+
// call the onMethodName if it exists
|
558
|
+
if (_.isFunction(method)) {
|
559
|
+
// pass all arguments, except the event name
|
560
|
+
return method.apply(this, _.tail(arguments));
|
561
|
+
}
|
562
|
+
};
|
563
|
+
|
564
|
+
return triggerMethod;
|
565
|
+
})();
|
451
566
|
|
452
567
|
// DOMRefresh
|
453
568
|
// ----------
|
@@ -498,7 +613,7 @@ Marionette.MonitorDOMRefresh = (function(){
|
|
498
613
|
// These methods are used to bind/unbind a backbone "entity" (collection/model)
|
499
614
|
// to methods on a target object.
|
500
615
|
//
|
501
|
-
// The first
|
616
|
+
// The first parameter, `target`, must have a `listenTo` method from the
|
502
617
|
// EventBinder object.
|
503
618
|
//
|
504
619
|
// The second parameter is the entity (Backbone.Model or Backbone.Collection)
|
@@ -520,7 +635,7 @@ Marionette.MonitorDOMRefresh = (function(){
|
|
520
635
|
|
521
636
|
var method = target[methodName];
|
522
637
|
if(!method) {
|
523
|
-
|
638
|
+
throwError("Method '"+ methodName +"' was configured as an event handler, but does not exist.");
|
524
639
|
}
|
525
640
|
|
526
641
|
target.listenTo(entity, evt, method, target);
|
@@ -583,7 +698,7 @@ Marionette.MonitorDOMRefresh = (function(){
|
|
583
698
|
|
584
699
|
})(Marionette);
|
585
700
|
|
586
|
-
|
701
|
+
|
587
702
|
// Callbacks
|
588
703
|
// ---------
|
589
704
|
|
@@ -591,7 +706,7 @@ Marionette.MonitorDOMRefresh = (function(){
|
|
591
706
|
// and executing them at a later point in time, using jQuery's
|
592
707
|
// `Deferred` object.
|
593
708
|
Marionette.Callbacks = function(){
|
594
|
-
this._deferred =
|
709
|
+
this._deferred = Marionette.$.Deferred();
|
595
710
|
this._callbacks = [];
|
596
711
|
};
|
597
712
|
|
@@ -619,13 +734,13 @@ _.extend(Marionette.Callbacks.prototype, {
|
|
619
734
|
// Resets the list of callbacks to be run, allowing the same list
|
620
735
|
// to be run multiple times - whenever the `run` method is called.
|
621
736
|
reset: function(){
|
622
|
-
var that = this;
|
623
737
|
var callbacks = this._callbacks;
|
624
|
-
this._deferred =
|
738
|
+
this._deferred = Marionette.$.Deferred();
|
625
739
|
this._callbacks = [];
|
740
|
+
|
626
741
|
_.each(callbacks, function(cb){
|
627
|
-
|
628
|
-
});
|
742
|
+
this.add(cb.cb, cb.ctx);
|
743
|
+
}, this);
|
629
744
|
}
|
630
745
|
});
|
631
746
|
|
@@ -739,12 +854,28 @@ _.extend(Marionette.Region, {
|
|
739
854
|
}
|
740
855
|
|
741
856
|
// build the region instance
|
742
|
-
|
743
|
-
var regionManager = new RegionType({
|
857
|
+
var region = new RegionType({
|
744
858
|
el: selector
|
745
859
|
});
|
746
860
|
|
747
|
-
|
861
|
+
// override the `getEl` function if we have a parentEl
|
862
|
+
// this must be overridden to ensure the selector is found
|
863
|
+
// on the first use of the region. if we try to assign the
|
864
|
+
// region's `el` to `parentEl.find(selector)` in the object
|
865
|
+
// literal to build the region, the element will not be
|
866
|
+
// guaranteed to be in the DOM already, and will cause problems
|
867
|
+
if (regionConfig.parentEl){
|
868
|
+
|
869
|
+
region.getEl = function(selector) {
|
870
|
+
var parentEl = regionConfig.parentEl;
|
871
|
+
if (_.isFunction(parentEl)){
|
872
|
+
parentEl = parentEl();
|
873
|
+
}
|
874
|
+
return parentEl.find(selector);
|
875
|
+
};
|
876
|
+
}
|
877
|
+
|
878
|
+
return region;
|
748
879
|
}
|
749
880
|
|
750
881
|
});
|
@@ -762,10 +893,14 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
|
|
762
893
|
show: function(view){
|
763
894
|
|
764
895
|
this.ensureEl();
|
765
|
-
this.close();
|
766
896
|
|
767
|
-
view.
|
768
|
-
|
897
|
+
if (view !== this.currentView) {
|
898
|
+
this.close();
|
899
|
+
view.render();
|
900
|
+
this.open(view);
|
901
|
+
} else {
|
902
|
+
view.render();
|
903
|
+
}
|
769
904
|
|
770
905
|
Marionette.triggerMethod.call(view, "show");
|
771
906
|
Marionette.triggerMethod.call(this, "show", view);
|
@@ -782,7 +917,7 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
|
|
782
917
|
// Override this method to change how the region finds the
|
783
918
|
// DOM element that it manages. Return a jQuery selector object.
|
784
919
|
getEl: function(selector){
|
785
|
-
return
|
920
|
+
return Marionette.$(selector);
|
786
921
|
},
|
787
922
|
|
788
923
|
// Override this method to change how the new view is
|
@@ -797,7 +932,10 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
|
|
797
932
|
var view = this.currentView;
|
798
933
|
if (!view || view.isClosed){ return; }
|
799
934
|
|
935
|
+
// call 'close' or 'remove', depending on which is found
|
800
936
|
if (view.close) { view.close(); }
|
937
|
+
else if (view.remove) { view.remove(); }
|
938
|
+
|
801
939
|
Marionette.triggerMethod.call(this, "close");
|
802
940
|
|
803
941
|
delete this.currentView;
|
@@ -824,6 +962,133 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
|
|
824
962
|
// Copy the `extend` function used by Backbone's classes
|
825
963
|
Marionette.Region.extend = Marionette.extend;
|
826
964
|
|
965
|
+
// Marionette.RegionManager
|
966
|
+
// ------------------------
|
967
|
+
//
|
968
|
+
// Manage one or more related `Marionette.Region` objects.
|
969
|
+
Marionette.RegionManager = (function(Marionette){
|
970
|
+
|
971
|
+
var RegionManager = Marionette.Controller.extend({
|
972
|
+
constructor: function(options){
|
973
|
+
this._regions = {};
|
974
|
+
Marionette.Controller.prototype.constructor.call(this, options);
|
975
|
+
},
|
976
|
+
|
977
|
+
// Add multiple regions using an object literal, where
|
978
|
+
// each key becomes the region name, and each value is
|
979
|
+
// the region definition.
|
980
|
+
addRegions: function(regionDefinitions, defaults){
|
981
|
+
var regions = {};
|
982
|
+
|
983
|
+
_.each(regionDefinitions, function(definition, name){
|
984
|
+
if (typeof definition === "string"){
|
985
|
+
definition = { selector: definition };
|
986
|
+
}
|
987
|
+
|
988
|
+
if (definition.selector){
|
989
|
+
definition = _.defaults({}, definition, defaults);
|
990
|
+
}
|
991
|
+
|
992
|
+
var region = this.addRegion(name, definition);
|
993
|
+
regions[name] = region;
|
994
|
+
}, this);
|
995
|
+
|
996
|
+
return regions;
|
997
|
+
},
|
998
|
+
|
999
|
+
// Add an individual region to the region manager,
|
1000
|
+
// and return the region instance
|
1001
|
+
addRegion: function(name, definition){
|
1002
|
+
var region;
|
1003
|
+
|
1004
|
+
var isObject = _.isObject(definition);
|
1005
|
+
var isString = _.isString(definition);
|
1006
|
+
var hasSelector = !!definition.selector;
|
1007
|
+
|
1008
|
+
if (isString || (isObject && hasSelector)){
|
1009
|
+
region = Marionette.Region.buildRegion(definition, Marionette.Region);
|
1010
|
+
} else if (_.isFunction(definition)){
|
1011
|
+
region = Marionette.Region.buildRegion(definition, Marionette.Region);
|
1012
|
+
} else {
|
1013
|
+
region = definition;
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
this._store(name, region);
|
1017
|
+
this.triggerMethod("region:add", name, region);
|
1018
|
+
return region;
|
1019
|
+
},
|
1020
|
+
|
1021
|
+
// Get a region by name
|
1022
|
+
get: function(name){
|
1023
|
+
return this._regions[name];
|
1024
|
+
},
|
1025
|
+
|
1026
|
+
// Remove a region by name
|
1027
|
+
removeRegion: function(name){
|
1028
|
+
var region = this._regions[name];
|
1029
|
+
this._remove(name, region);
|
1030
|
+
},
|
1031
|
+
|
1032
|
+
// Close all regions in the region manager, and
|
1033
|
+
// remove them
|
1034
|
+
removeRegions: function(){
|
1035
|
+
_.each(this._regions, function(region, name){
|
1036
|
+
this._remove(name, region);
|
1037
|
+
}, this);
|
1038
|
+
},
|
1039
|
+
|
1040
|
+
// Close all regions in the region manager, but
|
1041
|
+
// leave them attached
|
1042
|
+
closeRegions: function(){
|
1043
|
+
_.each(this._regions, function(region, name){
|
1044
|
+
region.close();
|
1045
|
+
}, this);
|
1046
|
+
},
|
1047
|
+
|
1048
|
+
// Close all regions and shut down the region
|
1049
|
+
// manager entirely
|
1050
|
+
close: function(){
|
1051
|
+
this.removeRegions();
|
1052
|
+
var args = Array.prototype.slice.call(arguments);
|
1053
|
+
Marionette.Controller.prototype.close.apply(this, args);
|
1054
|
+
},
|
1055
|
+
|
1056
|
+
// internal method to store regions
|
1057
|
+
_store: function(name, region){
|
1058
|
+
this._regions[name] = region;
|
1059
|
+
this.length = _.size(this._regions);
|
1060
|
+
},
|
1061
|
+
|
1062
|
+
// internal method to remove a region
|
1063
|
+
_remove: function(name, region){
|
1064
|
+
region.close();
|
1065
|
+
delete this._regions[name];
|
1066
|
+
this.triggerMethod("region:remove", name, region);
|
1067
|
+
}
|
1068
|
+
|
1069
|
+
});
|
1070
|
+
|
1071
|
+
// Borrowing this code from Backbone.Collection:
|
1072
|
+
// http://backbonejs.org/docs/backbone.html#section-106
|
1073
|
+
//
|
1074
|
+
// Mix in methods from Underscore, for iteration, and other
|
1075
|
+
// collection related features.
|
1076
|
+
var methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',
|
1077
|
+
'select', 'reject', 'every', 'all', 'some', 'any', 'include',
|
1078
|
+
'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',
|
1079
|
+
'last', 'without', 'isEmpty', 'pluck'];
|
1080
|
+
|
1081
|
+
_.each(methods, function(method) {
|
1082
|
+
RegionManager.prototype[method] = function() {
|
1083
|
+
var regions = _.values(this._regions);
|
1084
|
+
var args = [regions].concat(_.toArray(arguments));
|
1085
|
+
return _[method].apply(_, args);
|
1086
|
+
};
|
1087
|
+
});
|
1088
|
+
|
1089
|
+
return RegionManager;
|
1090
|
+
})(Marionette);
|
1091
|
+
|
827
1092
|
|
828
1093
|
// Template Cache
|
829
1094
|
// --------------
|
@@ -844,7 +1109,6 @@ _.extend(Marionette.TemplateCache, {
|
|
844
1109
|
// retrieves the cached version, or loads it
|
845
1110
|
// from the DOM.
|
846
1111
|
get: function(templateId){
|
847
|
-
var that = this;
|
848
1112
|
var cachedTemplate = this.templateCaches[templateId];
|
849
1113
|
|
850
1114
|
if (!cachedTemplate){
|
@@ -864,7 +1128,7 @@ _.extend(Marionette.TemplateCache, {
|
|
864
1128
|
// `clear("#t1", "#t2", "...")`
|
865
1129
|
clear: function(){
|
866
1130
|
var i;
|
867
|
-
var args =
|
1131
|
+
var args = slice(arguments);
|
868
1132
|
var length = args.length;
|
869
1133
|
|
870
1134
|
if (length > 0){
|
@@ -884,8 +1148,6 @@ _.extend(Marionette.TemplateCache.prototype, {
|
|
884
1148
|
|
885
1149
|
// Internal method to load the template
|
886
1150
|
load: function(){
|
887
|
-
var that = this;
|
888
|
-
|
889
1151
|
// Guard clause to prevent loading this template more than once
|
890
1152
|
if (this.compiledTemplate){
|
891
1153
|
return this.compiledTemplate;
|
@@ -904,13 +1166,10 @@ _.extend(Marionette.TemplateCache.prototype, {
|
|
904
1166
|
// using a template-loader plugin as described here:
|
905
1167
|
// https://github.com/marionettejs/backbone.marionette/wiki/Using-marionette-with-requirejs
|
906
1168
|
loadTemplate: function(templateId){
|
907
|
-
var template =
|
1169
|
+
var template = Marionette.$(templateId).html();
|
908
1170
|
|
909
1171
|
if (!template || template.length === 0){
|
910
|
-
|
911
|
-
var err = new Error(msg);
|
912
|
-
err.name = "NoTemplateError";
|
913
|
-
throw err;
|
1172
|
+
throwError("Could not find template: '" + templateId + "'", "NoTemplateError");
|
914
1173
|
}
|
915
1174
|
|
916
1175
|
return template;
|
@@ -939,8 +1198,7 @@ Marionette.Renderer = {
|
|
939
1198
|
// custom rendering and template handling for all of Marionette.
|
940
1199
|
render: function(template, data){
|
941
1200
|
var templateFunc = typeof template === 'function' ? template : Marionette.TemplateCache.get(template);
|
942
|
-
|
943
|
-
return html;
|
1201
|
+
return templateFunc(data);
|
944
1202
|
}
|
945
1203
|
};
|
946
1204
|
|
@@ -993,7 +1251,6 @@ Marionette.View = Backbone.View.extend({
|
|
993
1251
|
configureTriggers: function(){
|
994
1252
|
if (!this.triggers) { return; }
|
995
1253
|
|
996
|
-
var that = this;
|
997
1254
|
var triggerEvents = {};
|
998
1255
|
|
999
1256
|
// Allow `triggers` to be configured as a function
|
@@ -1010,7 +1267,7 @@ Marionette.View = Backbone.View.extend({
|
|
1010
1267
|
if (e && e.preventDefault){ e.preventDefault(); }
|
1011
1268
|
if (e && e.stopPropagation){ e.stopPropagation(); }
|
1012
1269
|
|
1013
|
-
//
|
1270
|
+
// build the args for the event
|
1014
1271
|
var args = {
|
1015
1272
|
view: this,
|
1016
1273
|
model: this.model,
|
@@ -1018,10 +1275,10 @@ Marionette.View = Backbone.View.extend({
|
|
1018
1275
|
};
|
1019
1276
|
|
1020
1277
|
// trigger the event
|
1021
|
-
|
1278
|
+
this.triggerMethod(value, args);
|
1022
1279
|
};
|
1023
1280
|
|
1024
|
-
});
|
1281
|
+
}, this);
|
1025
1282
|
|
1026
1283
|
return triggerEvents;
|
1027
1284
|
},
|
@@ -1073,6 +1330,9 @@ Marionette.View = Backbone.View.extend({
|
|
1073
1330
|
return;
|
1074
1331
|
}
|
1075
1332
|
|
1333
|
+
// unbind UI elements
|
1334
|
+
this.unbindUIElements();
|
1335
|
+
|
1076
1336
|
// mark as closed before doing the actual close, to
|
1077
1337
|
// prevent infinite loops within "close" event handlers
|
1078
1338
|
// that are trying to close other views
|
@@ -1087,20 +1347,37 @@ Marionette.View = Backbone.View.extend({
|
|
1087
1347
|
bindUIElements: function(){
|
1088
1348
|
if (!this.ui) { return; }
|
1089
1349
|
|
1090
|
-
|
1091
|
-
|
1092
|
-
if (!this.
|
1093
|
-
|
1094
|
-
// will be overridden with jQuery selectors.
|
1095
|
-
this.uiBindings = _.result(this, "ui");
|
1350
|
+
// store the ui hash in _uiBindings so they can be reset later
|
1351
|
+
// and so re-rendering the view will be able to find the bindings
|
1352
|
+
if (!this._uiBindings){
|
1353
|
+
this._uiBindings = this.ui;
|
1096
1354
|
}
|
1097
1355
|
|
1098
|
-
//
|
1356
|
+
// get the bindings result, as a function or otherwise
|
1357
|
+
var bindings = _.result(this, "_uiBindings");
|
1358
|
+
|
1359
|
+
// empty the ui so we don't have anything to start with
|
1099
1360
|
this.ui = {};
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1361
|
+
|
1362
|
+
// bind each of the selectors
|
1363
|
+
_.each(_.keys(bindings), function(key) {
|
1364
|
+
var selector = bindings[key];
|
1365
|
+
this.ui[key] = this.$(selector);
|
1366
|
+
}, this);
|
1367
|
+
},
|
1368
|
+
|
1369
|
+
// This method unbinds the elements specified in the "ui" hash
|
1370
|
+
unbindUIElements: function(){
|
1371
|
+
if (!this.ui){ return; }
|
1372
|
+
|
1373
|
+
// delete all of the existing ui bindings
|
1374
|
+
_.each(this.ui, function($el, name){
|
1375
|
+
delete this.ui[name];
|
1376
|
+
}, this);
|
1377
|
+
|
1378
|
+
// reset the ui element to the original bindings configuration
|
1379
|
+
this.ui = this._uiBindings;
|
1380
|
+
delete this._uiBindings;
|
1104
1381
|
}
|
1105
1382
|
});
|
1106
1383
|
|
@@ -1112,8 +1389,7 @@ Marionette.View = Backbone.View.extend({
|
|
1112
1389
|
// and calling several methods on extended views, such as `onRender`.
|
1113
1390
|
Marionette.ItemView = Marionette.View.extend({
|
1114
1391
|
constructor: function(){
|
1115
|
-
|
1116
|
-
Marionette.View.prototype.constructor.apply(this, args);
|
1392
|
+
Marionette.View.prototype.constructor.apply(this, slice(arguments));
|
1117
1393
|
},
|
1118
1394
|
|
1119
1395
|
// Serialize the model or collection for the view. If a model is
|
@@ -1167,8 +1443,7 @@ Marionette.ItemView = Marionette.View.extend({
|
|
1167
1443
|
|
1168
1444
|
this.triggerMethod('item:before:close');
|
1169
1445
|
|
1170
|
-
|
1171
|
-
Marionette.View.prototype.close.apply(this, args);
|
1446
|
+
Marionette.View.prototype.close.apply(this, slice(arguments));
|
1172
1447
|
|
1173
1448
|
this.triggerMethod('item:closed');
|
1174
1449
|
}
|
@@ -1188,8 +1463,7 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1188
1463
|
constructor: function(options){
|
1189
1464
|
this._initChildViewStorage();
|
1190
1465
|
|
1191
|
-
|
1192
|
-
Marionette.View.prototype.constructor.apply(this, args);
|
1466
|
+
Marionette.View.prototype.constructor.apply(this, slice(arguments));
|
1193
1467
|
|
1194
1468
|
this._initialEvents();
|
1195
1469
|
},
|
@@ -1263,12 +1537,11 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1263
1537
|
// Internal method to loop through each item in the
|
1264
1538
|
// collection view and show it
|
1265
1539
|
showCollection: function(){
|
1266
|
-
var that = this;
|
1267
1540
|
var ItemView;
|
1268
1541
|
this.collection.each(function(item, index){
|
1269
|
-
ItemView =
|
1270
|
-
|
1271
|
-
});
|
1542
|
+
ItemView = this.getItemView(item);
|
1543
|
+
this.addItemView(item, ItemView, index);
|
1544
|
+
}, this);
|
1272
1545
|
},
|
1273
1546
|
|
1274
1547
|
// Internal method to show an empty view in place of
|
@@ -1301,9 +1574,7 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1301
1574
|
var itemView = Marionette.getOption(this, "itemView");
|
1302
1575
|
|
1303
1576
|
if (!itemView){
|
1304
|
-
|
1305
|
-
err.name = "NoItemViewError";
|
1306
|
-
throw err;
|
1577
|
+
throwError("An `itemView` must be specified", "NoItemViewError");
|
1307
1578
|
}
|
1308
1579
|
|
1309
1580
|
return itemView;
|
@@ -1312,12 +1583,10 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1312
1583
|
// Render the child item's view and add it to the
|
1313
1584
|
// HTML for the collection view.
|
1314
1585
|
addItemView: function(item, ItemView, index){
|
1315
|
-
var that = this;
|
1316
|
-
|
1317
1586
|
// get the itemViewOptions if any were specified
|
1318
1587
|
var itemViewOptions = Marionette.getOption(this, "itemViewOptions");
|
1319
1588
|
if (_.isFunction(itemViewOptions)){
|
1320
|
-
itemViewOptions = itemViewOptions.call(this, item);
|
1589
|
+
itemViewOptions = itemViewOptions.call(this, item, index);
|
1321
1590
|
}
|
1322
1591
|
|
1323
1592
|
// build the view
|
@@ -1354,7 +1623,7 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1354
1623
|
// Forward all child item view events through the parent,
|
1355
1624
|
// prepending "itemview:" to the event name
|
1356
1625
|
this.listenTo(view, "all", function(){
|
1357
|
-
var args = slice
|
1626
|
+
var args = slice(arguments);
|
1358
1627
|
args[0] = prefix + ":" + args[0];
|
1359
1628
|
args.splice(1, 0, view);
|
1360
1629
|
|
@@ -1371,8 +1640,7 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1371
1640
|
// Build an `itemView` for every model in the collection.
|
1372
1641
|
buildItemView: function(item, ItemViewType, itemViewOptions){
|
1373
1642
|
var options = _.extend({model: item}, itemViewOptions);
|
1374
|
-
|
1375
|
-
return view;
|
1643
|
+
return new ItemViewType(options);
|
1376
1644
|
},
|
1377
1645
|
|
1378
1646
|
// get the child view by item it holds, and remove it
|
@@ -1390,9 +1658,9 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1390
1658
|
if (view){
|
1391
1659
|
this.stopListening(view);
|
1392
1660
|
|
1393
|
-
|
1394
|
-
|
1395
|
-
}
|
1661
|
+
// call 'close' or 'remove', depending on which is found
|
1662
|
+
if (view.close) { view.close(); }
|
1663
|
+
else if (view.remove) { view.remove(); }
|
1396
1664
|
|
1397
1665
|
this.children.remove(view);
|
1398
1666
|
}
|
@@ -1431,8 +1699,7 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1431
1699
|
this.closeChildren();
|
1432
1700
|
this.triggerMethod("collection:closed");
|
1433
1701
|
|
1434
|
-
|
1435
|
-
Marionette.View.prototype.close.apply(this, args);
|
1702
|
+
Marionette.View.prototype.close.apply(this, slice(arguments));
|
1436
1703
|
},
|
1437
1704
|
|
1438
1705
|
// Close the child views that this collection view
|
@@ -1454,8 +1721,7 @@ Marionette.CollectionView = Marionette.View.extend({
|
|
1454
1721
|
// an item view as `modelView`, for the top leaf
|
1455
1722
|
Marionette.CompositeView = Marionette.CollectionView.extend({
|
1456
1723
|
constructor: function(options){
|
1457
|
-
|
1458
|
-
Marionette.CollectionView.apply(this, args);
|
1724
|
+
Marionette.CollectionView.apply(this, slice(arguments));
|
1459
1725
|
|
1460
1726
|
this.itemView = this.getItemView();
|
1461
1727
|
},
|
@@ -1479,9 +1745,7 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
|
|
1479
1745
|
var itemView = Marionette.getOption(this, "itemView") || this.constructor;
|
1480
1746
|
|
1481
1747
|
if (!itemView){
|
1482
|
-
|
1483
|
-
err.name = "NoItemViewError";
|
1484
|
-
throw err;
|
1748
|
+
throwError("An `itemView` must be specified", "NoItemViewError");
|
1485
1749
|
}
|
1486
1750
|
|
1487
1751
|
return itemView;
|
@@ -1504,6 +1768,7 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
|
|
1504
1768
|
// this again will tell the model's view to re-render itself
|
1505
1769
|
// but the collection will not re-render.
|
1506
1770
|
render: function(){
|
1771
|
+
this.isRendered = true;
|
1507
1772
|
this.isClosed = false;
|
1508
1773
|
this.resetItemViewContainer();
|
1509
1774
|
|
@@ -1524,15 +1789,10 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
|
|
1524
1789
|
},
|
1525
1790
|
|
1526
1791
|
_renderChildren: function(){
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
// Render the collection for the composite view
|
1532
|
-
renderCollection: function(){
|
1533
|
-
var args = Array.prototype.slice.apply(arguments);
|
1534
|
-
Marionette.CollectionView.prototype.render.apply(this, args);
|
1535
|
-
|
1792
|
+
if (this.isRendered){
|
1793
|
+
Marionette.CollectionView.prototype._renderChildren.call(this);
|
1794
|
+
this.triggerMethod("composite:collection:rendered");
|
1795
|
+
}
|
1536
1796
|
},
|
1537
1797
|
|
1538
1798
|
// Render an individual model, if we have one, as
|
@@ -1569,9 +1829,7 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
|
|
1569
1829
|
var selector = _.result(containerView, "itemViewContainer");
|
1570
1830
|
container = containerView.$(selector);
|
1571
1831
|
if (container.length <= 0) {
|
1572
|
-
|
1573
|
-
err.name = "ItemViewContainerMissingError";
|
1574
|
-
throw err;
|
1832
|
+
throwError("The specified `itemViewContainer` was not found: " + containerView.itemViewContainer, "ItemViewContainerMissingError");
|
1575
1833
|
}
|
1576
1834
|
|
1577
1835
|
} else {
|
@@ -1603,14 +1861,15 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
|
|
1603
1861
|
Marionette.Layout = Marionette.ItemView.extend({
|
1604
1862
|
regionType: Marionette.Region,
|
1605
1863
|
|
1606
|
-
// Ensure the regions are
|
1864
|
+
// Ensure the regions are available when the `initialize` method
|
1607
1865
|
// is called.
|
1608
|
-
constructor: function () {
|
1609
|
-
|
1610
|
-
this.initializeRegions();
|
1866
|
+
constructor: function (options) {
|
1867
|
+
options = options || {};
|
1611
1868
|
|
1612
|
-
|
1613
|
-
|
1869
|
+
this._firstRender = true;
|
1870
|
+
this._initializeRegions(options);
|
1871
|
+
|
1872
|
+
Marionette.ItemView.call(this, options);
|
1614
1873
|
},
|
1615
1874
|
|
1616
1875
|
// Layout's render will use the existing region objects the
|
@@ -1623,11 +1882,14 @@ Marionette.Layout = Marionette.ItemView.extend({
|
|
1623
1882
|
// if this is the first render, don't do anything to
|
1624
1883
|
// reset the regions
|
1625
1884
|
this._firstRender = false;
|
1885
|
+
} else if (this.isClosed){
|
1886
|
+
// a previously closed layout means we need to
|
1887
|
+
// completely re-initialize the regions
|
1888
|
+
this._initializeRegions();
|
1626
1889
|
} else {
|
1627
1890
|
// If this is not the first render call, then we need to
|
1628
1891
|
// re-initializing the `el` for each region
|
1629
|
-
this.
|
1630
|
-
this.reInitializeRegions();
|
1892
|
+
this._reInitializeRegions();
|
1631
1893
|
}
|
1632
1894
|
|
1633
1895
|
var args = Array.prototype.slice.apply(arguments);
|
@@ -1639,75 +1901,82 @@ Marionette.Layout = Marionette.ItemView.extend({
|
|
1639
1901
|
// Handle closing regions, and then close the view itself.
|
1640
1902
|
close: function () {
|
1641
1903
|
if (this.isClosed){ return; }
|
1642
|
-
|
1643
|
-
this.closeRegions();
|
1644
|
-
this.destroyRegions();
|
1645
|
-
|
1904
|
+
this.regionManager.close();
|
1646
1905
|
var args = Array.prototype.slice.apply(arguments);
|
1647
1906
|
Marionette.ItemView.prototype.close.apply(this, args);
|
1648
1907
|
},
|
1649
1908
|
|
1650
|
-
//
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1656
|
-
initializeRegions: function () {
|
1657
|
-
if (!this.regionManagers){
|
1658
|
-
this.regionManagers = {};
|
1659
|
-
}
|
1909
|
+
// Add a single region, by name, to the layout
|
1910
|
+
addRegion: function(name, definition){
|
1911
|
+
var regions = {};
|
1912
|
+
regions[name] = definition;
|
1913
|
+
return this.addRegions(regions)[name];
|
1914
|
+
},
|
1660
1915
|
|
1661
|
-
|
1662
|
-
|
1663
|
-
_.
|
1916
|
+
// Add multiple regions as a {name: definition, name2: def2} object literal
|
1917
|
+
addRegions: function(regions){
|
1918
|
+
this.regions = _.extend(this.regions || {}, regions);
|
1919
|
+
return this._buildRegions(regions);
|
1920
|
+
},
|
1664
1921
|
|
1665
|
-
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
1922
|
+
// Remove a single region from the Layout, by name
|
1923
|
+
removeRegion: function(name){
|
1924
|
+
return this.regionManager.removeRegion(name);
|
1925
|
+
},
|
1669
1926
|
|
1670
|
-
|
1671
|
-
|
1672
|
-
|
1927
|
+
// internal method to build regions
|
1928
|
+
_buildRegions: function(regions){
|
1929
|
+
var that = this;
|
1673
1930
|
|
1931
|
+
var defaults = {
|
1932
|
+
parentEl: function(){ return that.$el; }
|
1933
|
+
};
|
1934
|
+
|
1935
|
+
return this.regionManager.addRegions(regions, defaults);
|
1674
1936
|
},
|
1675
1937
|
|
1676
|
-
//
|
1677
|
-
//
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1938
|
+
// Internal method to initialize the regions that have been defined in a
|
1939
|
+
// `regions` attribute on this layout.
|
1940
|
+
_initializeRegions: function (options) {
|
1941
|
+
var regions;
|
1942
|
+
this._initRegionManager();
|
1943
|
+
|
1944
|
+
if (_.isFunction(this.regions)) {
|
1945
|
+
regions = this.regions(options);
|
1681
1946
|
} else {
|
1682
|
-
|
1683
|
-
region.reset();
|
1684
|
-
});
|
1947
|
+
regions = this.regions || {};
|
1685
1948
|
}
|
1949
|
+
|
1950
|
+
this.addRegions(regions);
|
1686
1951
|
},
|
1687
1952
|
|
1688
|
-
//
|
1689
|
-
//
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
manager.close();
|
1953
|
+
// Internal method to re-initialize all of the regions by updating the `el` that
|
1954
|
+
// they point to
|
1955
|
+
_reInitializeRegions: function(){
|
1956
|
+
this.regionManager.closeRegions();
|
1957
|
+
this.regionManager.each(function(region){
|
1958
|
+
region.reset();
|
1695
1959
|
});
|
1696
1960
|
},
|
1697
1961
|
|
1698
|
-
//
|
1699
|
-
//
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1962
|
+
// Internal method to initialize the region manager
|
1963
|
+
// and all regions in it
|
1964
|
+
_initRegionManager: function(){
|
1965
|
+
this.regionManager = new Marionette.RegionManager();
|
1966
|
+
|
1967
|
+
this.listenTo(this.regionManager, "region:add", function(name, region){
|
1968
|
+
this[name] = region;
|
1969
|
+
this.trigger("region:add", name, region);
|
1970
|
+
});
|
1971
|
+
|
1972
|
+
this.listenTo(this.regionManager, "region:remove", function(name, region){
|
1973
|
+
delete this[name];
|
1974
|
+
this.trigger("region:remove", name, region);
|
1704
1975
|
});
|
1705
|
-
this.regionManagers = {};
|
1706
1976
|
}
|
1707
1977
|
});
|
1708
1978
|
|
1709
1979
|
|
1710
|
-
|
1711
1980
|
// AppRouter
|
1712
1981
|
// ---------
|
1713
1982
|
|
@@ -1720,7 +1989,7 @@ Marionette.Layout = Marionette.ItemView.extend({
|
|
1720
1989
|
//
|
1721
1990
|
// App routers can only take one `controller` object.
|
1722
1991
|
// It is recommended that you divide your controller
|
1723
|
-
// objects in to smaller
|
1992
|
+
// objects in to smaller pieces of related functionality
|
1724
1993
|
// and have multiple routers / controllers, instead of
|
1725
1994
|
// just one giant router and controller.
|
1726
1995
|
//
|
@@ -1729,8 +1998,7 @@ Marionette.Layout = Marionette.ItemView.extend({
|
|
1729
1998
|
Marionette.AppRouter = Backbone.Router.extend({
|
1730
1999
|
|
1731
2000
|
constructor: function(options){
|
1732
|
-
|
1733
|
-
Backbone.Router.prototype.constructor.apply(this, args);
|
2001
|
+
Backbone.Router.prototype.constructor.apply(this, slice(arguments));
|
1734
2002
|
|
1735
2003
|
this.options = options;
|
1736
2004
|
|
@@ -1744,33 +2012,15 @@ Marionette.AppRouter = Backbone.Router.extend({
|
|
1744
2012
|
// router, and turn them in to routes that trigger the
|
1745
2013
|
// specified method on the specified `controller`.
|
1746
2014
|
processAppRoutes: function(controller, appRoutes){
|
1747
|
-
|
1748
|
-
|
1749
|
-
var routes = [];
|
1750
|
-
var router = this;
|
1751
|
-
|
1752
|
-
for(route in appRoutes){
|
1753
|
-
if (appRoutes.hasOwnProperty(route)){
|
1754
|
-
routes.unshift([route, appRoutes[route]]);
|
1755
|
-
}
|
1756
|
-
}
|
2015
|
+
_.each(appRoutes, function(methodName, route) {
|
2016
|
+
var method = controller[methodName];
|
1757
2017
|
|
1758
|
-
|
1759
|
-
|
1760
|
-
route = routes[i][0];
|
1761
|
-
methodName = routes[i][1];
|
1762
|
-
method = controller[methodName];
|
1763
|
-
|
1764
|
-
if (!method){
|
1765
|
-
var msg = "Method '" + methodName + "' was not found on the controller";
|
1766
|
-
var err = new Error(msg);
|
1767
|
-
err.name = "NoMethodError";
|
1768
|
-
throw err;
|
2018
|
+
if (!method) {
|
2019
|
+
throw new Error("Method '" + methodName + "' was not found on the controller");
|
1769
2020
|
}
|
1770
2021
|
|
1771
|
-
|
1772
|
-
|
1773
|
-
}
|
2022
|
+
this.route(route, methodName, _.bind(method, controller));
|
2023
|
+
}, this);
|
1774
2024
|
}
|
1775
2025
|
});
|
1776
2026
|
|
@@ -1782,7 +2032,8 @@ Marionette.AppRouter = Backbone.Router.extend({
|
|
1782
2032
|
// Stores and starts up `Region` objects, includes an
|
1783
2033
|
// event aggregator as `app.vent`
|
1784
2034
|
Marionette.Application = function(options){
|
1785
|
-
this.
|
2035
|
+
this._initRegionManager();
|
2036
|
+
this._initCallbacks = new Marionette.Callbacks();
|
1786
2037
|
this.vent = new Backbone.Wreqr.EventAggregator();
|
1787
2038
|
this.commands = new Backbone.Wreqr.Commands();
|
1788
2039
|
this.reqres = new Backbone.Wreqr.RequestResponse();
|
@@ -1810,7 +2061,7 @@ _.extend(Marionette.Application.prototype, Backbone.Events, {
|
|
1810
2061
|
// method is called, or run immediately if added after `start`
|
1811
2062
|
// has already been called.
|
1812
2063
|
addInitializer: function(initializer){
|
1813
|
-
this.
|
2064
|
+
this._initCallbacks.add(initializer);
|
1814
2065
|
},
|
1815
2066
|
|
1816
2067
|
// kick off all of the application's processes.
|
@@ -1818,7 +2069,7 @@ _.extend(Marionette.Application.prototype, Backbone.Events, {
|
|
1818
2069
|
// to the app, and runs all of the initializer functions
|
1819
2070
|
start: function(options){
|
1820
2071
|
this.triggerMethod("initialize:before", options);
|
1821
|
-
this.
|
2072
|
+
this._initCallbacks.run(options, this);
|
1822
2073
|
this.triggerMethod("initialize:after", options);
|
1823
2074
|
|
1824
2075
|
this.triggerMethod("start", options);
|
@@ -1827,32 +2078,40 @@ _.extend(Marionette.Application.prototype, Backbone.Events, {
|
|
1827
2078
|
// Add regions to your app.
|
1828
2079
|
// Accepts a hash of named strings or Region objects
|
1829
2080
|
// addRegions({something: "#someRegion"})
|
1830
|
-
// addRegions{
|
2081
|
+
// addRegions({something: Region.extend({el: "#someRegion"}) });
|
1831
2082
|
addRegions: function(regions){
|
1832
|
-
|
1833
|
-
_.each(regions, function (region, name) {
|
1834
|
-
var regionManager = Marionette.Region.buildRegion(region, Marionette.Region);
|
1835
|
-
that[name] = regionManager;
|
1836
|
-
});
|
2083
|
+
return this._regionManager.addRegions(regions);
|
1837
2084
|
},
|
1838
2085
|
|
1839
2086
|
// Removes a region from your app.
|
1840
2087
|
// Accepts the regions name
|
1841
2088
|
// removeRegion('myRegion')
|
1842
2089
|
removeRegion: function(region) {
|
1843
|
-
this
|
1844
|
-
delete this[region];
|
2090
|
+
this._regionManager.removeRegion(region);
|
1845
2091
|
},
|
1846
2092
|
|
1847
2093
|
// Create a module, attached to the application
|
1848
2094
|
module: function(moduleNames, moduleDefinition){
|
1849
2095
|
// slice the args, and add this application object as the
|
1850
2096
|
// first argument of the array
|
1851
|
-
var args = slice
|
2097
|
+
var args = slice(arguments);
|
1852
2098
|
args.unshift(this);
|
1853
2099
|
|
1854
2100
|
// see the Marionette.Module object for more information
|
1855
2101
|
return Marionette.Module.create.apply(Marionette.Module, args);
|
2102
|
+
},
|
2103
|
+
|
2104
|
+
// Internal method to set up the region manager
|
2105
|
+
_initRegionManager: function(){
|
2106
|
+
this._regionManager = new Marionette.RegionManager();
|
2107
|
+
|
2108
|
+
this.listenTo(this._regionManager, "region:add", function(name, region){
|
2109
|
+
this[name] = region;
|
2110
|
+
});
|
2111
|
+
|
2112
|
+
this.listenTo(this._regionManager, "region:remove", function(name, region){
|
2113
|
+
delete this[name];
|
2114
|
+
});
|
1856
2115
|
}
|
1857
2116
|
});
|
1858
2117
|
|
@@ -1896,7 +2155,7 @@ _.extend(Marionette.Module.prototype, Backbone.Events, {
|
|
1896
2155
|
this._finalizerCallbacks.add(callback);
|
1897
2156
|
},
|
1898
2157
|
|
1899
|
-
// Start the module, and run all of
|
2158
|
+
// Start the module, and run all of its initializers
|
1900
2159
|
start: function(options){
|
1901
2160
|
// Prevent re-starting a module that is already started
|
1902
2161
|
if (this._isInitialized){ return; }
|
@@ -1904,11 +2163,7 @@ _.extend(Marionette.Module.prototype, Backbone.Events, {
|
|
1904
2163
|
// start the sub-modules (depth-first hierarchy)
|
1905
2164
|
_.each(this.submodules, function(mod){
|
1906
2165
|
// check to see if we should start the sub-module with this parent
|
1907
|
-
|
1908
|
-
startWithParent = mod.startWithParent;
|
1909
|
-
|
1910
|
-
// start the sub-module
|
1911
|
-
if (startWithParent){
|
2166
|
+
if (mod.startWithParent){
|
1912
2167
|
mod.start(options);
|
1913
2168
|
}
|
1914
2169
|
});
|
@@ -1962,7 +2217,7 @@ _.extend(Marionette.Module.prototype, Backbone.Events, {
|
|
1962
2217
|
this.app,
|
1963
2218
|
Backbone,
|
1964
2219
|
Marionette,
|
1965
|
-
|
2220
|
+
Marionette.$, _,
|
1966
2221
|
customArgs
|
1967
2222
|
]);
|
1968
2223
|
|
@@ -1983,12 +2238,11 @@ _.extend(Marionette.Module, {
|
|
1983
2238
|
|
1984
2239
|
// Create a module, hanging off the app parameter as the parent object.
|
1985
2240
|
create: function(app, moduleNames, moduleDefinition){
|
1986
|
-
var that = this;
|
1987
2241
|
var module = app;
|
1988
2242
|
|
1989
2243
|
// get the custom args passed in after the module definition and
|
1990
2244
|
// get rid of the module name and definition function
|
1991
|
-
var customArgs = slice
|
2245
|
+
var customArgs = slice(arguments);
|
1992
2246
|
customArgs.splice(0, 3);
|
1993
2247
|
|
1994
2248
|
// split the module names and get the length
|
@@ -2002,9 +2256,9 @@ _.extend(Marionette.Module, {
|
|
2002
2256
|
// Loop through all the parts of the module definition
|
2003
2257
|
_.each(moduleNames, function(moduleName, i){
|
2004
2258
|
var parentModule = module;
|
2005
|
-
module =
|
2006
|
-
|
2007
|
-
});
|
2259
|
+
module = this._getModule(parentModule, moduleName, app);
|
2260
|
+
this._addModuleDefinition(parentModule, module, moduleDefinitions[i], customArgs);
|
2261
|
+
}, this);
|
2008
2262
|
|
2009
2263
|
// Return the last module in the definition chain
|
2010
2264
|
return module;
|
@@ -2051,7 +2305,6 @@ _.extend(Marionette.Module, {
|
|
2051
2305
|
|
2052
2306
|
// `and` the two together, ensuring a single `false` will prevent it
|
2053
2307
|
// from starting with the parent
|
2054
|
-
var tmp = module.startWithParent;
|
2055
2308
|
module.startWithParent = module.startWithParent && startWithParent;
|
2056
2309
|
|
2057
2310
|
// setup auto-start if needed
|
@@ -2075,4 +2328,4 @@ _.extend(Marionette.Module, {
|
|
2075
2328
|
|
2076
2329
|
|
2077
2330
|
return Marionette;
|
2078
|
-
})(Backbone, _
|
2331
|
+
})(this, Backbone, _);
|