Skip to content

Commit

Permalink
Merge d70f25e into 1d9fe2d
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesplease committed Feb 4, 2015
2 parents 1d9fe2d + d70f25e commit 2dca103
Show file tree
Hide file tree
Showing 15 changed files with 253 additions and 274 deletions.
7 changes: 4 additions & 3 deletions api/item-view.yaml
Expand Up @@ -6,11 +6,12 @@ extends:
- Marionette.AbstractView

description: |
An `ItemView` is a view that represents a single item. That item may be a `Backbone.Model` or may be a `Backbone.Collection`. Whichever it is though, it will be treated as a single item.
An `ItemView` is the basic view of Marionette. It can be used to render a Model or Collection. In addition, ItemViews can create and manage child views through the use of
[Regions]((marionette.region.md)). Regions are containers for child views.
Please see [the Marionette.AbstractView documentation](marionette.Abstractview.md) for more information on available features and functionality.
ItemView extends from AbstractView. For the full API, refer to [the Marionette.AbstractView documentation](marionette.abstractview.md) for inherited methods and properties.
Additionally, interactions with Marionette.Region will provide features such as `onShow` callbacks, etc. Please see [the Region documentation](marionette.region.md) for more information.
Unlike Backbone Views, the ItemView Class emits many events. These are most often triggered when a ItemView is displayed as a child within another ItemView or CollectionView.
constructor:
description: |
Expand Down
1 change: 0 additions & 1 deletion src/build/bundled.js
Expand Up @@ -57,7 +57,6 @@
// @include ../item-view.js
// @include ../collection-view.js
// @include ../composite-view.js
// @include ../layout-view.js

// @include ../behavior.js
// @include ../behaviors.js
Expand Down
1 change: 0 additions & 1 deletion src/build/core.js
Expand Up @@ -52,7 +52,6 @@
// @include ../item-view.js
// @include ../collection-view.js
// @include ../composite-view.js
// @include ../layout-view.js

// @include ../behavior.js
// @include ../behaviors.js
Expand Down
142 changes: 138 additions & 4 deletions src/item-view.js
@@ -1,14 +1,19 @@
// Item View
// ---------

// A single item view implementation that contains code for rendering
// with underscore.js templates, serializing the view's model or collection,
// and calling several methods on extended views, such as `onRender`.
// The standard view. Includes view events, automatic rendering
// of Underscore templates, nested views, and more.
Marionette.ItemView = Marionette.AbstractView.extend({
regionClass: Marionette.Region,

// Setting up the inheritance chain which allows changes to
// Marionette.AbstractView.prototype.constructor which allows overriding
constructor: function() {
constructor: function(options) {
options = options || {};

this._firstRender = true;
this._initializeRegions(options);

Marionette.AbstractView.apply(this, arguments);
},

Expand Down Expand Up @@ -45,9 +50,21 @@ Marionette.ItemView = Marionette.AbstractView.extend({
// a very specific rendering for your view. In general, though,
// you should override the `Marionette.Renderer` object to
// change how Marionette renders views.
// Subsequent renders after the first will re-render all nested
// views.
render: function() {
this._ensureViewIsIntact();

if (this._firstRender) {
// if this is the first render, don't do anything to
// reset the regions
this._firstRender = false;
} else {
// If this is not the first render call, then we need to
// re-initialize the `el` for each region
this._reInitializeRegions();
}

this.triggerMethod('before:render', this);

this._renderTemplate();
Expand Down Expand Up @@ -105,5 +122,122 @@ Marionette.ItemView = Marionette.AbstractView.extend({
this.$el.html(html);

return this;
},

// Add a single region, by name, to the layoutView
addRegion: function(name, definition) {
var regions = {};
regions[name] = definition;
return this._buildRegions(regions)[name];
},

// Add multiple regions as a {name: definition, name2: def2} object literal
addRegions: function(regions) {
this.regions = _.extend({}, this.regions, regions);
return this._buildRegions(regions);
},

// Remove a single region from the LayoutView, by name
removeRegion: function(name) {
delete this.regions[name];
return this.regionManager.removeRegion(name);
},

// Provides alternative access to regions
// Accepts the region name
// getRegion('main')
getRegion: function(region) {
return this.regionManager.get(region);
},

// Get all regions
getRegions: function(){
return this.regionManager.getRegions();
},

// Enable easy overriding of the default `RegionManager`
// for customized region interactions and business specific
// view logic for better control over single regions.
getRegionManager: function() {
return new Marionette.RegionManager();
},

// Handle destroying regions, and then destroy the view itself.
destroy: function() {
if (this.isDestroyed) { return this; }

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

// Internal method to initialize the regions that have been defined in a
// `regions` attribute on this layoutView.
_initializeRegions: function(options) {
var regions;
this._initRegionManager();

regions = Marionette._getValue(this.regions, this, [options]) || {};

// Enable users to define `regions` as instance options.
var regionOptions = this.getOption.call(options, 'regions');

// enable region options to be a function
regionOptions = Marionette._getValue(regionOptions, this, [options]);

_.extend(regions, regionOptions);

// Normalize region selectors hash to allow
// a user to use the @ui. syntax.
regions = this.normalizeUIValues(regions);

this.addRegions(regions);
},

// internal method to build regions
_buildRegions: function(regions) {
var defaults = {
regionClass: this.getOption('regionClass'),
parentEl: _.partial(_.result, this, 'el')
};

return this.regionManager.addRegions(regions, defaults);
},

// Internal method to re-initialize all of the regions by updating
// the `el` that they point to
_reInitializeRegions: function() {
this.regionManager.invoke('reset');
},

// Internal method to initialize the region manager
// and all regions in it
_initRegionManager: function() {
this.regionManager = this.getRegionManager();
this.regionManager._parent = this;

this.listenTo(this.regionManager, 'before:add:region', function(name) {
this.triggerMethod('before:add:region', name);
});

this.listenTo(this.regionManager, 'add:region', function(name, region) {
this[name] = region;
this.triggerMethod('add:region', name, region);
});

this.listenTo(this.regionManager, 'before:remove:region', function(name) {
this.triggerMethod('before:remove:region', name);
});

this.listenTo(this.regionManager, 'remove:region', function(name, region) {
delete this[name];
this.triggerMethod('remove:region', name, region);
});
},

_getImmediateChildren: function() {
return _.chain(this.regionManager.getRegions())
.pluck('currentView')
.compact()
.value();
}
});
160 changes: 0 additions & 160 deletions src/layout-view.js

This file was deleted.

4 changes: 2 additions & 2 deletions test/unit/behaviors.spec.js
Expand Up @@ -377,12 +377,12 @@ describe('Behaviors', function() {

describe('within a layout', function() {
beforeEach(function() {
this.LayoutView = Marionette.LayoutView.extend({
this.ItemView = Marionette.ItemView.extend({
template: _.template('<div class="baz"></div>'),
regions: { bazRegion: '.baz' }
});

this.layoutView = new this.LayoutView();
this.layoutView = new this.ItemView();
this.layoutView.render();
this.layoutView.bazRegion.show(new this.View());
this.layoutView.destroy();
Expand Down
7 changes: 7 additions & 0 deletions test/unit/collection-view.spec.js
Expand Up @@ -11,6 +11,13 @@ describe('collection view', function() {
this.$el.html(this.model.get('foo'));
this.trigger('render');
},
// Init region manager creates a circular reference, which
// explodes Sinon's deep equals assertion. These tests
// do not care if the view has a region manager or not.
_initializeRegions: function() {},
// The ItemView's destroy method tries to destroy the
// RegionManager, which, from the above, does not exist.
destroy: Marionette.AbstractView.prototype.destroy,
onRender: function() {}
});

Expand Down

0 comments on commit 2dca103

Please sign in to comment.