marionette-rails 1.0.0.beta3 → 1.0.0.beta4

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Backbone.Marionette, v1.0.0-beta3
2
+ * Backbone.Marionette, v1.0.0-beta4
3
3
  * Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
4
4
  * Distributed under MIT license
5
5
  * http://github.com/marionettejs/backbone.marionette
@@ -244,9 +244,79 @@ Backbone.Marionette = Marionette = (function(Backbone, _, $){
244
244
  // For slicing `arguments` in functions
245
245
  var slice = Array.prototype.slice;
246
246
 
247
+ // Marionette.extend
248
+ // -----------------
249
+
247
250
  // Borrow the Backbone `extend` method so we can use it as needed
248
251
  Marionette.extend = Backbone.Model.extend;
249
252
 
253
+ // Marionette.getOption
254
+ // --------------------
255
+
256
+ // Retrieve an object, function or other value from a target
257
+ // object or it's `options`, with `options` taking precedence.
258
+ Marionette.getOption = function(target, optionName){
259
+ if (!target || !optionName){ return; }
260
+ var value;
261
+
262
+ if (target.options && target.options[optionName]){
263
+ value = target.options[optionName];
264
+ } else {
265
+ value = target[optionName];
266
+ }
267
+
268
+ return value;
269
+ };
270
+
271
+ // Mairionette.createObject
272
+ // ------------------------
273
+
274
+ // A wrapper / shim for `Object.create`. Uses native `Object.create`
275
+ // if available, otherwise shims it in place for Marionette to use.
276
+ Marionette.createObject = (function(){
277
+ var createObject;
278
+
279
+ // Define this once, and just replace the .prototype on it as needed,
280
+ // to improve performance in older / less optimized JS engines
281
+ function F() {}
282
+
283
+
284
+ // Check for existing native / shimmed Object.create
285
+ if (typeof Object.create === "function"){
286
+
287
+ // found native/shim, so use it
288
+ createObject = Object.create;
289
+
290
+ } else {
291
+
292
+ // An implementation of the Boodman/Crockford delegation
293
+ // w/ Cornford optimization, as suggested by @unscriptable
294
+ // https://gist.github.com/3959151
295
+
296
+ // native/shim not found, so shim it ourself
297
+ createObject = function (o) {
298
+
299
+ // set the prototype of the function
300
+ // so we will get `o` as the prototype
301
+ // of the new object instance
302
+ F.prototype = o;
303
+
304
+ // create a new object that inherits from
305
+ // the `o` parameter
306
+ var child = new F();
307
+
308
+ // clean up just in case o is really large
309
+ F.prototype = null;
310
+
311
+ // send it back
312
+ return child;
313
+ };
314
+
315
+ }
316
+
317
+ return createObject;
318
+ })();
319
+
250
320
  // Trigger an event and a corresponding method name. Examples:
251
321
  //
252
322
  // `this.triggerMethod("foo")` will trigger the "foo" event and
@@ -274,11 +344,22 @@ Marionette.triggerMethod = function(){
274
344
  }
275
345
  };
276
346
 
347
+
277
348
  // EventBinder
278
349
  // -----------
279
350
  // Import the event binder from it's new home
280
351
  // https://github.com/marionettejs/backbone.eventbinder
281
- Marionette.EventBinder = Backbone.EventBinder;
352
+ Marionette.EventBinder = Backbone.EventBinder.extend({
353
+
354
+ augment: function(target){
355
+ var eventBinder = new Marionette.EventBinder();
356
+ target.eventBinder = eventBinder;
357
+ target.bindTo = _.bind(eventBinder.bindTo, eventBinder);
358
+ target.unbindFrom = _.bind(eventBinder.unbindFrom, eventBinder);
359
+ target.unbindAll = _.bind(eventBinder.unbindAll, eventBinder);
360
+ }
361
+
362
+ });
282
363
 
283
364
  // Add the EventBinder methods to the view directly,
284
365
  // but keep them bound to the EventBinder instance so they work properly.
@@ -310,6 +391,361 @@ Marionette.EventAggregator = Backbone.Wreqr.EventAggregator.extend({
310
391
 
311
392
  });
312
393
 
394
+ // Callbacks
395
+ // ---------
396
+
397
+ // A simple way of managing a collection of callbacks
398
+ // and executing them at a later point in time, using jQuery's
399
+ // `Deferred` object.
400
+ Marionette.Callbacks = function(){
401
+ this._deferred = $.Deferred();
402
+ this._callbacks = [];
403
+ };
404
+
405
+ _.extend(Marionette.Callbacks.prototype, {
406
+
407
+ // Add a callback to be executed. Callbacks added here are
408
+ // guaranteed to execute, even if they are added after the
409
+ // `run` method is called.
410
+ add: function(callback, contextOverride){
411
+ this._callbacks.push({cb: callback, ctx: contextOverride});
412
+
413
+ this._deferred.done(function(context, options){
414
+ if (contextOverride){ context = contextOverride; }
415
+ callback.call(context, options);
416
+ });
417
+ },
418
+
419
+ // Run all registered callbacks with the context specified.
420
+ // Additional callbacks can be added after this has been run
421
+ // and they will still be executed.
422
+ run: function(options, context){
423
+ this._deferred.resolve(context, options);
424
+ },
425
+
426
+ // Resets the list of callbacks to be run, allowing the same list
427
+ // to be run multiple times - whenever the `run` method is called.
428
+ reset: function(){
429
+ var that = this;
430
+ var callbacks = this._callbacks;
431
+ this._deferred = $.Deferred();
432
+ this._callbacks = [];
433
+ _.each(callbacks, function(cb){
434
+ that.add(cb.cb, cb.ctx);
435
+ });
436
+ }
437
+ });
438
+
439
+
440
+ // Template Cache
441
+ // --------------
442
+
443
+ // Manage templates stored in `<script>` blocks,
444
+ // caching them for faster access.
445
+ Marionette.TemplateCache = function(templateId){
446
+ this.templateId = templateId;
447
+ };
448
+
449
+ // TemplateCache object-level methods. Manage the template
450
+ // caches from these method calls instead of creating
451
+ // your own TemplateCache instances
452
+ _.extend(Marionette.TemplateCache, {
453
+ templateCaches: {},
454
+
455
+ // Get the specified template by id. Either
456
+ // retrieves the cached version, or loads it
457
+ // from the DOM.
458
+ get: function(templateId){
459
+ var that = this;
460
+ var cachedTemplate = this.templateCaches[templateId];
461
+
462
+ if (!cachedTemplate){
463
+ cachedTemplate = new Marionette.TemplateCache(templateId);
464
+ this.templateCaches[templateId] = cachedTemplate;
465
+ }
466
+
467
+ return cachedTemplate.load();
468
+ },
469
+
470
+ // Clear templates from the cache. If no arguments
471
+ // are specified, clears all templates:
472
+ // `clear()`
473
+ //
474
+ // If arguments are specified, clears each of the
475
+ // specified templates from the cache:
476
+ // `clear("#t1", "#t2", "...")`
477
+ clear: function(){
478
+ var i;
479
+ var length = arguments.length;
480
+
481
+ if (length > 0){
482
+ for(i=0; i<length; i++){
483
+ delete this.templateCaches[arguments[i]];
484
+ }
485
+ } else {
486
+ this.templateCaches = {};
487
+ }
488
+ }
489
+ });
490
+
491
+ // TemplateCache instance methods, allowing each
492
+ // template cache object to manage it's own state
493
+ // and know whether or not it has been loaded
494
+ _.extend(Marionette.TemplateCache.prototype, {
495
+
496
+ // Internal method to load the template asynchronously.
497
+ load: function(){
498
+ var that = this;
499
+
500
+ // Guard clause to prevent loading this template more than once
501
+ if (this.compiledTemplate){
502
+ return this.compiledTemplate;
503
+ }
504
+
505
+ // Load the template and compile it
506
+ var template = this.loadTemplate(this.templateId);
507
+ this.compiledTemplate = this.compileTemplate(template);
508
+
509
+ return this.compiledTemplate;
510
+ },
511
+
512
+ // Load a template from the DOM, by default. Override
513
+ // this method to provide your own template retrieval,
514
+ // such as asynchronous loading from a server.
515
+ loadTemplate: function(templateId){
516
+ var template = $(templateId).html();
517
+
518
+ if (!template || template.length === 0){
519
+ var msg = "Could not find template: '" + templateId + "'";
520
+ var err = new Error(msg);
521
+ err.name = "NoTemplateError";
522
+ throw err;
523
+ }
524
+
525
+ return template;
526
+ },
527
+
528
+ // Pre-compile the template before caching it. Override
529
+ // this method if you do not need to pre-compile a template
530
+ // (JST / RequireJS for example) or if you want to change
531
+ // the template engine used (Handebars, etc).
532
+ compileTemplate: function(rawTemplate){
533
+ return _.template(rawTemplate);
534
+ }
535
+ });
536
+
537
+
538
+ // Renderer
539
+ // --------
540
+
541
+ // Render a template with data by passing in the template
542
+ // selector and the data to render.
543
+ Marionette.Renderer = {
544
+
545
+ // Render a template with data. The `template` parameter is
546
+ // passed to the `TemplateCache` object to retrieve the
547
+ // template function. Override this method to provide your own
548
+ // custom rendering and template handling for all of Marionette.
549
+ render: function(template, data){
550
+ var templateFunc = typeof template === 'function' ? template : Marionette.TemplateCache.get(template);
551
+ var html = templateFunc(data);
552
+ return html;
553
+ }
554
+ };
555
+
556
+
557
+
558
+ // Marionette Controller
559
+ // ---------------------
560
+ //
561
+ // A multi-purpose object to use as a controller for
562
+ // modules and routers, and as a mediator for workflow
563
+ // and coordination of other objects, views, and more.
564
+ Marionette.Controller = function(options){
565
+ this.options = options || {};
566
+
567
+ Marionette.addEventBinder(this);
568
+
569
+ if (_.isFunction(this.initialize)){
570
+ this.initialize(options);
571
+ }
572
+ };
573
+
574
+ Marionette.Controller.extend = Marionette.extend;
575
+
576
+ // Controller Methods
577
+ // --------------
578
+
579
+ // Ensure it can trigger events with Backbone.Events
580
+ _.extend(Marionette.Controller.prototype, Backbone.Events);
581
+
582
+ // Region
583
+ // ------
584
+ //
585
+ // Manage the visual regions of your composite application. See
586
+ // http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/
587
+
588
+ Marionette.Region = function(options){
589
+ this.options = options || {};
590
+
591
+ Marionette.addEventBinder(this);
592
+
593
+ this.el = Marionette.getOption(this, "el");
594
+
595
+ if (!this.el){
596
+ var err = new Error("An 'el' must be specified for a region.");
597
+ err.name = "NoElError";
598
+ throw err;
599
+ }
600
+
601
+ if (this.initialize){
602
+ this.initialize.apply(this, arguments);
603
+ }
604
+ };
605
+
606
+
607
+ // Region Type methods
608
+ // -------------------
609
+
610
+ _.extend(Marionette.Region, {
611
+
612
+ // Build an instance of a region by passing in a configuration object
613
+ // and a default region type to use if none is specified in the config.
614
+ //
615
+ // The config object should either be a string as a jQuery DOM selector,
616
+ // a Region type directly, or an object literal that specifies both
617
+ // a selector and regionType:
618
+ //
619
+ // ```js
620
+ // {
621
+ // selector: "#foo",
622
+ // regionType: MyCustomRegion
623
+ // }
624
+ // ```
625
+ //
626
+ buildRegion: function(regionConfig, defaultRegionType){
627
+ var regionIsString = (typeof regionConfig === "string");
628
+ var regionSelectorIsString = (typeof regionConfig.selector === "string");
629
+ var regionTypeIsUndefined = (typeof regionConfig.regionType === "undefined");
630
+ var regionIsType = (typeof regionConfig === "function");
631
+
632
+ if (!regionIsType && !regionIsString && !regionSelectorIsString) {
633
+ throw new Error("Region must be specified as a Region type, a selector string or an object with selector property");
634
+ }
635
+
636
+ var selector, RegionType;
637
+
638
+ // get the selector for the region
639
+
640
+ if (regionIsString) {
641
+ selector = regionConfig;
642
+ }
643
+
644
+ if (regionConfig.selector) {
645
+ selector = regionConfig.selector;
646
+ }
647
+
648
+ // get the type for the region
649
+
650
+ if (regionIsType){
651
+ RegionType = regionConfig;
652
+ }
653
+
654
+ if (!regionIsType && regionTypeIsUndefined) {
655
+ RegionType = defaultRegionType;
656
+ }
657
+
658
+ if (regionConfig.regionType) {
659
+ RegionType = regionConfig.regionType;
660
+ }
661
+
662
+ // build the region instance
663
+
664
+ var regionManager = new RegionType({
665
+ el: selector
666
+ });
667
+
668
+ return regionManager;
669
+ }
670
+
671
+ });
672
+
673
+ // Region Instance Methods
674
+ // -----------------------
675
+
676
+ _.extend(Marionette.Region.prototype, Backbone.Events, {
677
+
678
+ // Displays a backbone view instance inside of the region.
679
+ // Handles calling the `render` method for you. Reads content
680
+ // directly from the `el` attribute. Also calls an optional
681
+ // `onShow` and `close` method on your view, just after showing
682
+ // or just before closing the view, respectively.
683
+ show: function(view){
684
+
685
+ this.ensureEl();
686
+ this.close();
687
+
688
+ view.render();
689
+ this.open(view);
690
+
691
+ Marionette.triggerMethod.call(view, "show");
692
+ Marionette.triggerMethod.call(this, "show", view);
693
+
694
+ this.currentView = view;
695
+ },
696
+
697
+ ensureEl: function(){
698
+ if (!this.$el || this.$el.length === 0){
699
+ this.$el = this.getEl(this.el);
700
+ }
701
+ },
702
+
703
+ // Override this method to change how the region finds the
704
+ // DOM element that it manages. Return a jQuery selector object.
705
+ getEl: function(selector){
706
+ return $(selector);
707
+ },
708
+
709
+ // Override this method to change how the new view is
710
+ // appended to the `$el` that the region is managing
711
+ open: function(view){
712
+ this.$el.empty().append(view.el);
713
+ },
714
+
715
+ // Close the current view, if there is one. If there is no
716
+ // current view, it does nothing and returns immediately.
717
+ close: function(){
718
+ var view = this.currentView;
719
+ if (!view || view.isClosed){ return; }
720
+
721
+ if (view.close) { view.close(); }
722
+ Marionette.triggerMethod.call(this, "close");
723
+
724
+ delete this.currentView;
725
+ },
726
+
727
+ // Attach an existing view to the region. This
728
+ // will not call `render` or `onShow` for the new view,
729
+ // and will not replace the current HTML for the `el`
730
+ // of the region.
731
+ attachView: function(view){
732
+ this.currentView = view;
733
+ },
734
+
735
+ // Reset the region by closing any existing view and
736
+ // clearing out the cached `$el`. The next time a view
737
+ // is shown via this region, the region will re-query the
738
+ // DOM for the region's `el`.
739
+ reset: function(){
740
+ this.close();
741
+ delete this.$el;
742
+ }
743
+ });
744
+
745
+ // Copy the `extend` function used by Backbone's classes
746
+ Marionette.Region.extend = Marionette.extend;
747
+
748
+
313
749
  // Marionette.View
314
750
  // ---------------
315
751
 
@@ -337,17 +773,7 @@ Marionette.View = Backbone.View.extend({
337
773
  // definition or pass a `template: "whatever"` parameter in
338
774
  // to the constructor options.
339
775
  getTemplate: function(){
340
- var template;
341
-
342
- // Get the template from `this.options.template` or
343
- // `this.template`. The `options` takes precedence.
344
- if (this.options && this.options.template){
345
- template = this.options.template;
346
- } else {
347
- template = this.template;
348
- }
349
-
350
- return template;
776
+ return Marionette.getOption(this, "template");
351
777
  },
352
778
 
353
779
  // Mix in template helper methods. Looks for a
@@ -628,7 +1054,8 @@ Marionette.CollectionView = Marionette.View.extend({
628
1054
  // a collection of item views, when the collection is
629
1055
  // empty
630
1056
  showEmptyView: function(){
631
- var EmptyView = this.options.emptyView || this.emptyView;
1057
+ var EmptyView = Marionette.getOption(this, "emptyView");
1058
+
632
1059
  if (EmptyView && !this._showingEmptyView){
633
1060
  this._showingEmptyView = true;
634
1061
  var model = new Backbone.Model();
@@ -650,7 +1077,7 @@ Marionette.CollectionView = Marionette.View.extend({
650
1077
  // or from the `itemView` in the object definition. The "options"
651
1078
  // takes precedence.
652
1079
  getItemView: function(item){
653
- var itemView = this.options.itemView || this.itemView;
1080
+ var itemView = Marionette.getOption(this, "itemView");
654
1081
 
655
1082
  if (!itemView){
656
1083
  var err = new Error("An `itemView` must be specified");
@@ -666,11 +1093,20 @@ Marionette.CollectionView = Marionette.View.extend({
666
1093
  addItemView: function(item, ItemView, index){
667
1094
  var that = this;
668
1095
 
669
- var view = this.buildItemView(item, ItemView);
1096
+ // get the itemViewOptions if any were specified
1097
+ var itemViewOptions;
1098
+ if (_.isFunction(this.itemViewOptions)){
1099
+ itemViewOptions = this.itemViewOptions(item);
1100
+ } else {
1101
+ itemViewOptions = this.itemViewOptions;
1102
+ }
1103
+
1104
+ // build the view
1105
+ var view = this.buildItemView(item, ItemView, itemViewOptions);
670
1106
 
671
1107
  // Store the child view itself so we can properly
672
1108
  // remove and/or close it later
673
- this.storeChild(view);
1109
+ this.storeChild(item, view);
674
1110
  this.triggerMethod("item:added", view);
675
1111
 
676
1112
  // Forward all child item view events through the parent,
@@ -706,17 +1142,9 @@ Marionette.CollectionView = Marionette.View.extend({
706
1142
  },
707
1143
 
708
1144
  // Build an `itemView` for every model in the collection.
709
- buildItemView: function(item, ItemView){
710
- var itemViewOptions;
711
-
712
- if (_.isFunction(this.itemViewOptions)){
713
- itemViewOptions = this.itemViewOptions(item);
714
- } else {
715
- itemViewOptions = this.itemViewOptions;
716
- }
717
-
1145
+ buildItemView: function(item, ItemViewType, itemViewOptions){
718
1146
  var options = _.extend({model: item}, itemViewOptions);
719
- var view = new ItemView(options);
1147
+ var view = new ItemViewType(options);
720
1148
  return view;
721
1149
  },
722
1150
 
@@ -749,8 +1177,8 @@ Marionette.CollectionView = Marionette.View.extend({
749
1177
 
750
1178
  // Store references to all of the child `itemView`
751
1179
  // instances so they can be managed and cleaned up, later.
752
- storeChild: function(view){
753
- this.children[view.model.cid] = view;
1180
+ storeChild: function(item, view){
1181
+ this.children[item.cid] = view;
754
1182
  },
755
1183
 
756
1184
  // Internal method to set up the `children` object for
@@ -811,7 +1239,7 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
811
1239
  // `this.itemView` or Marionette.CompositeView if no `itemView`
812
1240
  // has been defined
813
1241
  getItemView: function(item){
814
- var itemView = this.options.itemView || this.itemView || this.constructor;
1242
+ var itemView = Marionette.getOption(this, "itemView") || this.constructor;
815
1243
 
816
1244
  if (!itemView){
817
1245
  var err = new Error("An `itemView` must be specified");
@@ -832,8 +1260,6 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
832
1260
  data = this.model.toJSON();
833
1261
  }
834
1262
 
835
- data = this.mixinTemplateHelpers(data);
836
-
837
1263
  return data;
838
1264
  },
839
1265
 
@@ -872,6 +1298,7 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
872
1298
  renderModel: function(){
873
1299
  var data = {};
874
1300
  data = this.serializeData();
1301
+ data = this.mixinTemplateHelpers(data);
875
1302
 
876
1303
  var template = this.getTemplate();
877
1304
  return Marionette.Renderer.render(template, data);
@@ -921,177 +1348,6 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
921
1348
  });
922
1349
 
923
1350
 
924
- // Region
925
- // ------
926
- //
927
- // Manage the visual regions of your composite application. See
928
- // http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/
929
-
930
- Marionette.Region = function(options){
931
- this.options = options || {};
932
-
933
- var el = this.options.el;
934
- delete this.options.el;
935
-
936
- Marionette.addEventBinder(this);
937
-
938
- if (el){
939
- this.el = el;
940
- }
941
-
942
- if (!this.el){
943
- var err = new Error("An 'el' must be specified for a region.");
944
- err.name = "NoElError";
945
- throw err;
946
- }
947
-
948
- if (this.initialize){
949
- this.initialize.apply(this, arguments);
950
- }
951
- };
952
-
953
-
954
- // Region Type methods
955
- // -------------------
956
-
957
- _.extend(Marionette.Region, {
958
-
959
- // Build an instance of a region by passing in a configuration object
960
- // and a default region type to use if none is specified in the config.
961
- //
962
- // The config object should either be a string as a jQuery DOM selector,
963
- // a Region type directly, or an object literal that specifies both
964
- // a selector and regionType:
965
- //
966
- // ```js
967
- // {
968
- // selector: "#foo",
969
- // regionType: MyCustomRegion
970
- // }
971
- // ```
972
- //
973
- buildRegion: function(regionConfig, defaultRegionType){
974
- var regionIsString = (typeof regionConfig === "string");
975
- var regionSelectorIsString = (typeof regionConfig.selector === "string");
976
- var regionTypeIsUndefined = (typeof regionConfig.regionType === "undefined");
977
- var regionIsType = (typeof regionConfig === "function");
978
-
979
- if (!regionIsType && !regionIsString && !regionSelectorIsString) {
980
- throw new Error("Region must be specified as a Region type, a selector string or an object with selector property");
981
- }
982
-
983
- var selector, RegionType;
984
-
985
- // get the selector for the region
986
-
987
- if (regionIsString) {
988
- selector = regionConfig;
989
- }
990
-
991
- if (regionConfig.selector) {
992
- selector = regionConfig.selector;
993
- }
994
-
995
- // get the type for the region
996
-
997
- if (regionIsType){
998
- RegionType = regionConfig;
999
- }
1000
-
1001
- if (!regionIsType && regionTypeIsUndefined) {
1002
- RegionType = defaultRegionType;
1003
- }
1004
-
1005
- if (regionConfig.regionType) {
1006
- RegionType = regionConfig.regionType;
1007
- }
1008
-
1009
- // build the region instance
1010
-
1011
- var regionManager = new RegionType({
1012
- el: selector
1013
- });
1014
-
1015
- return regionManager;
1016
- }
1017
-
1018
- });
1019
-
1020
- // Region Instance Methods
1021
- // -----------------------
1022
-
1023
- _.extend(Marionette.Region.prototype, Backbone.Events, {
1024
-
1025
- // Displays a backbone view instance inside of the region.
1026
- // Handles calling the `render` method for you. Reads content
1027
- // directly from the `el` attribute. Also calls an optional
1028
- // `onShow` and `close` method on your view, just after showing
1029
- // or just before closing the view, respectively.
1030
- show: function(view){
1031
-
1032
- this.ensureEl();
1033
- this.close();
1034
-
1035
- view.render();
1036
- this.open(view);
1037
-
1038
- Marionette.triggerMethod.call(view, "show");
1039
- Marionette.triggerMethod.call(this, "show", view);
1040
-
1041
- this.currentView = view;
1042
- },
1043
-
1044
- ensureEl: function(){
1045
- if (!this.$el || this.$el.length === 0){
1046
- this.$el = this.getEl(this.el);
1047
- }
1048
- },
1049
-
1050
- // Override this method to change how the region finds the
1051
- // DOM element that it manages. Return a jQuery selector object.
1052
- getEl: function(selector){
1053
- return $(selector);
1054
- },
1055
-
1056
- // Override this method to change how the new view is
1057
- // appended to the `$el` that the region is managing
1058
- open: function(view){
1059
- this.$el.html(view.el);
1060
- },
1061
-
1062
- // Close the current view, if there is one. If there is no
1063
- // current view, it does nothing and returns immediately.
1064
- close: function(){
1065
- var view = this.currentView;
1066
- if (!view || view.isClosed){ return; }
1067
-
1068
- if (view.close) { view.close(); }
1069
- Marionette.triggerMethod.call(this, "close");
1070
-
1071
- delete this.currentView;
1072
- },
1073
-
1074
- // Attach an existing view to the region. This
1075
- // will not call `render` or `onShow` for the new view,
1076
- // and will not replace the current HTML for the `el`
1077
- // of the region.
1078
- attachView: function(view){
1079
- this.currentView = view;
1080
- },
1081
-
1082
- // Reset the region by closing any existing view and
1083
- // clearing out the cached `$el`. The next time a view
1084
- // is shown via this region, the region will re-query the
1085
- // DOM for the region's `el`.
1086
- reset: function(){
1087
- this.close();
1088
- delete this.$el;
1089
- }
1090
- });
1091
-
1092
- // Copy the `extend` function used by Backbone's classes
1093
- Marionette.Region.extend = Marionette.extend;
1094
-
1095
1351
  // Layout
1096
1352
  // ------
1097
1353
 
@@ -1180,24 +1436,92 @@ Marionette.Layout = Marionette.ItemView.extend({
1180
1436
  }
1181
1437
  },
1182
1438
 
1183
- // Close all of the regions that have been opened by
1184
- // this layout. This method is called when the layout
1185
- // itself is closed.
1186
- closeRegions: function () {
1187
- var that = this;
1188
- _.each(this.regionManagers, function (manager, name) {
1189
- manager.close();
1190
- });
1191
- },
1439
+ // Close all of the regions that have been opened by
1440
+ // this layout. This method is called when the layout
1441
+ // itself is closed.
1442
+ closeRegions: function () {
1443
+ var that = this;
1444
+ _.each(this.regionManagers, function (manager, name) {
1445
+ manager.close();
1446
+ });
1447
+ },
1448
+
1449
+ // Destroys all of the regions by removing references
1450
+ // from the Layout
1451
+ destroyRegions: function(){
1452
+ var that = this;
1453
+ _.each(this.regionManagers, function (manager, name) {
1454
+ delete that[name];
1455
+ });
1456
+ this.regionManagers = {};
1457
+ }
1458
+ });
1459
+
1460
+
1461
+
1462
+ // AppRouter
1463
+ // ---------
1464
+
1465
+ // Reduce the boilerplate code of handling route events
1466
+ // and then calling a single method on another object.
1467
+ // Have your routers configured to call the method on
1468
+ // your object, directly.
1469
+ //
1470
+ // Configure an AppRouter with `appRoutes`.
1471
+ //
1472
+ // App routers can only take one `controller` object.
1473
+ // It is recommended that you divide your controller
1474
+ // objects in to smaller peices of related functionality
1475
+ // and have multiple routers / controllers, instead of
1476
+ // just one giant router and controller.
1477
+ //
1478
+ // You can also add standard routes to an AppRouter.
1479
+
1480
+ Marionette.AppRouter = Backbone.Router.extend({
1481
+
1482
+ constructor: function(options){
1483
+ Backbone.Router.prototype.constructor.call(this, options);
1484
+
1485
+ if (this.appRoutes){
1486
+ var controller = this.controller;
1487
+ if (options && options.controller) {
1488
+ controller = options.controller;
1489
+ }
1490
+ this.processAppRoutes(controller, this.appRoutes);
1491
+ }
1492
+ },
1493
+
1494
+ // Internal method to process the `appRoutes` for the
1495
+ // router, and turn them in to routes that trigger the
1496
+ // specified method on the specified `controller`.
1497
+ processAppRoutes: function(controller, appRoutes){
1498
+ var method, methodName;
1499
+ var route, routesLength, i;
1500
+ var routes = [];
1501
+ var router = this;
1502
+
1503
+ for(route in appRoutes){
1504
+ if (appRoutes.hasOwnProperty(route)){
1505
+ routes.unshift([route, appRoutes[route]]);
1506
+ }
1507
+ }
1508
+
1509
+ routesLength = routes.length;
1510
+ for (i = 0; i < routesLength; i++){
1511
+ route = routes[i][0];
1512
+ methodName = routes[i][1];
1513
+ method = controller[methodName];
1514
+
1515
+ if (!method){
1516
+ var msg = "Method '" + methodName + "' was not found on the controller";
1517
+ var err = new Error(msg);
1518
+ err.name = "NoMethodError";
1519
+ throw err;
1520
+ }
1192
1521
 
1193
- // Destroys all of the regions by removing references
1194
- // from the Layout
1195
- destroyRegions: function(){
1196
- var that = this;
1197
- _.each(this.regionManagers, function (manager, name) {
1198
- delete that[name];
1199
- });
1200
- this.regionManagers = {};
1522
+ method = _.bind(method, controller);
1523
+ router.route(route, methodName, method);
1524
+ }
1201
1525
  }
1202
1526
  });
1203
1527
 
@@ -1285,73 +1609,6 @@ _.extend(Marionette.Application.prototype, Backbone.Events, {
1285
1609
  // Copy the `extend` function used by Backbone's classes
1286
1610
  Marionette.Application.extend = Marionette.extend;
1287
1611
 
1288
- // AppRouter
1289
- // ---------
1290
-
1291
- // Reduce the boilerplate code of handling route events
1292
- // and then calling a single method on another object.
1293
- // Have your routers configured to call the method on
1294
- // your object, directly.
1295
- //
1296
- // Configure an AppRouter with `appRoutes`.
1297
- //
1298
- // App routers can only take one `controller` object.
1299
- // It is recommended that you divide your controller
1300
- // objects in to smaller peices of related functionality
1301
- // and have multiple routers / controllers, instead of
1302
- // just one giant router and controller.
1303
- //
1304
- // You can also add standard routes to an AppRouter.
1305
-
1306
- Marionette.AppRouter = Backbone.Router.extend({
1307
-
1308
- constructor: function(options){
1309
- Backbone.Router.prototype.constructor.call(this, options);
1310
-
1311
- if (this.appRoutes){
1312
- var controller = this.controller;
1313
- if (options && options.controller) {
1314
- controller = options.controller;
1315
- }
1316
- this.processAppRoutes(controller, this.appRoutes);
1317
- }
1318
- },
1319
-
1320
- // Internal method to process the `appRoutes` for the
1321
- // router, and turn them in to routes that trigger the
1322
- // specified method on the specified `controller`.
1323
- processAppRoutes: function(controller, appRoutes){
1324
- var method, methodName;
1325
- var route, routesLength, i;
1326
- var routes = [];
1327
- var router = this;
1328
-
1329
- for(route in appRoutes){
1330
- if (appRoutes.hasOwnProperty(route)){
1331
- routes.unshift([route, appRoutes[route]]);
1332
- }
1333
- }
1334
-
1335
- routesLength = routes.length;
1336
- for (i = 0; i < routesLength; i++){
1337
- route = routes[i][0];
1338
- methodName = routes[i][1];
1339
- method = controller[methodName];
1340
-
1341
- if (!method){
1342
- var msg = "Method '" + methodName + "' was not found on the controller";
1343
- var err = new Error(msg);
1344
- err.name = "NoMethodError";
1345
- throw err;
1346
- }
1347
-
1348
- method = _.bind(method, controller);
1349
- router.route(route, methodName, method);
1350
- }
1351
- }
1352
- });
1353
-
1354
-
1355
1612
  // Module
1356
1613
  // ------
1357
1614
 
@@ -1567,169 +1824,6 @@ _.extend(Marionette.Module, {
1567
1824
  }
1568
1825
  });
1569
1826
 
1570
- // Template Cache
1571
- // --------------
1572
-
1573
- // Manage templates stored in `<script>` blocks,
1574
- // caching them for faster access.
1575
- Marionette.TemplateCache = function(templateId){
1576
- this.templateId = templateId;
1577
- };
1578
-
1579
- // TemplateCache object-level methods. Manage the template
1580
- // caches from these method calls instead of creating
1581
- // your own TemplateCache instances
1582
- _.extend(Marionette.TemplateCache, {
1583
- templateCaches: {},
1584
-
1585
- // Get the specified template by id. Either
1586
- // retrieves the cached version, or loads it
1587
- // from the DOM.
1588
- get: function(templateId){
1589
- var that = this;
1590
- var cachedTemplate = this.templateCaches[templateId];
1591
-
1592
- if (!cachedTemplate){
1593
- cachedTemplate = new Marionette.TemplateCache(templateId);
1594
- this.templateCaches[templateId] = cachedTemplate;
1595
- }
1596
-
1597
- return cachedTemplate.load();
1598
- },
1599
-
1600
- // Clear templates from the cache. If no arguments
1601
- // are specified, clears all templates:
1602
- // `clear()`
1603
- //
1604
- // If arguments are specified, clears each of the
1605
- // specified templates from the cache:
1606
- // `clear("#t1", "#t2", "...")`
1607
- clear: function(){
1608
- var i;
1609
- var length = arguments.length;
1610
-
1611
- if (length > 0){
1612
- for(i=0; i<length; i++){
1613
- delete this.templateCaches[arguments[i]];
1614
- }
1615
- } else {
1616
- this.templateCaches = {};
1617
- }
1618
- }
1619
- });
1620
-
1621
- // TemplateCache instance methods, allowing each
1622
- // template cache object to manage it's own state
1623
- // and know whether or not it has been loaded
1624
- _.extend(Marionette.TemplateCache.prototype, {
1625
-
1626
- // Internal method to load the template asynchronously.
1627
- load: function(){
1628
- var that = this;
1629
-
1630
- // Guard clause to prevent loading this template more than once
1631
- if (this.compiledTemplate){
1632
- return this.compiledTemplate;
1633
- }
1634
-
1635
- // Load the template and compile it
1636
- var template = this.loadTemplate(this.templateId);
1637
- this.compiledTemplate = this.compileTemplate(template);
1638
-
1639
- return this.compiledTemplate;
1640
- },
1641
-
1642
- // Load a template from the DOM, by default. Override
1643
- // this method to provide your own template retrieval,
1644
- // such as asynchronous loading from a server.
1645
- loadTemplate: function(templateId){
1646
- var template = $(templateId).html();
1647
-
1648
- if (!template || template.length === 0){
1649
- var msg = "Could not find template: '" + templateId + "'";
1650
- var err = new Error(msg);
1651
- err.name = "NoTemplateError";
1652
- throw err;
1653
- }
1654
-
1655
- return template;
1656
- },
1657
-
1658
- // Pre-compile the template before caching it. Override
1659
- // this method if you do not need to pre-compile a template
1660
- // (JST / RequireJS for example) or if you want to change
1661
- // the template engine used (Handebars, etc).
1662
- compileTemplate: function(rawTemplate){
1663
- return _.template(rawTemplate);
1664
- }
1665
- });
1666
-
1667
-
1668
- // Renderer
1669
- // --------
1670
-
1671
- // Render a template with data by passing in the template
1672
- // selector and the data to render.
1673
- Marionette.Renderer = {
1674
-
1675
- // Render a template with data. The `template` parameter is
1676
- // passed to the `TemplateCache` object to retrieve the
1677
- // template function. Override this method to provide your own
1678
- // custom rendering and template handling for all of Marionette.
1679
- render: function(template, data){
1680
- var templateFunc = typeof template === 'function' ? template : Marionette.TemplateCache.get(template);
1681
- var html = templateFunc(data);
1682
- return html;
1683
- }
1684
- };
1685
-
1686
-
1687
- // Callbacks
1688
- // ---------
1689
-
1690
- // A simple way of managing a collection of callbacks
1691
- // and executing them at a later point in time, using jQuery's
1692
- // `Deferred` object.
1693
- Marionette.Callbacks = function(){
1694
- this._deferred = $.Deferred();
1695
- this._callbacks = [];
1696
- };
1697
-
1698
- _.extend(Marionette.Callbacks.prototype, {
1699
-
1700
- // Add a callback to be executed. Callbacks added here are
1701
- // guaranteed to execute, even if they are added after the
1702
- // `run` method is called.
1703
- add: function(callback, contextOverride){
1704
- this._callbacks.push({cb: callback, ctx: contextOverride});
1705
-
1706
- this._deferred.done(function(context, options){
1707
- if (contextOverride){ context = contextOverride; }
1708
- callback.call(context, options);
1709
- });
1710
- },
1711
-
1712
- // Run all registered callbacks with the context specified.
1713
- // Additional callbacks can be added after this has been run
1714
- // and they will still be executed.
1715
- run: function(options, context){
1716
- this._deferred.resolve(context, options);
1717
- },
1718
-
1719
- // Resets the list of callbacks to be run, allowing the same list
1720
- // to be run multiple times - whenever the `run` method is called.
1721
- reset: function(){
1722
- var that = this;
1723
- var callbacks = this._callbacks;
1724
- this._deferred = $.Deferred();
1725
- this._callbacks = [];
1726
- _.each(callbacks, function(cb){
1727
- that.add(cb.cb, cb.ctx);
1728
- });
1729
- }
1730
- });
1731
-
1732
-
1733
1827
 
1734
1828
  return Marionette;
1735
1829
  })(Backbone, _, $ || window.jQuery || window.Zepto || window.ender);
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marionette-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta3
4
+ version: 1.0.0.beta4
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors: