New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

marionette.toolkit

Package Overview
Dependencies
Maintainers
4
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

marionette.toolkit - npm Package Compare versions

Comparing version 0.3.0 to 0.4.0

packages/App/App.js

2

bower.json
{
"name": "marionette.toolkit",
"version": "0.3.0",
"version": "0.4.0",
"description": "A collection of opinionated Backbone.Marionette extensions for large scale application architecture.",

@@ -5,0 +5,0 @@ "main": "./dist/marionette.toolkit.js",

@@ -0,1 +1,9 @@

#### v0.4.0
* Toolkit now exports `App`, `Component` and `StateClass` to [npm separately](https://www.npmjs.com/browse/keyword/marionette.toolkit-modularized).
* `StateModel` can now be defined as a function returning a `Backbone.Model`
* A `Component` `ViewClass` can now be defined as a function returning a View
* If defining `childApps` as a function, it is now passed the same `options` as `initialize`
* Prevent an `App` from destroying more than once
#### v0.3.0

@@ -25,3 +33,3 @@

* Added `Toolkit.noConflict`
* `App` now has a `triggerStart` method that can be overridden to introduce async app starts.
* `App` now has a `triggerStart` method that can be overridden to introduce async app starts
* `App` `buildApp` is now easier to override

@@ -28,0 +36,0 @@ * `Component` `buildView` is now easier to override

/**
* marionette.toolkit - A collection of opinionated Backbone.Marionette extensions for large scale application architecture.
* @version v0.3.0
* @version v0.4.0
* @link https://github.com/RoundingWellOS/marionette.toolkit

@@ -34,3 +34,3 @@ * @license MIT

var StateModel = this.getStateModelClass();
var StateModel = this._getStateModel(options);

@@ -47,12 +47,24 @@ this._stateModel = new StateModel(_.result(this, "stateDefaults"));

* Get the StateClass StateModel class.
* If you need a dynamic StateModel override this function
* Checks if the `StateModel` is a model class (the common case)
* Then check if it's a function (which we assume that returns a model class)
*
* @public
* @abstract
* @method getStateModelClass
* @private
* @method _getStateModel
* @param {Object} [options] - Options that can be used to determine the StateModel.
* @memberOf StateClass
* @returns {Backbone.Model}
*/
getStateModelClass: function getStateModelClass() {
return this.StateModel;
_getStateModel: function _getStateModel(options) {
var StateModel = this.getOption("StateModel");
if (StateModel.prototype instanceof Backbone.Model || StateModel === Backbone.Model) {
return StateModel;
} else if (_.isFunction(StateModel)) {
return StateModel.call(this, options);
} else {
throw new Marionette.Error({
name: "InvalidStateModelError",
message: "\"StateModel\" must be a model class or a function that returns a model class"
});
}
},

@@ -106,4 +118,6 @@

var AbstractApp = StateClass.extend({
var state_class = StateClass;
var AbstractApp = state_class.extend({
/**

@@ -178,3 +192,3 @@ * Internal flag indiciate when `App` has started but has not yet stopped.

// Will call initialize
StateClass.call(this, options);
state_class.call(this, options);

@@ -305,7 +319,11 @@ if (_.result(this, "startAfterInitialized")) {

destroy: function destroy() {
this.stop();
if (this._isDestroyed) {
return;
}
this._isDestroyed = true;
StateClass.prototype.destroy.apply(this, arguments);
this.stop();
state_class.prototype.destroy.apply(this, arguments);
},

@@ -353,3 +371,3 @@

}
return StateClass.prototype.on.apply(this, arguments);
return state_class.prototype.on.apply(this, arguments);
},

@@ -371,3 +389,3 @@

}
return StateClass.prototype.listenTo.apply(this, arguments);
return state_class.prototype.listenTo.apply(this, arguments);
},

@@ -390,8 +408,10 @@

return StateClass.prototype.listenToOnce.apply(this, arguments);
return state_class.prototype.listenToOnce.apply(this, arguments);
}
});
var App = AbstractApp.extend({
var abstract_app = AbstractApp;
var App = abstract_app.extend({
/**

@@ -421,3 +441,3 @@ * @public

this._initChildApps();
this._initChildApps(options);

@@ -432,3 +452,3 @@ // The child apps should be handled while the app is running;

AbstractApp.call(this, options);
abstract_app.call(this, options);
},

@@ -443,5 +463,12 @@

*/
_initChildApps: function _initChildApps() {
if (this.childApps) {
this.addChildApps(_.result(this, "childApps"));
_initChildApps: function _initChildApps(options) {
var childApps = this.childApps;
if (childApps) {
if (_.isFunction(childApps)) {
childApps = childApps.call(this, options);
}
this.addChildApps(childApps);
}

@@ -720,4 +747,6 @@ },

var Component = StateClass.extend({
var app = App;
var Component = state_class.extend({
/**

@@ -763,3 +792,3 @@ * The view class to be managed.

StateClass.call(this, options);
state_class.call(this, options);

@@ -853,2 +882,30 @@ this._setStateDefaults(stateAttrs);

/**
* Get the Component ViewClass class.
* Checks if the `ViewClass` is a view class (the common case)
* Then check if it's a function (which we assume that returns a view class)
*
* @private
* @method _getViewClass
* @memberOf Component
* @param {Object} [options] - Options that can be used to determine the ViewClass.
* @returns {View}
*/
_getViewClass: function _getViewClass(options) {
options = options || {};
var ViewClass = this.getOption("ViewClass");
if (ViewClass.prototype instanceof Backbone.View || ViewClass === Backbone.View) {
return ViewClass;
} else if (_.isFunction(ViewClass)) {
return ViewClass.call(this, options);
} else {
throw new Marionette.Error({
name: "InvalidViewClassError",
message: "\"ViewClass\" must be a view class or a function that returns a view class"
});
}
},
/**
* Shows or re-shows a newly built view in the component's region

@@ -865,5 +922,7 @@ *

renderView: function renderView(options) {
var ViewClass = this._getViewClass(options);
var viewOptions = this.mixinOptions(options);
var view = this.buildView(this.ViewClass, viewOptions);
var view = this.buildView(ViewClass, viewOptions);

@@ -958,3 +1017,3 @@ // Attach current built view to component

if (this._shouldDestroy) {
StateClass.prototype.destroy.apply(this, arguments);
state_class.prototype.destroy.apply(this, arguments);
}

@@ -995,2 +1054,4 @@ },

var component = Component;
var previousToolkit = Marionette.Toolkit;

@@ -1005,8 +1066,10 @@

Toolkit.StateClass = StateClass;
Toolkit.VERSION = "0.4.0";
Toolkit.App = App;
Toolkit.StateClass = state_class;
Toolkit.Component = Component;
Toolkit.App = app;
Toolkit.Component = component;
var marionette_toolkit = Toolkit;

@@ -1013,0 +1076,0 @@

@@ -1,2 +0,8 @@

!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?module.exports=i(require("backbone.marionette"),require("underscore"),require("backbone")):"function"==typeof define&&define.amd?define(["backbone.marionette","underscore","backbone"],i):t.Marionette.Toolkit=i(t.Marionette,t._,t.Backbone)}(this,function(t,i,e){"use strict";var n=t.Object.extend({StateModel:e.Model,constructor:function(e){e=e||{},i.extend(this,i.pick(e,["StateModel","stateEvents","stateDefaults"]));var n=this.getStateModelClass();this._stateModel=new n(i.result(this,"stateDefaults")),this.bindEntityEvents(this._stateModel,i.result(this,"stateEvents")),t.Object.call(this,e)},getStateModelClass:function(){return this.StateModel},setState:function(){return this._stateModel.set.apply(this._stateModel,arguments)},getState:function(t){return t?this._stateModel.get.apply(this._stateModel,arguments):this._stateModel},destroy:function(){this._stateModel.stopListening(),t.Object.prototype.destroy.apply(this,arguments)}}),s=n.extend({_isRunning:!1,_isDestroyed:!1,preventDestroy:!1,startAfterInitialized:!1,startWithParent:!1,stopWithParent:!0,constructor:function(t){t=t||{},i.bindAll(this,"start","stop");var e=["startWithParent","stopWithParent","startAfterInitialized","preventDestroy"];i.extend(this,i.pick(t,e)),n.call(this,t),i.result(this,"startAfterInitialized")&&this.start(t)},_ensureAppIsIntact:function(){if(this._isDestroyed)throw new t.Error({name:"AppDestroyedError",message:"App has already been destroyed and cannot be used."})},isRunning:function(){return this._isRunning},start:function(t){return this._ensureAppIsIntact(),this._isRunning?this:(this.triggerMethod("before:start",t),this._isRunning=!0,this.triggerStart(t),this)},triggerStart:function(t){this.triggerMethod("start",t)},stop:function(t){return this._isRunning?(this.triggerMethod("before:stop",t),this._isRunning=!1,this.triggerMethod("stop",t),this._stopRunningListeners(),this._stopRunningEvents(),this):this},isDestroyed:function(){return this._isDestroyed},destroy:function(){this.stop(),this._isDestroyed=!0,n.prototype.destroy.apply(this,arguments)},_stopRunningEvents:function(){i.each(this._runningEvents,function(t){this.off.apply(this,t)},this)},_stopRunningListeners:function(){i.each(this._runningListeningTo,function(t){this.stopListening.apply(this,t)},this)},on:function(){return this._isRunning&&(this._runningEvents=this._runningEvents||[],this._runningEvents.push(arguments)),n.prototype.on.apply(this,arguments)},listenTo:function(){return this._isRunning&&(this._runningListeningTo=this._runningListeningTo||[],this._runningListeningTo.push(arguments)),n.prototype.listenTo.apply(this,arguments)},listenToOnce:function(){return this._isRunning&&(this._runningListeningTo=this._runningListeningTo||[],this._runningListeningTo.push(arguments)),n.prototype.listenToOnce.apply(this,arguments)}}),r=s.extend({constructor:function(t){t=t||{},this._childApps={},i.extend(this,i.pick(t,["childApps"])),this._initChildApps(),this.on({start:this._startChildApps,"before:stop":this._stopChildApps,"before:destroy":this._destroyChildApps}),s.call(this,t)},_initChildApps:function(){this.childApps&&this.addChildApps(i.result(this,"childApps"))},_startChildApps:function(){i.each(this._childApps,function(t){i.result(t,"startWithParent")&&t.start()})},_stopChildApps:function(){i.each(this._childApps,function(t){i.result(t,"stopWithParent")&&t.stop()})},_destroyChildApps:function(){i.each(this._childApps,function(t){i.result(t,"preventDestroy")||t.destroy()})},_buildAppFromObject:function(t){var e=t.AppClass,n=i.omit(t,"AppClass");return this.buildApp(e,n)},_buildApp:function(t,e){return i.isFunction(t)?this.buildApp(t,e):i.isObject(t)?this._buildAppFromObject(t):void 0},buildApp:function(t,i){return new t(i)},_ensureAppIsUnique:function(i){if(this._childApps[i])throw new t.Error({name:"DuplicateChildAppError",message:'A child App with name "'+i+'" has already been added.'})},addChildApps:function(t){i.each(t,function(t,i){this.addChildApp(i,t)},this)},addChildApp:function(e,n,s){this._ensureAppIsUnique(e);var r=this._buildApp(n,s);if(!r)throw new t.Error({name:"AddChildAppError",message:"App build failed. Incorrect configuration."});return r._name=e,this._childApps[e]=r,r.on("destroy",i.partial(this._removeChildApp,e),this),this.isRunning()&&i.result(r,"startWithParent")&&r.start(),r},getName:function(){return this._name},getChildApps:function(){return i.clone(this._childApps)},getChildApp:function(t){return this._childApps[t]},_removeChildApp:function(t){delete this._childApps[t]._name,delete this._childApps[t]},removeChildApps:function(){var t=this.getChildApps();return i.each(this._childApps,function(t,i){this.removeChildApp(i)},this),t},removeChildApp:function(t,e){e=e||{};var n=this.getChildApp(t);if(n)return e.preventDestroy||i.result(n,"preventDestroy")?this._removeChildApp(t):n.destroy(),n}}),o=n.extend({ViewClass:t.ItemView,viewEventPrefix:"view",viewOptions:{},constructor:function(t,e){e=e||{},i.extend(this,i.pick(e,["viewEventPrefix","ViewClass","viewOptions","region"])),n.call(this,e),this._setStateDefaults(t)},_shouldDestroy:!0,_setStateDefaults:function(t){this.setState(t,{silent:!0})},showIn:function(t,i){return this.region=t,this.show(i),this},show:function(i){if(this._isShown)throw new t.Error({name:"ComponentShowError",message:"Component has already been shown in a region."});if(!this.region)throw new t.Error({name:"ComponentRegionError",message:"Component has no defined region."});return this.triggerMethod("before:show"),this.renderView(i),this._isShown=!0,this.triggerMethod("show"),this.listenTo(this.region,"empty",this._destroy),this},renderView:function(t){var i=this.mixinOptions(t),e=this.buildView(this.ViewClass,i);return this.currentView=e,this._proxyViewEvents(e),this.triggerMethod("before:render:view",e),this._shouldDestroy=!1,this.region.show(e),this._shouldDestroy=!0,this.triggerMethod("render:view",e),this},_proxyViewEvents:function(t){var e=this.getOption("viewEventPrefix");t.on("all",function(){var n=i.toArray(arguments),s=n[0];n[0]=e+":"+s,n.splice(1,0,t),this.triggerMethod.apply(this,n)},this)},mixinOptions:function(t){var e=i.result(this,"viewOptions");return i.extend({stateModel:this.getState()},e,t)},buildView:function(t,i){return new t(i)},_destroy:function(){this._shouldDestroy&&n.prototype.destroy.apply(this,arguments)},_emptyRegion:function(t){this.region&&(this.stopListening(this.region,"empty"),this.region.empty(t))},destroy:function(t){this._emptyRegion(t),this._shouldDestroy=!0,this._destroy(t)}}),h=t.Toolkit,p=t.Toolkit={};p.noConflict=function(){return t.Toolkit=h,this},p.StateClass=n,p.App=r,p.Component=o;var u=p;return u});
/**
* marionette.toolkit - A collection of opinionated Backbone.Marionette extensions for large scale application architecture.
* @version v0.4.0
* @link https://github.com/RoundingWellOS/marionette.toolkit
* @license MIT
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("backbone.marionette"),require("underscore"),require("backbone")):"function"==typeof define&&define.amd?define(["backbone.marionette","underscore","backbone"],e):t.Marionette.Toolkit=e(t.Marionette,t._,t.Backbone)}(this,function(t,e,i){"use strict";var s=t.Object.extend({StateModel:i.Model,constructor:function(i){i=i||{},e.extend(this,e.pick(i,["StateModel","stateEvents","stateDefaults"]));var s=this._getStateModel(i);this._stateModel=new s(e.result(this,"stateDefaults")),this.bindEntityEvents(this._stateModel,e.result(this,"stateEvents")),t.Object.call(this,i)},_getStateModel:function(s){var n=this.getOption("StateModel");if(n.prototype instanceof i.Model||n===i.Model)return n;if(e.isFunction(n))return n.call(this,s);throw new t.Error({name:"InvalidStateModelError",message:'"StateModel" must be a model class or a function that returns a model class'})},setState:function(){return this._stateModel.set.apply(this._stateModel,arguments)},getState:function(t){return t?this._stateModel.get.apply(this._stateModel,arguments):this._stateModel},destroy:function(){this._stateModel.stopListening(),t.Object.prototype.destroy.apply(this,arguments)}}),n=s,r=n.extend({_isRunning:!1,_isDestroyed:!1,preventDestroy:!1,startAfterInitialized:!1,startWithParent:!1,stopWithParent:!0,constructor:function(t){t=t||{},e.bindAll(this,"start","stop");var i=["startWithParent","stopWithParent","startAfterInitialized","preventDestroy"];e.extend(this,e.pick(t,i)),n.call(this,t),e.result(this,"startAfterInitialized")&&this.start(t)},_ensureAppIsIntact:function(){if(this._isDestroyed)throw new t.Error({name:"AppDestroyedError",message:"App has already been destroyed and cannot be used."})},isRunning:function(){return this._isRunning},start:function(t){return this._ensureAppIsIntact(),this._isRunning?this:(this.triggerMethod("before:start",t),this._isRunning=!0,this.triggerStart(t),this)},triggerStart:function(t){this.triggerMethod("start",t)},stop:function(t){return this._isRunning?(this.triggerMethod("before:stop",t),this._isRunning=!1,this.triggerMethod("stop",t),this._stopRunningListeners(),this._stopRunningEvents(),this):this},isDestroyed:function(){return this._isDestroyed},destroy:function(){this._isDestroyed||(this._isDestroyed=!0,this.stop(),n.prototype.destroy.apply(this,arguments))},_stopRunningEvents:function(){e.each(this._runningEvents,function(t){this.off.apply(this,t)},this)},_stopRunningListeners:function(){e.each(this._runningListeningTo,function(t){this.stopListening.apply(this,t)},this)},on:function(){return this._isRunning&&(this._runningEvents=this._runningEvents||[],this._runningEvents.push(arguments)),n.prototype.on.apply(this,arguments)},listenTo:function(){return this._isRunning&&(this._runningListeningTo=this._runningListeningTo||[],this._runningListeningTo.push(arguments)),n.prototype.listenTo.apply(this,arguments)},listenToOnce:function(){return this._isRunning&&(this._runningListeningTo=this._runningListeningTo||[],this._runningListeningTo.push(arguments)),n.prototype.listenToOnce.apply(this,arguments)}}),o=r,h=o.extend({constructor:function(t){t=t||{},this._childApps={},e.extend(this,e.pick(t,["childApps"])),this._initChildApps(t),this.on({start:this._startChildApps,"before:stop":this._stopChildApps,"before:destroy":this._destroyChildApps}),o.call(this,t)},_initChildApps:function(t){var i=this.childApps;i&&(e.isFunction(i)&&(i=i.call(this,t)),this.addChildApps(i))},_startChildApps:function(){e.each(this._childApps,function(t){e.result(t,"startWithParent")&&t.start()})},_stopChildApps:function(){e.each(this._childApps,function(t){e.result(t,"stopWithParent")&&t.stop()})},_destroyChildApps:function(){e.each(this._childApps,function(t){e.result(t,"preventDestroy")||t.destroy()})},_buildAppFromObject:function(t){var i=t.AppClass,s=e.omit(t,"AppClass");return this.buildApp(i,s)},_buildApp:function(t,i){return e.isFunction(t)?this.buildApp(t,i):e.isObject(t)?this._buildAppFromObject(t):void 0},buildApp:function(t,e){return new t(e)},_ensureAppIsUnique:function(e){if(this._childApps[e])throw new t.Error({name:"DuplicateChildAppError",message:'A child App with name "'+e+'" has already been added.'})},addChildApps:function(t){e.each(t,function(t,e){this.addChildApp(e,t)},this)},addChildApp:function(i,s,n){this._ensureAppIsUnique(i);var r=this._buildApp(s,n);if(!r)throw new t.Error({name:"AddChildAppError",message:"App build failed. Incorrect configuration."});return r._name=i,this._childApps[i]=r,r.on("destroy",e.partial(this._removeChildApp,i),this),this.isRunning()&&e.result(r,"startWithParent")&&r.start(),r},getName:function(){return this._name},getChildApps:function(){return e.clone(this._childApps)},getChildApp:function(t){return this._childApps[t]},_removeChildApp:function(t){delete this._childApps[t]._name,delete this._childApps[t]},removeChildApps:function(){var t=this.getChildApps();return e.each(this._childApps,function(t,e){this.removeChildApp(e)},this),t},removeChildApp:function(t,i){i=i||{};var s=this.getChildApp(t);if(s)return i.preventDestroy||e.result(s,"preventDestroy")?this._removeChildApp(t):s.destroy(),s}}),a=h,p=n.extend({ViewClass:t.ItemView,viewEventPrefix:"view",viewOptions:{},constructor:function(t,i){i=i||{},e.extend(this,e.pick(i,["viewEventPrefix","ViewClass","viewOptions","region"])),n.call(this,i),this._setStateDefaults(t)},_shouldDestroy:!0,_setStateDefaults:function(t){this.setState(t,{silent:!0})},showIn:function(t,e){return this.region=t,this.show(e),this},show:function(e){if(this._isShown)throw new t.Error({name:"ComponentShowError",message:"Component has already been shown in a region."});if(!this.region)throw new t.Error({name:"ComponentRegionError",message:"Component has no defined region."});return this.triggerMethod("before:show"),this.renderView(e),this._isShown=!0,this.triggerMethod("show"),this.listenTo(this.region,"empty",this._destroy),this},_getViewClass:function(s){s=s||{};var n=this.getOption("ViewClass");if(n.prototype instanceof i.View||n===i.View)return n;if(e.isFunction(n))return n.call(this,s);throw new t.Error({name:"InvalidViewClassError",message:'"ViewClass" must be a view class or a function that returns a view class'})},renderView:function(t){var e=this._getViewClass(t),i=this.mixinOptions(t),s=this.buildView(e,i);return this.currentView=s,this._proxyViewEvents(s),this.triggerMethod("before:render:view",s),this._shouldDestroy=!1,this.region.show(s),this._shouldDestroy=!0,this.triggerMethod("render:view",s),this},_proxyViewEvents:function(t){var i=this.getOption("viewEventPrefix");t.on("all",function(){var s=e.toArray(arguments),n=s[0];s[0]=i+":"+n,s.splice(1,0,t),this.triggerMethod.apply(this,s)},this)},mixinOptions:function(t){var i=e.result(this,"viewOptions");return e.extend({stateModel:this.getState()},i,t)},buildView:function(t,e){return new t(e)},_destroy:function(){this._shouldDestroy&&n.prototype.destroy.apply(this,arguments)},_emptyRegion:function(t){this.region&&(this.stopListening(this.region,"empty"),this.region.empty(t))},destroy:function(t){this._emptyRegion(t),this._shouldDestroy=!0,this._destroy(t)}}),u=p,l=t.Toolkit,d=t.Toolkit={};d.noConflict=function(){return t.Toolkit=l,this},d.VERSION="0.4.0",d.StateClass=n,d.App=a,d.Component=u;var c=d;return c});
//# sourceMappingURL=marionette.toolkit.min.js.map

@@ -27,6 +27,7 @@ # Marionette.Toolkit.App

`childApps` can be passed to an `App` at instantiation or defined on the definition.
If defined as a function it will receive the `options` passed to the `constructor`.
```js
var MyApp = Marionette.Toolkit.App.extend({
childApps: function(){
childApps: function(options){
return {

@@ -33,0 +34,0 @@ childName: MyChildApp,

@@ -70,2 +70,20 @@ # Marionette.Toolkit.Component

```
You can also define `ViewClass` as a function. In this form, the value
returned by this method is the `ViewClass` class that will be instantiated.
When defined as a function, it will receive the `options` passed to [`renderView`](#component-renderview).
```js
var MyViewClass = Marionette.ItemView.extend({});
Marionette.Toolkit.Component.extend({
ViewClass: function(options){
if(options.foo){
return MyViewClass;
}
return Marionette.ItemView;
}
});
```
The `ViewClass` can be provided in the component definition or

@@ -72,0 +90,0 @@ in the constructor function call, to get a component instance.

@@ -13,3 +13,2 @@ # Marionette.Toolkit.StateClass

* [StateClass API](#stateclass-api)
* [StateClass `getStateModelClass`](#stateclass-getstatemodelclass)
* [Setting State `setState`](#setting-state)

@@ -33,8 +32,21 @@ * [Getting State `getState`](#getting-state)

The state model must be defined before it is referenced by the
`StateModel` attribute in a state class definition.
Use `getStateModelClass` to lookup the definition as state classes are instantiated.
You can also define `StateModel` as a function. In this form, the value
returned by this method is the `StateModel` class that will be instantiated.
When defined as a function, it will receive the `options` passed to the `constructor`.
```js
var MyStateModel = Backbone.Model.extend({});
Marionette.Toolkit.StateClass.extend({
StateModel: function(options){
if(options.foo){
return MyStateModel;
}
return Backbone.Model;
}
});
```
Alternatively, you can specify a `StateModel` in the options for
the constructor:
the `constructor`:

@@ -92,25 +104,2 @@ ```js

### StateClass `getStateModelClass`
The value returned by this method is the `StateModel` class that will be instantiated when a `StateClass` is instatiated.
Override this method for dynamic `StateModel` definitions.
```js
var FooModel = Backbone.Model.extend({});
var BarModel = Backbone.Model.extend({});
var MyStateClass = Marionette.Toolkit.StateClass.extend({
getStateModelClass: function() {
if(this.getOption('isFoo')) {
return FooModel;
}
else {
return BarModel;
}
}
});
var myFooStateClass = new MyStateClass({ isFoo: true });
var myBarStateClass = new MyStateClass();
```
### Setting State

@@ -117,0 +106,0 @@

@@ -14,3 +14,4 @@ var gulp = require('gulp');

const source = require('vinyl-source-stream');
const _ = require('lodash');
const Promise = require('bluebird');
const _ = require('underscore');

@@ -79,21 +80,34 @@ const manifest = require('./package.json');

// Build two versions of the library
gulp.task('build', ['lint-src', 'clean'], function(done) {
esperanto.bundle({
function _build(entryFileName, destFolder, expFileName, expVarName, umd){
return esperanto.bundle({
base: 'src',
entry: config.entryFileName,
entry: entryFileName,
transform: function(source) {
var js_source = _.template(source)(manifest);
// Poor way of modifying dependency for modular build
if(!umd){
return js_source.replace('./state-class', 'marionette.toolkit.state-class');
}
return js_source;
}
}).then(function(bundle) {
var res = bundle.toUmd({
banner: getBanner(),
var banner = getBanner();
var bundleMethod = umd? 'toUmd' : 'toCjs';
var res = bundle[bundleMethod]({
banner: banner,
sourceMap: true,
sourceMapSource: config.entryFileName + '.js',
sourceMapFile: exportFileName + '.js',
name: config.exportVarName
sourceMapSource: entryFileName + '.js',
sourceMapFile: expFileName + '.js',
name: expVarName
});
// Write the generated sourcemap
mkdirp.sync(destinationFolder);
fs.writeFileSync(path.join(destinationFolder, exportFileName + '.js'), res.map.toString());
mkdirp.sync(destFolder);
fs.writeFileSync(path.join(destFolder, expFileName + '.js'), res.map.toString());
$.file(exportFileName + '.js', res.code, { src: true })
$.file(expFileName + '.js', res.code, { src: true })
.pipe($.plumber())

@@ -103,14 +117,50 @@ .pipe($.sourcemaps.init({ loadMaps: true }))

.pipe($.sourcemaps.write('./', {addComment: false}))
.pipe(gulp.dest(destinationFolder))
.pipe(gulp.dest(destFolder))
.pipe($.filter(['*', '!**/*.js.map']))
.pipe($.rename(exportFileName + '.min.js'))
.pipe($.rename(expFileName + '.min.js'))
.pipe($.uglifyjs({
outSourceMap: true,
inSourceMap: destinationFolder + '/' + exportFileName + '.js.map',
inSourceMap: destFolder + '/' + expFileName + '.js.map',
}))
.pipe(gulp.dest(destinationFolder))
.on('end', done);
.pipe($.header(banner))
.pipe(gulp.dest(destFolder));
});
}
// Build two versions of the library
gulp.task('build-lib', ['lint-src', 'clean'], function() {
return _build(config.entryFileName, destinationFolder, exportFileName, config.exportVarName, 'umd');
});
function _buildPackage(destFolder, entryName, exportName){
var data = {
version: manifest.version,
exportVarName: exportName,
entryName: entryName,
dependencies: JSON.stringify(manifest.dependencies, null, 4)
};
gulp.src('./packages/LICENSE')
.pipe(gulp.dest(destFolder));
gulp.src('./packages/README.md')
.pipe($.template(data))
.pipe(gulp.dest(destFolder));
gulp.src('./packages/package.json')
.pipe($.template(data))
.pipe(gulp.dest(destFolder));
}
gulp.task('build-packages', ['lint-src', 'clean'], function() {
var tasks = _.map(config.exportPackageNames, function(entryName, exportName){
var destFolder = './packages/' + exportName + '/';
var exportVarName = 'Marionette.Toolkit.' + exportName;
return _build(entryName, destFolder, exportName, exportVarName)
.then(_.partial(_buildPackage, destFolder, entryName, exportName));
});
return Promise.all(tasks);
});
// Bundle our app for our unit tests

@@ -177,3 +227,5 @@ gulp.task('browserify', function() {

gulp.task('build', ['build-lib', 'build-packages']);
// An alias of test
gulp.task('default', ['test']);
{
"name": "marionette.toolkit",
"version": "0.3.0",
"version": "0.4.0",
"description": "A collection of opinionated Backbone.Marionette extensions for large scale application architecture.",

@@ -37,2 +37,3 @@ "main": "./dist/marionette.toolkit.js",

"babelify": "^5.0.3",
"bluebird": "^2.9.27",
"browserify": "^8.1.1",

@@ -47,2 +48,3 @@ "chai": "^2.0.0",

"gulp-filter": "^2.0.0",
"gulp-header": "^1.2.2",
"gulp-istanbul": "^0.6.0",

@@ -58,2 +60,3 @@ "gulp-jscs": "^1.4.0",

"gulp-sourcemaps": "^1.3.0",
"gulp-template": "^3.0.0",
"gulp-uglifyjs": "^0.6.0",

@@ -64,3 +67,2 @@ "isparta": "^2.2.0",

"jshint-stylish": "^1.0.0",
"lodash": "^3.2.0",
"mkdirp": "^0.5.0",

@@ -71,2 +73,3 @@ "mocha": "^2.1.0",

"sinon-chai": "^2.7.0",
"underscore": "^1.8.3",
"vinyl-source-stream": "^1.0.0"

@@ -77,2 +80,7 @@ },

"exportVarName": "Marionette.Toolkit",
"exportPackageNames": {
"App": "app",
"Component": "component",
"StateClass": "state-class"
},
"mochaGlobals": [

@@ -90,4 +98,4 @@ "stub",

"backbone": "1.0.0 - 1.1.2",
"underscore": "1.4.4 - 1.8.2"
"underscore": "1.4.4 - 1.8.3"
}
}

@@ -14,2 +14,3 @@ Marionette.Toolkit

In addition to the full library, each element in Toolkit is available as it's own [npm module](https://www.npmjs.com/browse/keyword/marionette.toolkit-modularized).

@@ -44,8 +45,13 @@ ## Documentation

**Via [npm](https://www.npmjs.com/package/marionette.toolkit)**
```
$ npm install marionette.toolkit
```
**Via [bower](http://bower.io/search/?q=marionette.toolkit)**
```
$ npm i marionette.toolkit
$ bower install marionette.toolkit
```
Currently Marionette.Toolkit is available via npm. If you would like add it to another channel, please
Currently Marionette.Toolkit is available via npm and bower. If you would like add it to another channel, please
[open an issue](#github-issues).

@@ -59,10 +65,11 @@

Marionette.Toolkit currently requires [Marionette](http://marionettejs.com) 2.1.0+ as it extends
Marionette.Toolkit currently requires [Marionette](http://marionettejs.com) 2.2.0+ as it utilizes [`Marionette.Error`](https://github.com/marionettejs/backbone.marionette/blob/v2.2.0/src/marionette.error.js) and extends
[`Marionette.Object`](https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.object.md)
It's possible this library would work with earlier versions by shimming
It's possible this library would work with earlier versions by manually adding `Marionette.Error` and shimming
`Marionette.Object = Marionette.Controller;`
This library is currently only tested with the latest version of Marionette.
This library is tested with v2.2+ and a mix of underscore and lodash versions.
Marionette.Toolkit supports IE8+ and modern browsers.

@@ -69,0 +76,0 @@

@@ -216,6 +216,10 @@ import _ from 'underscore';

destroy: function() {
this.stop();
if(this._isDestroyed) {
return;
}
this._isDestroyed = true;
this.stop();
StateClass.prototype.destroy.apply(this, arguments);

@@ -222,0 +226,0 @@ },

@@ -39,3 +39,3 @@ import _ from 'underscore';

this._initChildApps();
this._initChildApps(options);

@@ -60,5 +60,12 @@ // The child apps should be handled while the app is running;

*/
_initChildApps: function() {
if(this.childApps) {
this.addChildApps(_.result(this, 'childApps'));
_initChildApps: function(options) {
var childApps = this.childApps;
if(childApps) {
if(_.isFunction(childApps)) {
childApps = childApps.call(this, options);
}
this.addChildApps(childApps);
}

@@ -65,0 +72,0 @@ },

import _ from 'underscore';
import Backbone from 'backbone';
import Marionette from 'backbone.marionette';

@@ -144,2 +145,30 @@ import StateClass from './state-class';

/**
* Get the Component ViewClass class.
* Checks if the `ViewClass` is a view class (the common case)
* Then check if it's a function (which we assume that returns a view class)
*
* @private
* @method _getViewClass
* @memberOf Component
* @param {Object} [options] - Options that can be used to determine the ViewClass.
* @returns {View}
*/
_getViewClass: function(options) {
options = options || {};
var ViewClass = this.getOption('ViewClass');
if (ViewClass.prototype instanceof Backbone.View || ViewClass === Backbone.View) {
return ViewClass;
} else if (_.isFunction(ViewClass)) {
return ViewClass.call(this, options);
} else {
throw new Marionette.Error({
name: 'InvalidViewClassError',
message: '"ViewClass" must be a view class or a function that returns a view class'
});
}
},
/**
* Shows or re-shows a newly built view in the component's region

@@ -156,5 +185,7 @@ *

renderView: function(options){
var ViewClass = this._getViewClass(options);
var viewOptions = this.mixinOptions(options);
var view = this.buildView(this.ViewClass, viewOptions);
var view = this.buildView(ViewClass, viewOptions);

@@ -161,0 +192,0 @@ // Attach current built view to component

@@ -20,2 +20,4 @@ import Marionette from 'backbone.marionette';

Toolkit.VERSION = '<%= version %>';
Toolkit.StateClass = StateClass;

@@ -22,0 +24,0 @@

@@ -35,3 +35,3 @@ import _ from 'underscore';

var StateModel = this.getStateModelClass();
var StateModel = this._getStateModel(options);

@@ -48,12 +48,24 @@ this._stateModel = new StateModel(_.result(this, 'stateDefaults'));

* Get the StateClass StateModel class.
* If you need a dynamic StateModel override this function
* Checks if the `StateModel` is a model class (the common case)
* Then check if it's a function (which we assume that returns a model class)
*
* @public
* @abstract
* @method getStateModelClass
* @private
* @method _getStateModel
* @param {Object} [options] - Options that can be used to determine the StateModel.
* @memberOf StateClass
* @returns {Backbone.Model}
*/
getStateModelClass: function(){
return this.StateModel;
_getStateModel: function(options){
var StateModel = this.getOption('StateModel');
if (StateModel.prototype instanceof Backbone.Model || StateModel === Backbone.Model) {
return StateModel;
} else if (_.isFunction(StateModel)) {
return StateModel.call(this, options);
} else {
throw new Marionette.Error({
name: 'InvalidStateModelError',
message: '"StateModel" must be a model class or a function that returns a model class'
});
}
},

@@ -60,0 +72,0 @@

@@ -99,13 +99,32 @@ describe('App Manager', function() {

it('should accept a function', function() {
var childApps = function(){
return {
cA1: Marionette.Toolkit.App,
cA2: Marionette.Toolkit.App
describe('when passing childApps as a function', function() {
beforeEach(function () {
var childApps = function(){
return {
cA1: Marionette.Toolkit.App,
cA2: Marionette.Toolkit.App
};
};
};
this.myApp = new Marionette.Toolkit.App({ childApps: childApps });
this.MyApp2 = Marionette.Toolkit.App.extend({
childApps: childApps
});
});
expect(_.keys(this.myApp._childApps)).to.have.length(2);
it('should use the results of the childApps function', function() {
this.myApp = new this.MyApp2();
expect(_.keys(this.myApp._childApps)).to.have.length(2);
});
it('should pass options to childApps', function() {
var opts = { fooOption: 'bar' };
this.sinon.stub(this.MyApp2.prototype, 'childApps');
this.myApp = new this.MyApp2(opts);
expect(this.MyApp2.prototype.childApps)
.to.have.been.calledOnce
.and.calledWith(opts);
});
});

@@ -112,0 +131,0 @@ });

@@ -9,2 +9,3 @@ import AbstractApp from '../../src/abstract-app';

this.stopStub = this.sinon.stub();
this.destroyStub = this.sinon.stub();
this.myApp = new AbstractApp();

@@ -15,2 +16,3 @@ this.myApp.on('before:start', this.beforeStartStub);

this.myApp.on('stop', this.stopStub);
this.myApp.on('destroy', this.destroyStub);
});

@@ -75,13 +77,19 @@

describe('when an application is yet to be destroyed', function () {
it('should have isDestroyed() to return false', function () {
expect(this.myApp.isDestroyed()).to.equal(false);
});
});
describe('when destroying an application', function () {
beforeEach(function () {
this.myApp.start();
this.myApp.destroy();
});
it('should have isDestroyed() to return false PRIOR to destroying', function () {
expect(this.myApp.isDestroyed()).to.equal(false);
it('should be stopped', function () {
expect(this.stopStub).to.have.been.calledOnce;
});
it('should successfully be destroyed', function () {
this.myApp.destroy();
expect(this.myApp.isDestroyed()).to.equal(true);

@@ -92,3 +100,2 @@ });

it('should throw an error', function () {
this.myApp.destroy();
expect(_.bind(function(){

@@ -99,4 +106,15 @@ this.myApp.start();

});
describe('and destroying it again', function () {
beforeEach(function () {
this.myApp.destroy();
});
it('should not destroy', function () {
expect(this.destroyStub).to.have.not.been.calledTwice;
});
});
});
});

@@ -131,2 +131,41 @@ describe('Marionette.Toolkit.Component', function () {

// SETTING ViewClass
describe('when defining ViewClass as a function that returns a view class', function() {
beforeEach(function() {
this.MyComponent = Marionette.Toolkit.Component.extend({
region: this.myRegion,
ViewClass: function(options){
if(options.foo){
return Marionette.ItemView.extend({
customViewOption: 'bar',
template: _.template('<div></div>')
});
}
return Marionette.ItemView;
}
});
this.myComponent = new this.MyComponent();
this.myComponent.show({ foo: true });
});
it('should use the correct view class for passed options', function() {
expect(this.myComponent.currentView.getOption('customViewOption')).to.equal('bar');
});
});
describe('when defining ViewClass as neither a function or a class', function() {
beforeEach(function() {
this.MyComponent = Marionette.Toolkit.Component.extend({
region: this.myRegion,
ViewClass: 'Invalid View'
});
this.myComponent = new this.MyComponent();
});
it('should throw an error saying the ViewClass is invalid', function() {
expect(_.bind(this.myComponent.show, this.myComponent)).to.throw('"ViewClass" must be a view class or a function that returns a view class');
});
});
// INSTANTIATING A COMPONENT WITH OPTIONS

@@ -133,0 +172,0 @@ describe('when instantiating a component', function () {

@@ -47,8 +47,36 @@ describe('State Class', function() {

describe('when calling getStateModelClass()', function () {
it('should return the correct stateModel that will be used in instantiation', function () {
expect(this.myStateClass.getStateModelClass()).to.deep.equal(this.MyModel);
// SETTING StateModel
describe('when defining StateModel as a function that returns a model class', function() {
beforeEach(function() {
this.MyStateClass = Marionette.Toolkit.StateClass.extend({
StateModel: function(options){
if(options.foo){
return Backbone.Model.extend({
customAttr: 'bar'
});
}
return Backbone.Model;
}
});
this.myStateClass = new this.MyStateClass({ foo: true });
});
it('should use the correct model class for the passed options', function() {
expect(this.myStateClass.getState().customAttr).to.equal('bar');
});
});
describe('when defining StateModel as neither a function or a class', function() {
beforeEach(function() {
this.MyStateClass = Marionette.Toolkit.StateClass.extend({
StateModel: 'Invalid Class'
});
});
it('should throw an error saying the StateModel is invalid', function() {
expect(_.bind(function(){ this.myStateClass = new this.MyStateClass(); }, this)).to.throw('"StateModel" must be a model class or a function that returns a model class');
});
});
describe('when triggering a stateEvent', function () {

@@ -55,0 +83,0 @@ it('should call the correct stateEvent', function () {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc