Skip to content

Commit

Permalink
bump and build v1.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
samccone committed Mar 21, 2014
1 parent 59a3cf6 commit b945bc6
Show file tree
Hide file tree
Showing 13 changed files with 628 additions and 26 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"./lib/backbone.marionette.js",
"./lib/core/amd/backbone.marionette.js"
],
"version": "1.6.4",
"version": "1.7.0",
"keywords": [
"backbone",
"framework",
Expand Down
23 changes: 23 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
### v1.7.0 [view commit logs](https://github.com/marionettejs/backbone.marionette/compare/v1.6.4...v1.7.0)

Version 1.7 represents a significant step in formalizing the ways to improve your `view` code though reusable `behaviors`. Say goodbye to custom mixin strategies and welcome `behaviors` into town.

* Behaviors

A `Behavior` is an isolated set of DOM / user interactions interactions that can be mixed into any `View`. `Behaviors` allow you to blackbox `View` specific interactions into portable logical chunks, keeping your `views` simple and your code DRY. **[Read the docs here.](https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.behavior.md)**

* Modules
* Call stop listening on module stop.

* Events
* add a before:show event for views and regions

* Docs
* Entire refactor of application docs.

* Tests
* Rework the module tests to improve readability and consistency.

* General
* switch from `~` to `^` for *trusted* dependencies.

### v1.6.4 [view commit logs](https://github.com/marionettejs/backbone.marionette/compare/v1.6.3...v1.6.4)
* Fixes
* Patches a bug that would cause modules to be initialized twice when a custom module class is passed
Expand Down
2 changes: 1 addition & 1 deletion component.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "backbone.marionette",
"description": "Make your Backbone.js apps dance!",
"version": "1.6.4",
"version": "1.7.0",
"repo": "marionettejs/backbone.marionette",
"main": "lib/core/amd/backbone.marionette.js",
"keywords": [
Expand Down
203 changes: 198 additions & 5 deletions lib/backbone.marionette.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// MarionetteJS (Backbone.Marionette)
// ----------------------------------
// v1.6.4
// v1.7.0
//
// Copyright (c)2014 Derick Bailey, Muted Solutions, LLC.
// Distributed under MIT license
Expand Down Expand Up @@ -758,7 +758,8 @@ Marionette.Controller.extend = Marionette.extend;
_.extend(Marionette.Controller.prototype, Backbone.Events, {
close: function(){
this.stopListening();
this.triggerMethod("close");
var args = Array.prototype.slice.call(arguments);
this.triggerMethod.apply(this, ["close"].concat(args));
this.unbind();
}
});
Expand Down Expand Up @@ -892,6 +893,8 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
}

view.render();
Marionette.triggerMethod.call(this, "before:show", view);
Marionette.triggerMethod.call(view, "before:show");

if (isDifferentView || isViewClosed) {
this.open(view);
Expand Down Expand Up @@ -1224,6 +1227,10 @@ Marionette.View = Backbone.View.extend({
constructor: function(options){
_.bindAll(this, "render");

if (_.isObject(this.behaviors)) {
new Marionette.Behaviors(this);
}

// this exposes view options to the view initializer
// this is a backfill since backbone removed the assignment
// of this.options
Expand Down Expand Up @@ -1352,8 +1359,13 @@ Marionette.View = Backbone.View.extend({
if (_.isFunction(events)){ events = events.call(this); }

var combinedEvents = {};

// look up if this view has behavior events
var behaviorEvents = _.result(this, 'behaviorEvents') || {};
var triggers = this.configureTriggers();
_.extend(combinedEvents, events, triggers);

// behavior events will be overriden by view events and or triggers
_.extend(combinedEvents, behaviorEvents, events, triggers);

Backbone.View.prototype.delegateEvents.call(this, combinedEvents);
},
Expand All @@ -1378,9 +1390,11 @@ Marionette.View = Backbone.View.extend({
close: function(){
if (this.isClosed) { return; }

var args = Array.prototype.slice.call(arguments);

// allow the close to be stopped by returning `false`
// from the `onBeforeClose` method
var shouldClose = this.triggerMethod("before:close");
var shouldClose = this.triggerMethod.apply(this, ["before:close"].concat(args));
if (shouldClose === false){
return;
}
Expand All @@ -1389,7 +1403,7 @@ Marionette.View = Backbone.View.extend({
// prevent infinite loops within "close" event handlers
// that are trying to close other views
this.isClosed = true;
this.triggerMethod("close");
this.triggerMethod.apply(this, ["close"].concat(args));

// unbind UI elements
this.unbindUIElements();
Expand Down Expand Up @@ -2138,6 +2152,183 @@ Marionette.Layout = Marionette.ItemView.extend({
});


Marionette.Behavior = (function(_, Backbone){
function Behavior(options, view){
this.view = view;
this.defaults = _.result(this, "defaults") || {};
this.options = _.extend({}, this.defaults, options);

// proxy behavior $ method to the view
this.$ = function() {
return this.view.$.apply(this.view, arguments);
};

// proxy behavior $el method to the view
this.$el = function() {
return this.view.$el.apply(this.view, arguments);
};

this.initialize.apply(this, arguments);
}

_.extend(Behavior.prototype, {
initialize: function(){},

triggerMethod: Marionette.triggerMethod
});

// Borrow Backbones extend implementation
_.extend(Behavior, {
extend: Backbone.View.extend
});

return Behavior;
})(_, Backbone);

Marionette.Behaviors = (function(Marionette, _) {

function Behaviors(view) {
this.behaviors = Behaviors.parseBehaviors(view, view.behaviors);

Behaviors.wrap(view, this.behaviors, [
'bindUIElements', 'unbindUIElements',
'delegateEvents', 'undelegateEvents',
'onShow', 'onClose',
'behaviorEvents', 'triggerMethod'
]);
}

var methods = {
onShow: function(onShow, behaviors) {
var args = _.tail(arguments, 2);

_.each(behaviors, function(b) {
Marionette.triggerMethod.apply(b, ["show"].concat(args));
});

if (_.isFunction(onShow)) {
onShow.apply(this, args);
}
},

onClose: function(onClose, behaviors){
var args = _.tail(arguments, 2);

_.each(behaviors, function(b) {
Marionette.triggerMethod.apply(b, ["close"].concat(args));
});

if (_.isFunction(onClose)) {
onClose.apply(this, args);
}
},

bindUIElements: function(bindUIElements, behaviors) {
bindUIElements.apply(this);
_.invoke(behaviors, bindUIElements);
},

unbindUIElements: function(unbindUIElements, behaviors) {
unbindUIElements.apply(this);
_.invoke(behaviors, unbindUIElements);
},

triggerMethod: function(triggerMethod, behaviors) {
var args = _.tail(arguments, 2);
triggerMethod.apply(this, args);

_.each(behaviors, function(b) {
triggerMethod.apply(b, args);
});
},

delegateEvents: function(delegateEvents, behaviors) {
var args = _.tail(arguments, 2);
delegateEvents.apply(this, args);

_.each(behaviors, function(b){
Marionette.bindEntityEvents(this, this.model, Marionette.getOption(b, "modelEvents"));
Marionette.bindEntityEvents(this, this.collection, Marionette.getOption(b, "collectionEvents"));
}, this);
},

undelegateEvents: function(undelegateEvents, behaviors) {
var args = _.tail(arguments, 2);
undelegateEvents.apply(this, args);

_.each(behaviors, function(b) {
Marionette.unbindEntityEvents(this, this.model, Marionette.getOption(b, "modelEvents"));
Marionette.unbindEntityEvents(this, this.collection, Marionette.getOption(b, "collectionEvents"));
}, this);
},

behaviorEvents: function(behaviorEvents, behaviors) {
var _behaviorsEvents = {};

_.each(behaviors, function(b, i) {
var behaviorEvents = _.result(b, 'events') || {};
var _events = {};

_.each(_.keys(behaviorEvents), function(key) {
// append white-space at the end of each key to prevent behavior key collisions
// this is relying on the fact backbone events considers "click .foo" the same "click .foo "
var whitespace = (new Array(i+1)).join(" ");
_events[key + whitespace] = behaviorEvents[key];
});

_behaviorsEvents = _.extend(_behaviorsEvents, _events);
});

return _behaviorsEvents;
}
};

_.extend(Behaviors, {

// placeholder method to be extended by the user
// should define the object that stores the behaviors
// i.e.
//
// Marionette.Behaviors.behaviorsLookup: function() {
// return App.Behaviors
// }
behaviorsLookup: function() {
throw new Error("You must define where your behaviors are stored. See https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.behaviors.md#behaviorslookup");
},

getBehaviorClass: function(options, key) {
if (options.behaviorClass) {
return options.behaviorClass;
}

// Get behavior class can be either a flat object or a method
return _.isFunction(Behaviors.behaviorsLookup) ? Behaviors.behaviorsLookup.apply(this, arguments)[key] : Behaviors.behaviorsLookup[key];
},

parseBehaviors: function(view, behaviors){
return _.map(behaviors, function(options, key){
var BehaviorClass = Behaviors.getBehaviorClass(options, key);
return new BehaviorClass(options, view);
});
},

// wrap view internal methods so that they delegate to behaviors.
// For example, onClose should trigger close on all of the behaviors and then close itself.
// i.e.
//
// view.delegateEvents = _.partial(methods.delegateEvents, view.delegateEvents, behaviors);
wrap: function(view, behaviors, methodNames) {
_.each(methodNames, function(methodName) {
view[methodName] = _.partial(methods[methodName], view[methodName], behaviors);
});
}
});

return Behaviors;

})(Marionette, _);


// AppRouter
// ---------

Expand Down Expand Up @@ -2402,6 +2593,8 @@ _.extend(Marionette.Module.prototype, Backbone.Events, {
this._initializerCallbacks.reset();
this._finalizerCallbacks.reset();

this.stopListening();

Marionette.triggerMethod.call(this, "stop");
},

Expand Down
2 changes: 1 addition & 1 deletion lib/backbone.marionette.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions lib/backbone.marionette.min.js

Large diffs are not rendered by default.

Loading

0 comments on commit b945bc6

Please sign in to comment.