Skip to content

Commit

Permalink
Initial regionEvents pass
Browse files Browse the repository at this point in the history
  • Loading branch information
samccone committed Sep 10, 2014
1 parent 849a091 commit 48904ce
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 25 deletions.
22 changes: 13 additions & 9 deletions spec/javascripts/application.appRegions.spec.js
Expand Up @@ -17,12 +17,16 @@ describe('application regions', function() {
fooRegion: '#foo-region',
barRegion: '#bar-region'
});

this.app.start();
});

it('should initialize the regions', function() {
expect(this.app.fooRegion).to.deep.equal(this.fooRegion);
expect(this.app.barRegion).to.deep.equal(this.barRegion);
expect(this.app.fooRegion)
.to.be.instanceOf(Marionette.Region);

expect(this.app.barRegion)
.to.be.instanceOf(Marionette.Region);
});

it('should trigger a before:add:region event', function() {
Expand Down Expand Up @@ -74,7 +78,7 @@ describe('application regions', function() {
});

it('should initialize the regions, immediately', function() {
expect(this.app.fooRegion).to.deep.equal(this.fooRegion);
expect(this.app.fooRegion).to.be.instanceOf(Marionette.Region);
});

it('should create an instance of the specified region class', function() {
Expand Down Expand Up @@ -336,7 +340,7 @@ describe('application regions', function() {
});

it('should initialize the regions, immediately', function() {
expect(this.app.fooRegion).to.deep.equal(this.fooRegion);
expect(this.app.fooRegion).to.be.instanceOf(Marionette.Region);
});

it('should create an instance of the specified region class', function() {
Expand Down Expand Up @@ -377,13 +381,13 @@ describe('application regions', function() {
});

it('returns all the created regions on an object literal', function() {
expect(this.app.fooRegion).to.deep.equal(this.fooRegion);
expect(this.app.barRegion).to.deep.equal(this.barRegion);
expect(this.app.fooRegion).to.be.instanceOf(Marionette.Region);
expect(this.app.barRegion).to.be.instanceOf(Marionette.Region);
});

it('initializes all the regions immediately', function() {
expect(this.app.getRegion('fooRegion')).to.deep.equal(this.fooRegion);
expect(this.app.getRegion('barRegion')).to.deep.equal(this.barRegion);
expect(this.app.getRegion('fooRegion')).to.be.instanceOf(Marionette.Region);
expect(this.app.getRegion('barRegion')).to.be.instanceOf(Marionette.Region);
});

it('uses the custom regionClass', function() {
Expand All @@ -401,7 +405,7 @@ describe('application regions', function() {
});

it('should make the region available as a named attribute', function() {
expect(this.app.fooRegion).to.deep.equal(this.fooRegion);
expect(this.app.fooRegion).to.be.instanceOf(Marionette.Region);
});

it('should be able to retrieve the region', function() {
Expand Down
8 changes: 4 additions & 4 deletions spec/javascripts/layoutView.dynamicRegions.spec.js
Expand Up @@ -36,13 +36,13 @@ describe('layoutView - dynamic regions', function() {
});

it('returns all the created regions on an object literal', function() {
expect(this.app.fooRegion).to.deep.equal(this.fooRegion);
expect(this.app.barRegion).to.deep.equal(this.barRegion);
expect(this.app.fooRegion).to.be.instanceOf(Marionette.Region);
expect(this.app.barRegion).to.be.instanceOf(Marionette.Region);
});

it('initializes all the regions immediately', function() {
expect(this.app.getRegion('fooRegion')).to.deep.equal(this.fooRegion);
expect(this.app.getRegion('barRegion')).to.deep.equal(this.barRegion);
expect(this.app.getRegion('fooRegion')).to.be.instanceOf(Marionette.Region);
expect(this.app.getRegion('barRegion')).to.be.instanceOf(Marionette.Region);
});

it('uses the custom regionClass', function() {
Expand Down
75 changes: 75 additions & 0 deletions spec/javascripts/layoutView.spec.js
Expand Up @@ -454,4 +454,79 @@ describe('layoutView', function() {
expect(this.regions.regionTwo).to.equal(this.layout.getRegion("regionTwo"));
});
});

describe("region events", function() {
beforeEach(function() {
var suite = this;
this.viewRegionShowSpy = sinon.spy();
this.regionShowSpy = sinon.spy();
this.regionShowSpy2 = sinon.spy();
this.regionShowSpy3 = sinon.spy();

this.ItemView = Marionette.ItemView.extend({
template: false
});

this.Layout = Marionette.LayoutView.extend({
template: suite.layoutViewManagerTemplateFn,
regionEvents: {
"view:show": suite.viewRegionShowSpy,
"show": suite.regionShowSpy
},

regions: {
"oneRegion": "#regionOne",
"twoRegion": "#regionTwo"
},

onShow: function() {
this.oneRegion.show(new suite.ItemView());
this.twoRegion.show(new suite.ItemView());
}
});

this.Layout2 = this.Layout.extend({
regionEvents: function() {
return {
"show": suite.regionShowSpy2
};
}
});

this.Layout3 = this.Layout.extend({
regionEvents: {
"show": "onRegionEventShow"
},
onRegionEventShow: suite.regionShowSpy3
});

this.layout = new this.Layout();
this.layout.render();
this.layout.triggerMethod("show");

this.layout2 = new this.Layout2();
this.layout2.render();
this.layout2.triggerMethod("show");

this.layout3 = new this.Layout3();
this.layout3.render();
this.layout3.triggerMethod("show");
});

it("should call show when views are shown within regions", function() {
expect(this.viewRegionShowSpy).to.have.been.calledTwice;
});

it("should call show on regions when views are shown within", function() {
expect(this.regionShowSpy).to.have.been.calledTwice;
});

it("should call regionEvents when defined as a hash", function() {
expect(this.regionShowSpy2).to.have.been.calledTwice;
});

it("should call regionEvents when as a string", function() {
expect(this.regionShowSpy3).to.have.been.calledTwice;
});
});
});
20 changes: 10 additions & 10 deletions spec/javascripts/regionManager.spec.js
Expand Up @@ -238,15 +238,15 @@ describe('regionManager', function() {
});

it('returns all the created regions on an object literal', function() {
expect(this.regions.fooRegion).to.deep.equal(this.fooRegion);
expect(this.regions.barRegion).to.deep.equal(this.barRegion);
expect(this.regions.bazRegion).to.deep.equal(this.bazRegion);
expect(this.regions.fooRegion).to.be.instanceof(Marionette.Region);
expect(this.regions.barRegion).to.be.instanceof(Marionette.Region);
expect(this.regions.bazRegion).to.be.instanceof(Marionette.Region);
});

it('adds all the specified regions', function() {
expect(this.regionManager.get('fooRegion')).to.deep.equal(this.fooRegion);
expect(this.regionManager.get('barRegion')).to.deep.equal(this.barRegion);
expect(this.regionManager.get('bazRegion')).to.deep.equal(this.bazRegion);
expect(this.regionManager.get('fooRegion')).to.be.instanceof(Marionette.Region);
expect(this.regionManager.get('barRegion')).to.be.instanceof(Marionette.Region);
expect(this.regionManager.get('bazRegion')).to.be.instanceof(Marionette.Region);
});

it('uses the custom `regionClass`', function() {
Expand Down Expand Up @@ -282,13 +282,13 @@ describe('regionManager', function() {
});

it('returns all the created regions on an object literal', function() {
expect(this.regionManager.get('fooRegion')).to.deep.equal(this.fooRegion);
expect(this.regionManager.get('barRegion')).to.deep.equal(this.barRegion);
expect(this.regionManager.get('fooRegion')).to.be.an.instanceOf(this.BazRegion);
expect(this.regionManager.get('barRegion')).to.be.an.instanceOf(this.BazRegion);
});

it('adds all the specified regions', function() {
expect(this.regionManager.get('fooRegion')).to.deep.equal(this.fooRegion);
expect(this.regionManager.get('barRegion')).to.deep.equal(this.barRegion);
expect(this.regionManager.get('fooRegion')).to.be.an.instanceof(Marionette.Region);
expect(this.regionManager.get('barRegion')).to.be.an.instanceof(Marionette.Region);
});

it('overrides the regionClass via defaults', function() {
Expand Down
17 changes: 17 additions & 0 deletions src/marionette.layoutview.js
Expand Up @@ -46,6 +46,7 @@ Marionette.LayoutView = Marionette.ItemView.extend({
if (this.isDestroyed) { return this; }

this.regionManager.destroy();

return Marionette.ItemView.prototype.destroy.apply(this, arguments);
},

Expand Down Expand Up @@ -139,6 +140,20 @@ Marionette.LayoutView = Marionette.ItemView.extend({
return new Marionette.RegionManager();
},

// Internal method to handle the dispatching of events
// that occured with a region or on a region to the top
// level `regionEvents` interface. This allows for an
// abstact event registration without having to reach
// into the internals of the regions `currentView`.
_onRegionsEvent: function(eventName) {
var regionEvents = this.normalizeMethods(
_.result(this, 'regionEvents')
);

if (regionEvents && regionEvents[eventName]) {
regionEvents[eventName].apply(this, arguments);
}
},
// Internal method to initialize the region manager
// and all regions in it
_initRegionManager: function() {
Expand All @@ -161,5 +176,7 @@ Marionette.LayoutView = Marionette.ItemView.extend({
delete this[name];
this.triggerMethod('remove:region', name, region);
});

this.listenTo(this.regionManager, 'all', this._onRegionsEvent);
}
});
10 changes: 9 additions & 1 deletion src/marionette.region.js
@@ -1,4 +1,4 @@
/* jshint maxcomplexity: 10, maxstatements: 29 */
/* jshint maxcomplexity: 10, maxstatements: 30 */

// Region
// ------
Expand Down Expand Up @@ -163,7 +163,9 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
// to the currentView since once a view has been destroyed
// we can not reuse it.
view.once('destroy', _.bind(this.empty, this));

view.render();
this.listenTo(view, 'all', this._onViewEvent);

if (isChangingView) {
this.triggerMethod('before:swap', view);
Expand Down Expand Up @@ -192,6 +194,12 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
return this;
},

_onViewEvent: function() {
var args = slice.apply(arguments);
args[0] = 'view:'+args[0];
this.trigger.apply(this, args);
},

_ensureElement: function(){
if (!_.isObject(this.el)) {
this.$el = this.getEl(this.el);
Expand Down
13 changes: 12 additions & 1 deletion src/marionette.regionManager.js
@@ -1,3 +1,5 @@
/* jshint maxstatements: 27 */

// Marionette.RegionManager
// ------------------------
//
Expand Down Expand Up @@ -53,6 +55,11 @@ Marionette.RegionManager = (function(Marionette) {
this._store(name, region);

this.triggerMethod('add:region', name, region);

if (region.on) {
this.listenTo(region, 'all', this._onRegionEvent);
}

return region;
},

Expand Down Expand Up @@ -115,6 +122,7 @@ Marionette.RegionManager = (function(Marionette) {
this.triggerMethod('before:remove:region', name, region);
region.empty();
region.stopListening();
this.off(region);
delete this._regions[name];
this._setLength();
this.triggerMethod('remove:region', name, region);
Expand All @@ -123,8 +131,11 @@ Marionette.RegionManager = (function(Marionette) {
// set the number of regions current held
_setLength: function() {
this.length = _.size(this._regions);
}
},

_onRegionEvent: function() {
this.trigger.apply(this, arguments);
}
});

Marionette.actAsCollection(RegionManager.prototype, '_regions');
Expand Down

0 comments on commit 48904ce

Please sign in to comment.