Socket
Socket
Sign inDemoInstall

mvc-pack

Package Overview
Dependencies
3
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.11.0 to 0.12.0

376

dest/mvc-pack.js

@@ -5,4 +5,4 @@ (function (root, factory) {

// AMD. Register as an anonymous module unless amdModuleId is set
define(["class-wrapper","lodash"], function (a0,b1) {
return (root['mvc-pack'] = factory(a0,b1));
define(["class-wrapper","@valerii-zinchenko/observer","lodash"], function (a0,b1,c2) {
return (root['mvc-pack'] = factory(a0,b1,c2));
});

@@ -13,11 +13,11 @@ } else if (typeof module === 'object' && module.exports) {

// like Node.
module.exports = factory(require("class-wrapper"),require("lodash"));
module.exports = factory(require("class-wrapper"),require("@valerii-zinchenko/observer"),require("lodash"));
} else {
root['mvc-pack'] = factory(root["class-wrapper"],root["_"]);
root['mvc-pack'] = factory(root["class-wrapper"],root["Observer"],root["_"]);
}
}(this, function (ClassWrapper, _) {
}(this, function (ClassWrapper, Observer, _) {
// Package of combined patterns to build rich MVC modules
// v0.11.0
// Copyright (c) 2016-2017 Valerii Zinchenko
// v0.12.0
// Copyright (c) 2016-2019 Valerii Zinchenko
// Licensed under MIT (http://valerii-zinchenko.github.io/mvc-pack/blob/master/LICENSE.txt)

@@ -44,3 +44,2 @@ // All source files are available at https://github.com/valerii-zinchenko/mvc-pack

var Class = ClassWrapper.Class;
var SingletonClass = ClassWrapper.SingletonClass;

@@ -115,3 +114,3 @@ /*

*
* @version 3.0.1
* @version 3.1.0
*/

@@ -133,3 +132,10 @@

}
// Automatically bind all defined function to "this" and store them into "this" under the same name
Object.keys(this._bind2this).forEach(function(name) {
this[name] = this._bind2this[name].bind(this);
}, this);
}, /** @lends AModeComponent.prototype */{
__name: 'AModeComponent',
/**

@@ -150,2 +156,11 @@ * Reference to the model.

/**
* Set of function, which will be bound automatically to "this" by constructing an instance.
* This is most useful for event handlers, which in most cases should have the context of current class.
* Be careful, as that can overwrite other properties/methods defined in the class.
*
* @type {Object}
*/
_bind2this: {},
/**
* Connect view component to the module.

@@ -200,3 +215,3 @@ * This is called after constructor and setting of the model and control components.

*
* @version 2.0.0
* @version 3.0.0
*/

@@ -212,30 +227,16 @@

* @extends AModeComponent
* @mixes Observer
*/
var AControl = Class(AModeComponent, null, /** @lends AControl.prototype */{
/**
* Reference to the view.
*/
view: null,
__name: 'AControl',
Encapsulate: [Observer],
/**
* Control destructor.
* Control destructor
*/
destruct: function() {
this.view = null;
this._events = {};
AModeComponent.prototype.destruct.call(this);
},
/**
* Set view
*
* @param {Object} view - View
*
* @throws {Error} Incorrect type of view component
*/
setView: function(view) {
if (!(view instanceof AView)) {
throw new Error('Incorrect type of view component');
}
this.view = view;
}

@@ -278,2 +279,4 @@ });

var AView = Class(AModeComponent, null, /** @lends AView.prototype */{
__name: 'AView',
/**

@@ -323,2 +326,33 @@ * Reference to the control.

/**
* Insert additionl module into current view
*
* @param {DOMElement} container - Container element, where the module is going to be inserted. This should be empty, because it will be emptied before insertion
* @param {AView} view - View to insert
*/
insertView: function(container, view) {
// cleanup the container
while (container.firstChild) {
container.removeChild(container.firstChild);
}
this.appendView(container, view);
},
/**
* Appends the view's elements into the container
*
* @param {DOMElement} container - Container element, where the module is going to be inserted. This should be empty, because it will be emptied before insertion
* @param {AView} view - View to insert
*/
appendView: function(container, view) {
// insert view's elements
for (var n = 0, N = view.elements.length; n < N; n++) {
container.appendChild(view.elements[n]);
}
view.update();
},
/**
* Initialize required for view elements.

@@ -360,3 +394,3 @@ */

* Static view.
* It implements parent's [render()]{@link render} method to initalize required elements and attach eventh.
* It implements parent's [render()]{@link render} method to initialize required elements and attach events.
*

@@ -366,5 +400,7 @@ * @class

*/
var StaticView = SingletonClass(AView, function() {
var StaticView = Class(AView, function() {
this.element = document.querySelector(this.selector);
}, /** @lends StaticView.prototype */{
__name: 'StaticView',
/**

@@ -447,2 +483,4 @@ * Selector of a static element from a DOM

var DynamicView = Class(AView, null, /** @lends DynamicView.prototype */{
__name: 'DynamicView',
/**

@@ -534,2 +572,4 @@ * Main template.

var ADecorator = Class(DynamicView, null, /** @lends ADecorator.prototype */{
__name: 'ADecorator',
template: '<div data-mvc-container></div>',

@@ -620,10 +660,11 @@

*
* @see {@link AFMode}
* @see {@link AModeComponent}
* @see {@link AView}
* @see {@link AControl}
* @see {@link AFMode}
* @see {@link ADecorator}
*
* @author Valerii Zinchenko
*
* @version 5.0.0
* @version 6.0.0
*/

@@ -637,13 +678,17 @@

* @class
* @param {Object} properties - Mode's properties.
* @param {Object} properties.model - Model.
* @param {AView} properties.view - Main mode's view.
* @param {AControl} [properties.control] - Mode's control.
* @param {Object} [properties.decorators] - Object of decorators for a view, where the key is a decorator name and value is a decorator.
*
* @throws {Error} Incorrect type of the mode's properties. Expected: Object
* @throws {Error} Incorrect type of the model. Expected: Object
* @throws {Error} View should be inherited from AView
* @throws {Error} Decorator "{name}" should be inherited from ADecorator
* @throws {Error} Incorrect type of a view's constructor. Expected: Function
* @throws {Error} Incorrect type of a control's constructor. Expected: Function
* @throws {Error} Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor
* @throws {Error} Incorrect type of a decorator's constructor "{name}". Expected: Function
* @throws {Error} Control should be inherited from AControl
*
* @param {Object} properties - Mode's properties.
* @param {Object} properties.model - Model.
* @param {Function} properties.View - Constructor for the view component.
* @param {Function} [properties.Control] - Constructor for the control component.
* @param {Object} [properties.Decorators] - Map of decorators' names and decorators' construstors for a new mode.
* @param {Object} [properties.config] - Configurations for control, view and decorator components.
*/

@@ -654,37 +699,50 @@ var Mode = Class(function(properties) {

}
if (!utils.is(properties.model, 'Object')) {
if (utils.is(properties.model, 'Object')) {
this.model = properties.model;
} else {
throw new Error('Incorrect type of the model. Expected: Object');
}
if (!(properties.view instanceof AView)) {
throw new Error('View should be inherited from AView');
if (utils.is(properties.View, 'Function')) {
this.View = properties.View;
} else {
throw new Error('Incorrect type of a view\'s constructor. Expected: Function');
}
this.model = properties.model;
this._view = properties.view;
if (properties.Decorators) {
if (!utils.is(properties.Decorators, 'Object')) {
throw new Error('Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor');
}
if (properties.decorators && utils.is(properties.decorators, 'Object')) {
for (var key in properties.decorators) {
if ( !(properties.decorators[key] instanceof ADecorator) ) {
throw new Error('Decorator "' + key + '" should be inherited from ADecorator');
for (var key in properties.Decorators) {
if (!utils.is(properties.Decorators[key], 'Function')) {
throw new Error('Incorrect type of a decorator\'s constructor "' + key + '". Expected: Function');
}
}
this._decorators[key] = properties.decorators[key];
}
this.Decorators = properties.Decorators;
}
if (properties.control) {
if ( !(properties.control instanceof AControl) ) {
this.config = properties.config;
if (properties.Control) {
if (!utils.is(properties.Control, 'Function')) {
throw new Error('Incorrect type of a control\'s constructor. Expected: Function');
}
var control = new properties.Control(this.config);
if ( !(control instanceof AControl) ) {
throw new Error('Control should be inherited from AControl');
}
this.control = properties.control;
this.control = control;
this.control.setModel(this.model);
this.control.connect();
}
}, /** @lends Mode.prototype */{
__name: 'Mode',
this.view = this._view;
this.connect();
}, /** @lends Mode.prototype */{
/**
* Reference to the model.
*
* @type {Objcet}

@@ -695,18 +753,15 @@ */

/**
* Reference to the main view.
*
* @type {AView}
* View constructor
* @type {Function}
*/
_view: null,
View: null,
/**
* Current view. This can be an original or decorated view.
*
* @type {DynamicView}
* Map of decorators' names and decorators' construstors for a new mode
* @type {Object}
*/
view: null,
Decorators: {},
/**
* Reference to the control.
*
* @type {AControl}

@@ -717,74 +772,91 @@ */

/**
* Object of decorators, where the key is a name of a deocorator and value is a decorator object.
*
* Map of usages and created views for it
* @type {Object}
*/
_decorators: {},
_usages: {},
/**
* This indicates if a mode components are already connected or not.
* Get an instance of the view for a specific usage.
*
* @type {Boolean}
* For each usage a new instance of the view will be created and, if needed, decorated also with new instances of decorators.
* This allows to use the same view in different places with or without different decorators.
*
* @throws {Error} View should be inherited from AView
* @throws {Error} Decorator "{name}" should be inherited from ADecorator
*
* @param {String} [usage = 'default'] - Define for how/where he view is going to be used. For different usages different instances of a view and decorators will be created.
* @param {String[] | String} [decorators] - An array of decorators name or a single decorator name. Decorators will be applied in the same order as they are defined.
*/
_isConnected: false,
getView: function(usage, decorations) {
if (!usage) {
usage = 'default';
}
if (this._usages[usage]) {
return this._usages[usage];
}
/**
* Connect mode components
*/
connect: function() {
if (this._isConnected) {
return;
var view = new this.View(this.config);
if (!(view instanceof AView)) {
throw new Error('View should be inherited from AView');
}
this._view.setModel(this.model);
view.setModel(this.model);
if (this.control) {
this._view.setControl(this.control);
this.control.setModel(this.model);
this.control.setView(this._view);
this.control.connect();
view.setControl(this.control);
}
this._view.connect();
this._view.render();
view.connect();
view.render();
view = this.decorate(view, decorations);
var decorator;
for (var key in this._decorators) {
decorator = this._decorators[key];
decorator.setModel(this.model);
decorator.render();
}
this._usages[usage] = view;
this._isConnected = true;
return view;
},
/**
* Apply decorators to the original view.
* Apply decorators to a view.
*
* @param {String[] | String } decorators - An array of decorators name or a single decorator name. Decorators will be applied in the same order as they are defined.
* @throws {Error} View should be inherited from AView
* @throws {Error} Constructor for decorator "{name}" is not defined
* @throws {Error} Decorator "{name}" should be inherited from ADecorator
*
* @param {AView} view - View, which should be decorated.
* @param {String[] | String} decorators - An array of decorators name or a single decorator name. Decorators will be applied in the same order as they are defined.
* @return {Aview}
*/
decorateWith: function(decorators){
if (!decorators) {
return;
decorate: function(view, decorators){
if (!(view instanceof AView)) {
throw new Error('View should be inherited from AView');
}
if (this.Decorators.length === 0 || !decorators) {
return view;
}
if (utils.is(decorators, 'String')){
this.decorateWith([decorators]);
return;
decorators = [decorators];
}
var v = this._view;
var v = view;
var decorator;
var Constructor;
for (var n = 0, N = decorators.length; n < N; n++) {
Constructor = this.Decorators[decorators[n]];
if (!Constructor) {
throw new Error('Constructor for decorator "' + decorators[n] + '" is not defined');
}
if (this._decorators && decorators.length > 0) {
var decorator;
for (var n = 0, N = decorators.length; n < N; n++) {
decorator = this._decorators[decorators[n]];
if (decorator) {
decorator.setComponent(v);
decorator = new Constructor(this.config);
v = decorator;
}
if ( !(decorator instanceof ADecorator) ) {
throw new Error('Decorator "' + decorators[n] + '" should be inherited from ADecorator');
}
decorator.setComponent(v);
decorator.setModel(this.model);
decorator.render();
v = decorator;
}
this.view = v;
return v;
}

@@ -804,5 +876,5 @@ });

/**
* @file It contains the implementation of [abstract mode factory]{@link AFMode} that returns [mode builder]{@link BMode}.
* @file It contains the implementation of [abstract mode factory]{@link AFMode} that returns [mode builder]{@link FMode}.
*
* @see {@link BMode}
* @see {@link FMode}
* @see {@link Mode}

@@ -812,3 +884,3 @@ *

*
* @version 3.0.0
* @version 4.0.0
*/

@@ -823,6 +895,2 @@

* @throws {Error} Incorrect type of the constructors. Object expected.
* @throws {Error} Incorrect type of a view's constructor. Expected: Function
* @throws {Error} Incorrect type of a control's constructor. Expected: Function
* @throws {Error} Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor
* @throws {Error} Incorrect type of a decorator's constructor "{name}". Expected: Function
*

@@ -832,4 +900,4 @@ * @param {Object} Constructors - Collection of constructors for a mode.

* @param {Function} [Constructors.Control] - Constructor for the control component.
* @param {Object} [Constructors.Decorators] - Map of decorators' names and decorators' construstors for a new mode. If some constructor is not a function, then it will be skipped in order to avoid NPE
* @return {BMode} Mode builder.
* @param {Object} [Constructors.Decorators] - Map of decorators' names and decorators' constructors for a new mode. If some constructor is not a function, then it will be skipped in order to avoid NPE
* @return {FMode} Mode factory.
*/

@@ -840,24 +908,7 @@ function AFMode(Constructors) {

}
if (!utils.is(Constructors.View, 'Function')) {
throw new Error('Incorrect type of a view\'s constructor. Expected: Function');
}
if (Constructors.Control && !utils.is(Constructors.Control, 'Function')) {
throw new Error('Incorrect type of a control\'s constructor. Expected: Function');
}
if (Constructors.Decorators) {
if (!utils.is(Constructors.Decorators, 'Object')) {
throw new Error('Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor');
}
for (var key in Constructors.Decorators) {
if (!utils.is(Constructors.Decorators[key], 'Function')) {
throw new Error('Incorrect type of a decorator\'s constructor "' + key + '". Expected: Function');
}
}
}
/**
* Mode builder.
* Mode factory.
*
* @name BMode
* @name FMode
* @type {Function}

@@ -870,22 +921,7 @@ *

return function(model, config) {
var view = new Constructors.View(config);
var decorators;
if (Constructors.Decorators) {
decorators = {};
for (var key in Constructors.Decorators) {
decorators[key] = new Constructors.Decorators[key](config);
}
}
var control;
if (Constructors.Control) {
control = new Constructors.Control(config);
}
return new Mode({
model: model,
view: view,
decorators: decorators,
control: control,
View: Constructors.View,
Control: Constructors.Control,
Decorators: Constructors.Decorators,
config: config

@@ -940,2 +976,4 @@ });

}, /** @lends MVCModule.prototype */{
__name: 'MVCModule',
/**

@@ -967,13 +1005,6 @@ * Module's model

* @param {String} modeName - Mode name.
* @param {String | String[]} [decorators] - Mode's decorators.
* @return {Mode | Null}
*/
getMode: function(modeName, decorators) {
var mode = this.modes[modeName];
if (mode && decorators) {
mode.decorateWith(decorators);
}
return mode || null;
getMode: function(modeName) {
return this.modes[modeName] || null;
},

@@ -985,7 +1016,6 @@

* @param {String} env - Target environment.
* @param {String | String[]} [decorators] - Mode's decorators.
* @return {Mode | Null}
*/
getModeFor: function(env, decorators){
return this.getMode(this.envModeMap[env], decorators);
getModeFor: function(env){
return this.getMode(this.envModeMap[env]);
}

@@ -992,0 +1022,0 @@ });

// Package of combined patterns to build rich MVC modules
// v0.11.0
// Copyright (c) 2016-2017 Valerii Zinchenko
// v0.12.0
// Copyright (c) 2016-2019 Valerii Zinchenko
// Licensed under MIT (http://valerii-zinchenko.github.io/mvc-pack/blob/master/LICENSE.txt)
// All source files are available at https://github.com/valerii-zinchenko/mvc-pack
!function(t,e){void 0===t&&void 0!==window&&(t=window),"function"==typeof define&&define.amd?define(["class-wrapper","lodash"],function(o,n){return t["mvc-pack"]=e(o,n)}):"object"==typeof module&&module.exports?module.exports=e(require("class-wrapper"),require("lodash")):t["mvc-pack"]=e(t["class-wrapper"],t._)}(this,function(t,e){var o=t.Class,n=t.SingletonClass,r={whatIs:function(t){return Object.prototype.toString.call(t)},is:function(t,e){return this.whatIs(t)==="[object "+e+"]"}},i=o(function(t){t&&r.is(t,"Object")&&(this.config=t)},{model:null,config:null,connect:function(){},destruct:function(){this.model=null,this.config=null},setModel:function(t){if(!r.is(t,"Object"))throw new Error("Model for the mode is not defined");this.model=t}}),c=o(i,null,{view:null,destruct:function(){this.view=null,i.prototype.destruct.call(this)},setView:function(t){if(!(t instanceof s))throw new Error("Incorrect type of view component");this.view=t}}),s=o(i,null,{control:null,destruct:function(){this.control=null,i.prototype.destruct.call(this)},setControl:function(t){if(!(t instanceof c))throw new Error("Incorrect type of control component");this.control=t},render:function(){},update:function(){},_initElements:function(){},_attachEvents:function(){}}),l=n(s,function(){this.element=document.querySelector(this.selector)},{selector:"div",element:null,destruct:function(){this.element.remove(),s.prototype.destruct.call(this)},show:function(){this.element.classList.remove("hidden")},hide:function(){this.element.classList.add("hidden")},render:function(){return this._initElements(),this._attachEvents(),this.element}}),d=o(s,null,{template:"<div></div>",elements:[],_tmpContainer:"div",destruct:function(){this.elements.forEach(function(t){t.remove()}),s.prototype.destruct.call(this)},render:function(){return this._processTemplate(),this._initElements(),this._attachEvents(),this.elements},_processTemplate:function(){this.element=document.createElement(this._tmpContainer),this.element.innerHTML=e.template(this.template)(this);for(var t=this.element.children,o=0,n=t.length;o<n;o++)this.elements.push(t[o])}}),h=o(d,null,{template:"<div data-mvc-container></div>",_component:null,container:null,setComponent:function(t){if(!(t instanceof s))throw new Error('Incorrect type of the "component" argument. Expected AView');this._component=t},destruct:function(){this._component&&this._component.destruct(),d.prototype.destruct.call(this)},render:function(){return d.prototype.render.call(this),this._component&&this._component.elements.forEach(function(t){this.container.appendChild(t)},this),this.elements},update:function(){this._component&&this._component.update(),d.prototype.update.call(this)},_processTemplate:function(){d.prototype._processTemplate.call(this),this.container=this.element.querySelector("[data-mvc-container]")}}),u=o(function(t){if(!r.is(t,"Object"))throw new Error("Incorrect type of the mode's properties. Expected: Object");if(!r.is(t.model,"Object"))throw new Error("Incorrect type of the model. Expected: Object");if(!(t.view instanceof s))throw new Error("View should be inherited from AView");if(this.model=t.model,this._view=t.view,t.decorators&&r.is(t.decorators,"Object"))for(var e in t.decorators){if(!(t.decorators[e]instanceof h))throw new Error('Decorator "'+e+'" should be inherited from ADecorator');this._decorators[e]=t.decorators[e]}if(t.control){if(!(t.control instanceof c))throw new Error("Control should be inherited from AControl");this.control=t.control}this.view=this._view,this.connect()},{model:null,_view:null,view:null,control:null,_decorators:{},_isConnected:!1,connect:function(){if(!this._isConnected){this._view.setModel(this.model),this.control&&(this._view.setControl(this.control),this.control.setModel(this.model),this.control.setView(this._view),this.control.connect()),this._view.connect(),this._view.render();var t;for(var e in this._decorators)(t=this._decorators[e]).setModel(this.model),t.render();this._isConnected=!0}},decorateWith:function(t){if(t)if(r.is(t,"String"))this.decorateWith([t]);else{var e=this._view;if(this._decorators&&t.length>0)for(var o,n=0,i=t.length;n<i;n++)(o=this._decorators[t[n]])&&(o.setComponent(e),e=o);this.view=e}}}),a=o(function(t,e,o){if(!r.is(t,"Object")||!r.is(e,"Object"))throw new Error("Incorrect types of input arguments. Expected: Object model, Object modes");this.model=t,this.modes=e,r.is(o,"Object")&&(this.envModeMap=o)},{model:null,modes:null,envModeMap:{},getMode:function(t,e){var o=this.modes[t];return o&&e&&o.decorateWith(e),o||null},getModeFor:function(t,e){return this.getMode(this.envModeMap[t],e)}});return{AControl:c,AFMVCModule:function(t){if(!r.is(t,"Object"))throw new Error("Incorrect type of an input argument. Expected: Object MVCConstructors");if(!r.is(t.Model,"Function"))throw new Error("Model constructor should be a function");if(!r.is(t.Modes,"Object"))throw new Error("Incorrect type for model's modes");for(var e in t.Modes)if(!r.is(t.Modes[e],"Function"))throw new Error('Incorrect type of a mode "'+e+'", Function expected');return r.is(t.Module,"Function")||(t.Module=a),function(e,o,n){var r,i=new(t.Model.bind.apply(t.Model,[null].concat(e))),c={};for(var s in t.Modes)n&&(r=n[s]),c[s]=new t.Modes[s](i,r);return new t.Module(i,c,o)}},AFMode:function(t){if(!r.is(t,"Object"))throw new Error("Incorrect type of the constructors. Object expected.");if(!r.is(t.View,"Function"))throw new Error("Incorrect type of a view's constructor. Expected: Function");if(t.Control&&!r.is(t.Control,"Function"))throw new Error("Incorrect type of a control's constructor. Expected: Function");if(t.Decorators){if(!r.is(t.Decorators,"Object"))throw new Error("Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor");for(var e in t.Decorators)if(!r.is(t.Decorators[e],"Function"))throw new Error("Incorrect type of a decorator's constructor \""+e+'". Expected: Function')}return function(e,o){var n,r=new t.View(o);if(t.Decorators){n={};for(var i in t.Decorators)n[i]=new t.Decorators[i](o)}var c;return t.Control&&(c=new t.Control(o)),new u({model:e,view:r,decorators:n,control:c,config:o})}},AModeComponent:i,AView:s,DynamicView:d,ADecorator:h,MVCModule:a,Mode:u,StaticView:l,utils:r}});
!function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["class-wrapper","@valerii-zinchenko/observer","lodash"],function(o,n,r){return e["mvc-pack"]=t(o,n,r)}):"object"==typeof module&&module.exports?module.exports=t(require("class-wrapper"),require("@valerii-zinchenko/observer"),require("lodash")):e["mvc-pack"]=t(e["class-wrapper"],e.Observer,e._)}(this,function(e,t,o){var n=e.Class,r={whatIs:function(e){return Object.prototype.toString.call(e)},is:function(e,t){return this.whatIs(e)==="[object "+t+"]"}},i=n(function(e){e&&r.is(e,"Object")&&(this.config=e),Object.keys(this._bind2this).forEach(function(e){this[e]=this._bind2this[e].bind(this)},this)},{__name:"AModeComponent",model:null,config:null,_bind2this:{},connect:function(){},destruct:function(){this.model=null,this.config=null},setModel:function(e){if(!r.is(e,"Object"))throw new Error("Model for the mode is not defined");this.model=e}}),c=n(i,null,{__name:"AControl",Encapsulate:[t],destruct:function(){this._events={},i.prototype.destruct.call(this)}}),s=n(i,null,{__name:"AView",control:null,destruct:function(){this.control=null,i.prototype.destruct.call(this)},setControl:function(e){if(!(e instanceof c))throw new Error("Incorrect type of control component");this.control=e},render:function(){},update:function(){},insertView:function(e,t){for(;e.firstChild;)e.removeChild(e.firstChild);this.appendView(e,t)},appendView:function(e,t){for(var o=0,n=t.elements.length;o<n;o++)e.appendChild(t.elements[o]);t.update()},_initElements:function(){},_attachEvents:function(){}}),l=n(s,function(){this.element=document.querySelector(this.selector)},{__name:"StaticView",selector:"div",element:null,destruct:function(){this.element.remove(),s.prototype.destruct.call(this)},show:function(){this.element.classList.remove("hidden")},hide:function(){this.element.classList.add("hidden")},render:function(){return this._initElements(),this._attachEvents(),this.element}}),d=n(s,null,{__name:"DynamicView",template:"<div></div>",elements:[],_tmpContainer:"div",destruct:function(){this.elements.forEach(function(e){e.remove()}),s.prototype.destruct.call(this)},render:function(){return this._processTemplate(),this._initElements(),this._attachEvents(),this.elements},_processTemplate:function(){this.element=document.createElement(this._tmpContainer),this.element.innerHTML=o.template(this.template)(this);for(var e=this.element.children,t=0,n=e.length;t<n;t++)this.elements.push(e[t])}}),u=n(d,null,{__name:"ADecorator",template:"<div data-mvc-container></div>",_component:null,container:null,setComponent:function(e){if(!(e instanceof s))throw new Error('Incorrect type of the "component" argument. Expected AView');this._component=e},destruct:function(){this._component&&this._component.destruct(),d.prototype.destruct.call(this)},render:function(){return d.prototype.render.call(this),this._component&&this._component.elements.forEach(function(e){this.container.appendChild(e)},this),this.elements},update:function(){this._component&&this._component.update(),d.prototype.update.call(this)},_processTemplate:function(){d.prototype._processTemplate.call(this),this.container=this.element.querySelector("[data-mvc-container]")}}),h=n(function(e){if(!r.is(e,"Object"))throw new Error("Incorrect type of the mode's properties. Expected: Object");if(!r.is(e.model,"Object"))throw new Error("Incorrect type of the model. Expected: Object");if(this.model=e.model,!r.is(e.View,"Function"))throw new Error("Incorrect type of a view's constructor. Expected: Function");if(this.View=e.View,e.Decorators){if(!r.is(e.Decorators,"Object"))throw new Error("Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor");for(var t in e.Decorators)if(!r.is(e.Decorators[t],"Function"))throw new Error("Incorrect type of a decorator's constructor \""+t+'". Expected: Function');this.Decorators=e.Decorators}if(this.config=e.config,e.Control){if(!r.is(e.Control,"Function"))throw new Error("Incorrect type of a control's constructor. Expected: Function");var o=new e.Control(this.config);if(!(o instanceof c))throw new Error("Control should be inherited from AControl");this.control=o,this.control.setModel(this.model),this.control.connect()}},{__name:"Mode",model:null,View:null,Decorators:{},control:null,_usages:{},getView:function(e,t){if(e||(e="default"),this._usages[e])return this._usages[e];var o=new this.View(this.config);if(!(o instanceof s))throw new Error("View should be inherited from AView");return o.setModel(this.model),this.control&&o.setControl(this.control),o.connect(),o.render(),o=this.decorate(o,t),this._usages[e]=o,o},decorate:function(e,t){if(!(e instanceof s))throw new Error("View should be inherited from AView");if(0===this.Decorators.length||!t)return e;r.is(t,"String")&&(t=[t]);for(var o,n,i=e,c=0,l=t.length;c<l;c++){if(!(n=this.Decorators[t[c]]))throw new Error('Constructor for decorator "'+t[c]+'" is not defined');if(!((o=new n(this.config))instanceof u))throw new Error('Decorator "'+t[c]+'" should be inherited from ADecorator');o.setComponent(i),o.setModel(this.model),o.render(),i=o}return i}}),a=n(function(e,t,o){if(!r.is(e,"Object")||!r.is(t,"Object"))throw new Error("Incorrect types of input arguments. Expected: Object model, Object modes");this.model=e,this.modes=t,r.is(o,"Object")&&(this.envModeMap=o)},{__name:"MVCModule",model:null,modes:null,envModeMap:{},getMode:function(e){return this.modes[e]||null},getModeFor:function(e){return this.getMode(this.envModeMap[e])}});return{AControl:c,AFMVCModule:function(e){if(!r.is(e,"Object"))throw new Error("Incorrect type of an input argument. Expected: Object MVCConstructors");if(!r.is(e.Model,"Function"))throw new Error("Model constructor should be a function");if(!r.is(e.Modes,"Object"))throw new Error("Incorrect type for model's modes");for(var t in e.Modes)if(!r.is(e.Modes[t],"Function"))throw new Error('Incorrect type of a mode "'+t+'", Function expected');return r.is(e.Module,"Function")||(e.Module=a),function(t,o,n){var r,i=new(e.Model.bind.apply(e.Model,[null].concat(t))),c={};for(var s in e.Modes)n&&(r=n[s]),c[s]=new e.Modes[s](i,r);return new e.Module(i,c,o)}},AFMode:function(e){if(!r.is(e,"Object"))throw new Error("Incorrect type of the constructors. Object expected.");return function(t,o){return new h({model:t,View:e.View,Control:e.Control,Decorators:e.Decorators,config:o})}},AModeComponent:i,AView:s,DynamicView:d,ADecorator:u,MVCModule:a,Mode:h,StaticView:l,utils:r}});

@@ -50,2 +50,3 @@ module.exports = function(grunt) {

{'class-wrapper': 'ClassWrapper'},
{'@valerii-zinchenko/observer': 'Observer'},
{'lodash': '_'}

@@ -55,2 +56,3 @@ ],

'class-wrapper',
'Observer',
'_'

@@ -57,0 +59,0 @@ ]

@@ -19,3 +19,3 @@ /*

*
* @version 2.0.0
* @version 3.0.0
*/

@@ -31,31 +31,17 @@

* @extends AModeComponent
* @mixes Observer
*/
var AControl = Class(AModeComponent, null, /** @lends AControl.prototype */{
/**
* Reference to the view.
*/
view: null,
__name: 'AControl',
Encapsulate: [Observer],
/**
* Control destructor.
* Control destructor
*/
destruct: function() {
this.view = null;
this._events = {};
AModeComponent.prototype.destruct.call(this);
},
/**
* Set view
*
* @param {Object} view - View
*
* @throws {Error} Incorrect type of view component
*/
setView: function(view) {
if (!(view instanceof AView)) {
throw new Error('Incorrect type of view component');
}
this.view = view;
}
});

@@ -33,2 +33,4 @@ /*

var ADecorator = Class(DynamicView, null, /** @lends ADecorator.prototype */{
__name: 'ADecorator',
template: '<div data-mvc-container></div>',

@@ -35,0 +37,0 @@

@@ -12,5 +12,5 @@ /*

/**
* @file It contains the implementation of [abstract mode factory]{@link AFMode} that returns [mode builder]{@link BMode}.
* @file It contains the implementation of [abstract mode factory]{@link AFMode} that returns [mode builder]{@link FMode}.
*
* @see {@link BMode}
* @see {@link FMode}
* @see {@link Mode}

@@ -20,3 +20,3 @@ *

*
* @version 3.0.0
* @version 4.0.0
*/

@@ -31,6 +31,2 @@

* @throws {Error} Incorrect type of the constructors. Object expected.
* @throws {Error} Incorrect type of a view's constructor. Expected: Function
* @throws {Error} Incorrect type of a control's constructor. Expected: Function
* @throws {Error} Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor
* @throws {Error} Incorrect type of a decorator's constructor "{name}". Expected: Function
*

@@ -40,4 +36,4 @@ * @param {Object} Constructors - Collection of constructors for a mode.

* @param {Function} [Constructors.Control] - Constructor for the control component.
* @param {Object} [Constructors.Decorators] - Map of decorators' names and decorators' construstors for a new mode. If some constructor is not a function, then it will be skipped in order to avoid NPE
* @return {BMode} Mode builder.
* @param {Object} [Constructors.Decorators] - Map of decorators' names and decorators' constructors for a new mode. If some constructor is not a function, then it will be skipped in order to avoid NPE
* @return {FMode} Mode factory.
*/

@@ -48,24 +44,7 @@ function AFMode(Constructors) {

}
if (!utils.is(Constructors.View, 'Function')) {
throw new Error('Incorrect type of a view\'s constructor. Expected: Function');
}
if (Constructors.Control && !utils.is(Constructors.Control, 'Function')) {
throw new Error('Incorrect type of a control\'s constructor. Expected: Function');
}
if (Constructors.Decorators) {
if (!utils.is(Constructors.Decorators, 'Object')) {
throw new Error('Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor');
}
for (var key in Constructors.Decorators) {
if (!utils.is(Constructors.Decorators[key], 'Function')) {
throw new Error('Incorrect type of a decorator\'s constructor "' + key + '". Expected: Function');
}
}
}
/**
* Mode builder.
* Mode factory.
*
* @name BMode
* @name FMode
* @type {Function}

@@ -78,22 +57,7 @@ *

return function(model, config) {
var view = new Constructors.View(config);
var decorators;
if (Constructors.Decorators) {
decorators = {};
for (var key in Constructors.Decorators) {
decorators[key] = new Constructors.Decorators[key](config);
}
}
var control;
if (Constructors.Control) {
control = new Constructors.Control(config);
}
return new Mode({
model: model,
view: view,
decorators: decorators,
control: control,
View: Constructors.View,
Control: Constructors.Control,
Decorators: Constructors.Decorators,
config: config

@@ -100,0 +64,0 @@ });

@@ -20,3 +20,3 @@ /*

*
* @version 3.0.1
* @version 3.1.0
*/

@@ -38,3 +38,10 @@

}
// Automatically bind all defined function to "this" and store them into "this" under the same name
Object.keys(this._bind2this).forEach(function(name) {
this[name] = this._bind2this[name].bind(this);
}, this);
}, /** @lends AModeComponent.prototype */{
__name: 'AModeComponent',
/**

@@ -55,2 +62,11 @@ * Reference to the model.

/**
* Set of function, which will be bound automatically to "this" by constructing an instance.
* This is most useful for event handlers, which in most cases should have the context of current class.
* Be careful, as that can overwrite other properties/methods defined in the class.
*
* @type {Object}
*/
_bind2this: {},
/**
* Connect view component to the module.

@@ -57,0 +73,0 @@ * This is called after constructor and setting of the model and control components.

@@ -35,2 +35,4 @@ /*

var AView = Class(AModeComponent, null, /** @lends AView.prototype */{
__name: 'AView',
/**

@@ -80,2 +82,33 @@ * Reference to the control.

/**
* Insert additionl module into current view
*
* @param {DOMElement} container - Container element, where the module is going to be inserted. This should be empty, because it will be emptied before insertion
* @param {AView} view - View to insert
*/
insertView: function(container, view) {
// cleanup the container
while (container.firstChild) {
container.removeChild(container.firstChild);
}
this.appendView(container, view);
},
/**
* Appends the view's elements into the container
*
* @param {DOMElement} container - Container element, where the module is going to be inserted. This should be empty, because it will be emptied before insertion
* @param {AView} view - View to insert
*/
appendView: function(container, view) {
// insert view's elements
for (var n = 0, N = view.elements.length; n < N; n++) {
container.appendChild(view.elements[n]);
}
view.update();
},
/**
* Initialize required for view elements.

@@ -82,0 +115,0 @@ */

@@ -20,2 +20,1 @@ /*

var Class = ClassWrapper.Class;
var SingletonClass = ClassWrapper.SingletonClass;

@@ -34,2 +34,4 @@ /*

var DynamicView = Class(AView, null, /** @lends DynamicView.prototype */{
__name: 'DynamicView',
/**

@@ -36,0 +38,0 @@ * Main template.

@@ -14,10 +14,11 @@ /*

*
* @see {@link AFMode}
* @see {@link AModeComponent}
* @see {@link AView}
* @see {@link AControl}
* @see {@link AFMode}
* @see {@link ADecorator}
*
* @author Valerii Zinchenko
*
* @version 5.0.0
* @version 6.0.0
*/

@@ -31,13 +32,17 @@

* @class
* @param {Object} properties - Mode's properties.
* @param {Object} properties.model - Model.
* @param {AView} properties.view - Main mode's view.
* @param {AControl} [properties.control] - Mode's control.
* @param {Object} [properties.decorators] - Object of decorators for a view, where the key is a decorator name and value is a decorator.
*
* @throws {Error} Incorrect type of the mode's properties. Expected: Object
* @throws {Error} Incorrect type of the model. Expected: Object
* @throws {Error} View should be inherited from AView
* @throws {Error} Decorator "{name}" should be inherited from ADecorator
* @throws {Error} Incorrect type of a view's constructor. Expected: Function
* @throws {Error} Incorrect type of a control's constructor. Expected: Function
* @throws {Error} Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor
* @throws {Error} Incorrect type of a decorator's constructor "{name}". Expected: Function
* @throws {Error} Control should be inherited from AControl
*
* @param {Object} properties - Mode's properties.
* @param {Object} properties.model - Model.
* @param {Function} properties.View - Constructor for the view component.
* @param {Function} [properties.Control] - Constructor for the control component.
* @param {Object} [properties.Decorators] - Map of decorators' names and decorators' construstors for a new mode.
* @param {Object} [properties.config] - Configurations for control, view and decorator components.
*/

@@ -48,37 +53,50 @@ var Mode = Class(function(properties) {

}
if (!utils.is(properties.model, 'Object')) {
if (utils.is(properties.model, 'Object')) {
this.model = properties.model;
} else {
throw new Error('Incorrect type of the model. Expected: Object');
}
if (!(properties.view instanceof AView)) {
throw new Error('View should be inherited from AView');
if (utils.is(properties.View, 'Function')) {
this.View = properties.View;
} else {
throw new Error('Incorrect type of a view\'s constructor. Expected: Function');
}
this.model = properties.model;
this._view = properties.view;
if (properties.Decorators) {
if (!utils.is(properties.Decorators, 'Object')) {
throw new Error('Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor');
}
if (properties.decorators && utils.is(properties.decorators, 'Object')) {
for (var key in properties.decorators) {
if ( !(properties.decorators[key] instanceof ADecorator) ) {
throw new Error('Decorator "' + key + '" should be inherited from ADecorator');
for (var key in properties.Decorators) {
if (!utils.is(properties.Decorators[key], 'Function')) {
throw new Error('Incorrect type of a decorator\'s constructor "' + key + '". Expected: Function');
}
}
this._decorators[key] = properties.decorators[key];
}
this.Decorators = properties.Decorators;
}
if (properties.control) {
if ( !(properties.control instanceof AControl) ) {
this.config = properties.config;
if (properties.Control) {
if (!utils.is(properties.Control, 'Function')) {
throw new Error('Incorrect type of a control\'s constructor. Expected: Function');
}
var control = new properties.Control(this.config);
if ( !(control instanceof AControl) ) {
throw new Error('Control should be inherited from AControl');
}
this.control = properties.control;
this.control = control;
this.control.setModel(this.model);
this.control.connect();
}
}, /** @lends Mode.prototype */{
__name: 'Mode',
this.view = this._view;
this.connect();
}, /** @lends Mode.prototype */{
/**
* Reference to the model.
*
* @type {Objcet}

@@ -89,18 +107,15 @@ */

/**
* Reference to the main view.
*
* @type {AView}
* View constructor
* @type {Function}
*/
_view: null,
View: null,
/**
* Current view. This can be an original or decorated view.
*
* @type {DynamicView}
* Map of decorators' names and decorators' construstors for a new mode
* @type {Object}
*/
view: null,
Decorators: {},
/**
* Reference to the control.
*
* @type {AControl}

@@ -111,75 +126,92 @@ */

/**
* Object of decorators, where the key is a name of a deocorator and value is a decorator object.
*
* Map of usages and created views for it
* @type {Object}
*/
_decorators: {},
_usages: {},
/**
* This indicates if a mode components are already connected or not.
* Get an instance of the view for a specific usage.
*
* @type {Boolean}
* For each usage a new instance of the view will be created and, if needed, decorated also with new instances of decorators.
* This allows to use the same view in different places with or without different decorators.
*
* @throws {Error} View should be inherited from AView
* @throws {Error} Decorator "{name}" should be inherited from ADecorator
*
* @param {String} [usage = 'default'] - Define for how/where he view is going to be used. For different usages different instances of a view and decorators will be created.
* @param {String[] | String} [decorators] - An array of decorators name or a single decorator name. Decorators will be applied in the same order as they are defined.
*/
_isConnected: false,
getView: function(usage, decorations) {
if (!usage) {
usage = 'default';
}
if (this._usages[usage]) {
return this._usages[usage];
}
/**
* Connect mode components
*/
connect: function() {
if (this._isConnected) {
return;
var view = new this.View(this.config);
if (!(view instanceof AView)) {
throw new Error('View should be inherited from AView');
}
this._view.setModel(this.model);
view.setModel(this.model);
if (this.control) {
this._view.setControl(this.control);
this.control.setModel(this.model);
this.control.setView(this._view);
this.control.connect();
view.setControl(this.control);
}
this._view.connect();
this._view.render();
view.connect();
view.render();
view = this.decorate(view, decorations);
var decorator;
for (var key in this._decorators) {
decorator = this._decorators[key];
decorator.setModel(this.model);
decorator.render();
}
this._usages[usage] = view;
this._isConnected = true;
return view;
},
/**
* Apply decorators to the original view.
* Apply decorators to a view.
*
* @param {String[] | String } decorators - An array of decorators name or a single decorator name. Decorators will be applied in the same order as they are defined.
* @throws {Error} View should be inherited from AView
* @throws {Error} Constructor for decorator "{name}" is not defined
* @throws {Error} Decorator "{name}" should be inherited from ADecorator
*
* @param {AView} view - View, which should be decorated.
* @param {String[] | String} decorators - An array of decorators name or a single decorator name. Decorators will be applied in the same order as they are defined.
* @return {Aview}
*/
decorateWith: function(decorators){
if (!decorators) {
return;
decorate: function(view, decorators){
if (!(view instanceof AView)) {
throw new Error('View should be inherited from AView');
}
if (this.Decorators.length === 0 || !decorators) {
return view;
}
if (utils.is(decorators, 'String')){
this.decorateWith([decorators]);
return;
decorators = [decorators];
}
var v = this._view;
var v = view;
var decorator;
var Constructor;
for (var n = 0, N = decorators.length; n < N; n++) {
Constructor = this.Decorators[decorators[n]];
if (!Constructor) {
throw new Error('Constructor for decorator "' + decorators[n] + '" is not defined');
}
if (this._decorators && decorators.length > 0) {
var decorator;
for (var n = 0, N = decorators.length; n < N; n++) {
decorator = this._decorators[decorators[n]];
if (decorator) {
decorator.setComponent(v);
decorator = new Constructor(this.config);
v = decorator;
}
if ( !(decorator instanceof ADecorator) ) {
throw new Error('Decorator "' + decorators[n] + '" should be inherited from ADecorator');
}
decorator.setComponent(v);
decorator.setModel(this.model);
decorator.render();
v = decorator;
}
this.view = v;
return v;
}
});

@@ -45,2 +45,4 @@ /*

}, /** @lends MVCModule.prototype */{
__name: 'MVCModule',
/**

@@ -72,13 +74,6 @@ * Module's model

* @param {String} modeName - Mode name.
* @param {String | String[]} [decorators] - Mode's decorators.
* @return {Mode | Null}
*/
getMode: function(modeName, decorators) {
var mode = this.modes[modeName];
if (mode && decorators) {
mode.decorateWith(decorators);
}
return mode || null;
getMode: function(modeName) {
return this.modes[modeName] || null;
},

@@ -90,8 +85,7 @@

* @param {String} env - Target environment.
* @param {String | String[]} [decorators] - Mode's decorators.
* @return {Mode | Null}
*/
getModeFor: function(env, decorators){
return this.getMode(this.envModeMap[env], decorators);
getModeFor: function(env){
return this.getMode(this.envModeMap[env]);
}
});

@@ -27,3 +27,3 @@ /*

* Static view.
* It implements parent's [render()]{@link render} method to initalize required elements and attach eventh.
* It implements parent's [render()]{@link render} method to initialize required elements and attach events.
*

@@ -33,5 +33,7 @@ * @class

*/
var StaticView = SingletonClass(AView, function() {
var StaticView = Class(AView, function() {
this.element = document.querySelector(this.selector);
}, /** @lends StaticView.prototype */{
__name: 'StaticView',
/**

@@ -38,0 +40,0 @@ * Selector of a static element from a DOM

{
"name": "mvc-pack",
"version": "0.11.0",
"version": "0.12.0",
"description": "Package of combined patterns to build rich MVC modules",

@@ -16,4 +16,4 @@ "main": "dest/mvc-pack.js",

"doc": "grunt doc",
"preversion": "npm test",
"prepublishOnly": "grunt build"
"prepublishOnly": "grunt build",
"build": "grunt build"
},

@@ -27,2 +27,3 @@ "directories": {

"dependencies": {
"@valerii-zinchenko/observer": "^1.0.2",
"class-wrapper": "^1.0.3",

@@ -42,6 +43,5 @@ "lodash": "^4.17.4"

"grunt-template": "^1.0.0",
"grunt-umd": "^2.4.0",
"grunt-umd": "^3.0.0",
"istanbul": "^0.4.5",
"jsdoc-inheritance-diagram": "^1.0.0",
"libumd": "github:valerii-zinchenko/libumd",
"jsdoc-inheritance-diagram": "^1.2.1",
"load-grunt-tasks": "^3.5.2",

@@ -48,0 +48,0 @@ "mocha": "^4.0.1",

@@ -8,2 +8,10 @@ 'use strict';

});
test('Mixing of Observer', function() {
var c = new AControl();
assert.equal(c.listen, Observer.prototype.listen);
assert.equal(c.trigger, Observer.prototype.trigger);
assert.equal(c.removeListener, Observer.prototype.removeListener);
});
});

@@ -22,48 +30,7 @@

suite('setView', function(){
suite('incorrect view instance', function(){
[].concat(
[
undefined,
null,
false,
true,
0,
1,
'',
'1',
[],
{},
function(){}
].map(function(input){
return {
title: 'when type of input: ' + Object.prototype.toString.call(input) + ' and value: ' + input,
input: input
};
})
).forEach(function(testCase){
test(testCase.title, function(){
assert.throw(function(){
aControl.setView(testCase.input);
}, Error, 'Incorrect type of view component');
});
});
});
test('correct view instance', function(){
var view = new AView({});
assert.doesNotThrow(function(){
aControl.setView(view);
});
assert.equal(aControl.view, view, 'View was incorrectly set');
});
});
test('desctuct', function(){
assert.doesNotThrow(function(){
aControl.setView(new AView({}));
aControl.destruct();
});
assert.isNull(aControl.view, 'destruct() should set view to null');
assert.isTrue(AModeComponent.prototype.destruct.calledOnce, 'Parent\'s destruct() should be called');

@@ -70,0 +37,0 @@ });

@@ -1,3 +0,1 @@

'use strict';
suite('AFMode', function(){

@@ -23,77 +21,2 @@ suite('incorrect input argument', function(){

};
}),
[
undefined,
null,
false,
true,
0,
1,
'',
'str',
[],
{}
].map(function(input){
return {
title: 'type of a View constructor: ' + Object.prototype.toString(input) + ' with a value: ' + input,
input: {View: input},
expected: 'Incorrect type of a view\'s constructor. Expected: Function'
};
}),
[
true,
1,
'str',
[],
function(){}
].map(function(input){
return {
title: 'type of a Decorators: ' + Object.prototype.toString(input) + ' with a value: ' + input,
input: {
View: function(){},
Decorators: input
},
expected: 'Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor'
};
}),
[
undefined,
null,
false,
true,
0,
1,
'',
'str',
[],
{}
].map(function(input){
return {
title: 'type of a Decorator constructor: ' + Object.prototype.toString(input) + ' with a value: ' + input,
input: {
View: function(){},
Decorators: {
Deco: input
}
},
expected: 'Incorrect type of a decorator\'s constructor "Deco". Expected: Function'
};
}),
[
true,
1,
'str',
[],
{}
].map(function(input){
return {
title: 'type of a Control: ' + Object.prototype.toString(input) + ' with a value: ' + input,
input: {
View: function(){},
Control: input
},
expected: 'Incorrect type of a control\'s constructor. Expected: Function'
};
})

@@ -140,3 +63,3 @@ ).forEach(function(testCase){

suite('Mode builder. Integration tests with Mode', function(){
suite('Mode factory. Integration tests with Mode', function(){
setup(function(){

@@ -159,9 +82,3 @@ sinon.spy(AModeComponent.prototype, "connect");

var result;
assert.doesNotThrow(function(){
result = (AFMode({View: AView}))(model);
});
assert.isNotNull(result.view, 'View component of the mode was not setup');
assert.equal(result.view.model, model, 'Model was incorrectly set');
var result = (AFMode({View: AView}))(model);
});

@@ -172,21 +89,11 @@

var result;
assert.doesNotThrow(function(){
result = (AFMode({
View: AView,
Control: AControl
}))(model);
});
assert.isNotNull(result.view, 'View component of the mode was not setup');
assert.isNotNull(result.control, 'Control component of the mode was not setup');
assert.equal(result.control.model, model, 'Model was incorrectly set');
var result = (AFMode({
View: AView,
Control: AControl
}))(model);
});
test('with Decorators', function(){
var constructor = sinon.stub();
var Deco = Class(ADecorator, null, {});
var Deco = new Class(ADecorator, constructor, {});
var incorrectDeco = {};
var result = (AFMode({

@@ -198,6 +105,2 @@ View: AView,

}))({});
assert.isTrue(constructor.calledOnce, 'Decorator should be created in the mode builder');
assert.instanceOf(result._decorators.Deco, Deco, 'Decorator was incorrectly set');
assert.isUndefined(result._decorators.incorrectDeco, 'Incorrect docarator should not be passed further to a mode constructor');
});

@@ -208,14 +111,8 @@

var result;
assert.doesNotThrow(function(){
result = (AFMode({
View: AView,
Control: AControl
}))({}, config);
});
assert.equal(result.view.config, config, 'Configuration was incorrectly set to the view');
assert.equal(result.control.config, config, 'Configuration was incorrectly set to the control');
var result = (AFMode({
View: AView,
Control: AControl
}))({}, config);
});
});
});

@@ -9,2 +9,3 @@ 'use strict';

return {
title: 'incorrect type of input argument: ' + JSON.stringify(input),
input: input,

@@ -17,2 +18,3 @@ exception: 'Incorrect type of the mode\'s properties. Expected: Object'

return {
title: 'incorrect type of model: ' + JSON.stringify(input),
input: {model: input},

@@ -23,27 +25,85 @@ exception: 'Incorrect type of the model. Expected: Object'

[undefined, null, 0, 1, false, true, '', 'str', [], function(){}].map(function(input){
[
undefined,
null,
false,
true,
0,
1,
'',
'str',
[],
{}
].map(function(input){
return {
title: 'type of a View constructor: ' + Object.prototype.toString.call(input) + ' with a value: ' + JSON.stringify(input),
input: {
model: {},
view: input
View: input
},
exception: 'View should be inherited from AView'
exception: 'Incorrect type of a view\'s constructor. Expected: Function'
};
}),
[undefined, null, 0, 1, false, true, '', 'str', [], function(){}].map(function(input){
var model = {};
[
true,
1,
'str',
[],
{}
].map(function(input){
return {
title: 'type of a Control: ' + Object.prototype.toString.call(input) + ' with a value: ' + JSON.stringify(input),
input: {
model: model,
view: new AView(model),
decorators: {
deco: input
model: {},
View: function(){},
Control: input
},
exception: 'Incorrect type of a control\'s constructor. Expected: Function'
};
}),
[
true,
1,
'str',
[],
function(){}
].map(function(input){
return {
title: 'type of a Decorators: ' + Object.prototype.toString.call(input) + ' with a value: ' + JSON.stringify(input),
input: {
model: {},
View: function(){},
Decorators: input
},
exception: 'Incorrect type of map of decorators. Expected: Object. Where key is a decorator name, and value is a decorator constructor'
};
}),
[
undefined,
null,
false,
true,
0,
1,
'',
'str',
[],
{}
].map(function(input){
return {
title: 'type of a Decorator constructor: ' + Object.prototype.toString.call(input) + ' with a value: ' + JSON.stringify(input),
input: {
model: {},
View: function(){},
Decorators: {
Deco: input
}
},
exception: 'Decorator "deco" should be inherited from ADecorator'
exception: 'Incorrect type of a decorator\'s constructor "Deco". Expected: Function'
};
}),
[1, true, 'str', [], function(){}, {}].map(function(input){
[1, true, 'str', [], {}].map(function(input){
var model = {};

@@ -53,10 +113,19 @@ return {

model: model,
view: new AView(model),
control: input
View: AView,
Control: input
},
exception: 'Control should be inherited from AControl'
exception: 'Incorrect type of a control\'s constructor. Expected: Function'
};
})
}),
{
title: 'control instance is not an instance of AControl',
input: {
model: {},
View: AView,
Control: function(){}
},
exception: 'Control should be inherited from AControl'
}
).forEach(function(testCase){
test('input: ' + JSON.stringify(testCase.input), function(){
test(testCase.title || ('input: ' +JSON.stringify(testCase.input)), function(){
assert.throw(function(){

@@ -77,4 +146,4 @@ new Mode(testCase.input);

model: {},
view: new AView({}),
control: testCase
View: AView,
Control: testCase
});

@@ -87,19 +156,2 @@ });

});
suite('incompatible decorators object', function(){
[undefined, null, 0, 1, false, true, '', 'str', [], function(){}].forEach(function(testCase){
test('input: ' + testCase, function(){
var result;
assert.doesNotThrow(function(){
result = new Mode({
model: {},
view: new AView({}),
decorators: testCase
});
});
assert.isTrue(Object.keys(result._decorators).length === 0, 'Initiali object of decorators should not be changed');
});
});
});
});

@@ -109,6 +161,8 @@

setup(function(){
sinon.spy(Mode.prototype, 'connect');
sinon.spy(AControl.prototype, 'setModel');
sinon.spy(AControl.prototype, 'connect');
});
teardown(function(){
Mode.prototype.connect.restore();
AControl.prototype.setModel.restore();
AControl.prototype.connect.restore();
});

@@ -118,26 +172,25 @@

var model = {};
var view = new AView();
var control = new AControl();
var decorators = {
deco: new (Class(ADecorator, null, {})),
anotherdeco: new (Class(ADecorator, null, {}))
var Decorators = {
deco: Class(ADecorator, null, {}),
anotherdeco: Class(ADecorator, null, {})
};
var result;
assert.doesNotThrow(function(){
result = new Mode({
model: model,
view: view,
control: control,
decorators: decorators
});
var result = new Mode({
model: model,
View: AView,
Control: AControl,
Decorators: Decorators
});
assert.equal(result.model, model, 'Model was incorrectly set');
assert.equal(result._view, view, 'Main undecorated view was incorrectly set');
assert.equal(result.view, view, 'Final view was incorrectly set');
assert.equal(result.control, control, 'Control was incorrectly set');
assert.isUndefined(result._decorators.nofn, 'Incorrect decorator should not be set to a map of available decorators');
assert.isUndefined(result._decorators.incomp, 'Incompatible decoratorshould not be set to a map of available decorators');
assert.equal(result._decorators.deco, decorators.deco, 'Compatible decorator\'s constructor was lost');
assert.instanceOf(result.control, AControl, 'Control was incorrectly built');
assert.equal(result.View, AView, 'View constructor was incorrectly set');
assert.equal(result.Decorators, Decorators, 'Constructors for decorators were incorrectly set');
assert.isTrue(result.control.setModel.calledOnce, 'Model should be set to the control');
assert.isTrue(result.control.setModel.withArgs(result.model).calledOnce, 'Something wrong was set to the control as a model');
assert.isTrue(result.control.connect.calledOnce, 'Control\'s "connect" method should be called to execute the connection routine');
assert.isTrue(result.control.connect.calledAfter(result.control.setModel), 'Control\'s "connect" method should be called after model was set to it');
});

@@ -152,7 +205,7 @@ });

model: {},
view: new AView(),
control: new AControl(),
decorators: {
deco0: new (Class(ADecorator, null, {})),
deco1: new (Class(ADecorator, null, {}))
View: AView,
Control: AControl,
Decorators: {
deco0: Class(ADecorator, null, {}),
deco1: Class(ADecorator, null, {})
}

@@ -165,175 +218,20 @@ });

suite('connect', function(){
suite('getView', function(){
setup(function(){
mode._isConnected = false;
sinon.spy(mode._view, 'setModel');
sinon.spy(mode._view, 'connect');
sinon.spy(mode._view, 'setControl');
sinon.spy(mode._view, 'render');
sinon.spy(AControl.prototype, 'setModel');
sinon.spy(AControl.prototype, 'setView');
sinon.spy(AControl.prototype, 'connect');
sinon.spy(mode._decorators.deco0, 'setModel');
sinon.spy(mode._decorators.deco0, 'render');
sinon.spy(mode._decorators.deco1, 'setModel');
sinon.spy(mode._decorators.deco1, 'render');
});
teardown(function(){
mode._view.setModel.restore();
mode._view.connect.restore();
mode._view.setControl.restore();
mode._view.render.restore();
AControl.prototype.setModel.restore();
AControl.prototype.setView.restore();
AControl.prototype.connect.restore();
mode._decorators.deco0.setModel.restore();
mode._decorators.deco0.render.restore();
mode._decorators.deco1.setModel.restore();
mode._decorators.deco1.render.restore();
});
test('without control', function(){
mode.control = null;
assert.doesNotThrow(function(){
mode.connect();
mode.connect();
});
});
assert.isTrue(mode._view.setModel.withArgs(mode.model).calledOnce, 'Model should be set to the view');
assert.isTrue(mode._view.connect.calledOnce, 'Mode components was not connected to the view');
assert.isFalse(mode._view.setControl.called, 'Control component should not be set when the mode hasn\'t control component');
assert.isTrue(mode._view.render.calledAfter(mode._view.connect), 'View should be rendered after the connecting of all modes\' components');
var decorator;
for (var key in this._decorators) {
decorator = mode._decorators[key];
assert.isTrue(decorator.setModel.withArgs(mode.model).calledOnce, 'Model should be set into the decorator ' + key);
assert.isTrue(decorator.render.calledAfter(decorator.setModel), 'Decorator "' + key + '" should be rendered after the model will be set');
}
suite('decorate', function(){
setup(function(){
sinon.spy(ADecorator.prototype, 'setComponent');
});
test('with control', function(){
assert.doesNotThrow(function(){
mode.connect();
mode.connect();
});
assert.isTrue(mode._view.setModel.withArgs(mode.model).calledOnce, 'Model should be set to the view');
assert.isTrue(mode._view.setControl.calledOnce, 'Control component was not be set');
assert.isTrue(mode._view.connect.calledOnce, 'Mode components was not connected to the view');
assert.isTrue(mode._view.setModel.calledBefore(mode._view.setControl), 'Model should be set first');
assert.isTrue(mode._view.connect.calledAfter(mode._view.setControl), 'Control should be set to the view before connect()');
assert.isTrue(mode._view.render.calledAfter(mode._view.connect), 'View should be rendered after the connecting of all modes\' components');
assert.isTrue(mode.control.setModel.withArgs(mode.model).calledOnce, 'Model should be set to the control');
assert.isTrue(mode.control.setView.calledOnce, 'Control component was not be set');
assert.isTrue(mode.control.connect.calledOnce, 'Mode components was not connected to the view');
assert.isTrue(mode.control.setModel.calledBefore(mode.control.setView), 'Model should be set first');
assert.isTrue(mode.control.connect.calledAfter(mode.control.setView), 'View should be set to the ontrol before connect()');
var decorator;
for (var key in this._decorators) {
decorator = mode._decorators[key];
assert.isTrue(decorator.setModel.withArgs(mode.model).calledOnce, 'Model should be set into the decorator ' + key);
assert.isTrue(decorator.render.calledAfter(decorator.setModel), 'Decorator "' + key + '" should be rendered after the model will be set');
}
teardown(function(){
ADecorator.prototype.setComponent.restore();
});
});
suite('decorateWith', function(){
suite('order of decoration and called methods', function(){
setup(function(){
sinon.stub(ADecorator.prototype, 'setComponent');
});
teardown(function(){
ADecorator.prototype.setComponent.restore();
});
test('decorator does not exist', function(){
assert.doesNotThrow(function(){
mode.decorateWith('nothing');
});
assert.isFalse(ADecorator.prototype.setComponent.called, '"setComponent" should not be called at all, if decorator does not registered');
});
test('one decorator', function(){
assert.doesNotThrow(function(){
mode.decorateWith('deco0');
});
assert.isTrue(ADecorator.prototype.setComponent.calledOnce, 'Decorator should accept some decorated view only once');
assert.isTrue(ADecorator.prototype.setComponent.withArgs(mode._view).called, 'Decorator should accept initial mode view only once');
});
test('two decorators', function(){
assert.doesNotThrow(function(){
mode.decorateWith(['deco0', 'deco1']);
});
assert.isTrue(ADecorator.prototype.setComponent.calledTwice, 'Decorator should accept some decorated view only once');
assert.isTrue(mode._decorators.deco0.setComponent.withArgs(mode._view).calledBefore(mode._decorators.deco1.setComponent.withArgs(mode._decorators.deco0)), 'Decorators were applied in the incorrect sequesnce');
});
});
suite('public view', function(){
suite('no decorating', function(){
[undefined, null, false, true, 0, 1, {}, function(){}, '', []].forEach(function(input){
test('input: ' + JSON.stringify(input), function(){
assert.doesNotThrow(function(){
mode.decorateWith(input);
});
assert.equal(mode.view, mode._view, 'Incorrect final reference was set to the this.view');
});
});
});
suite('decorating', function(){
[
{
decorators: 'deco0',
expected: 'deco0'
},
{
decorators: 'deco1',
expected: 'deco1'
},
{
decorators: ['deco1', 'deco0'],
expected: 'deco0'
},
{
decorators: ['deco0', 'deco1'],
expected: 'deco1'
},
{
decorators: ['none', 'deco0', 'deco1'],
expected: 'deco1'
},
{
decorators: ['deco0', 'none', 'deco1'],
expected: 'deco1'
},
{
decorators: ['deco0', 'deco1', 'none'],
expected: 'deco1'
}
].forEach(function(testCase){
test(JSON.stringify(testCase.decorators), function(){
assert.doesNotThrow(function(){
mode.decorateWith(testCase.decorators);
});
assert.equal(mode.view, mode._decorators[testCase.expected], 'Incorrect final reference was set to the this.view');
});
});
});
});
});
});
});

@@ -71,12 +71,16 @@ 'use strict';

setup(function() {
uut = new MVCModule({}, {
mode: (AFMode({
View: AView,
Decorators: {
deco: ADecorator
}
}))({})
}, {
someEnv: 'mode'
});
uut = new MVCModule(
{},
{
mode: (AFMode({
View: AView,
Decorators: {
deco: ADecorator
}
}))({})
},
{
someEnv: 'mode'
}
);
});

@@ -88,60 +92,29 @@ teardown(function() {

suite('getMode', function() {
test('Undefined mode', function() {
var result;
assert.doesNotThrow(function(){
result = uut.getMode('str');
});
test('null should be returned if requested mode is not found', function() {
var result = uut.getMode('str');
assert.isNull(result, 'Null should be returned if desired mode is not exist');
assert.isNull(result);
});
test('existing mode', function(){
var result;
assert.doesNotThrow(function(){
result = uut.getMode('mode');
});
test('mode object should be returned for the existing mapping', function(){
var result = uut.getMode('mode');
assert.equal(result, uut.modes.mode, 'Incorrect existing mode was returned');
assert.equal(result, uut.modes.mode);
});
test('with decorator', function(){
var result;
assert.doesNotThrow(function(){
result = uut.getMode('mode', 'deco');
});
assert.equal(result.view, uut.modes.mode._decorators.deco, 'Afeter decorating the "view" should point to the decorator object');
});
});
suite('getModeFor', function(){
test('not registered mapping', function(){
var result;
assert.doesNotThrow(function(){
result = uut.getModeFor('eeeeenv');
});
test('null should be returned if mapping to a mode is not found', function(){
var result = uut.getModeFor('eeeeenv');
assert.isNull(result, 'Null should be returned, because it is not defined what mode should be used for a specific environment');
assert.isNull(result);
});
test('registered mapping', function(){
var result;
assert.doesNotThrow(function(){
result = uut.getModeFor('someEnv');
});
test('mode should be returned for the existing mapping', function(){
var result = uut.getModeFor('someEnv');
assert.equal(result, uut.modes.mode, 'Incorrect mode was returned');
assert.equal(result, uut.modes.mode);
});
test('registered mapping with a decorator', function(){
var result;
assert.doesNotThrow(function(){
result = uut.getModeFor('someEnv', 'deco');
});
assert.equal(result, uut.modes.mode, 'Incorrect mode was returned');
assert.equal(result.view, uut.modes.mode._decorators.deco, 'Mode was not decorated');
});
});
});
});

@@ -12,6 +12,2 @@ 'use strict';

});
test('is singleton', function(){
assert.equal(new StaticView(), new StaticView(), 'StaticView should behave as singleton');
});
});

@@ -18,0 +14,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc