Comparing version 0.10.0 to 0.11.0
(function (root, factory) { | ||
if(typeof define === "function" && define.amd) { | ||
define(["class-wrapper", "lodash"], function() { | ||
return factory.apply(null, arguments); | ||
}); | ||
} else if(typeof module === "object" && module.exports) { | ||
module.exports = factory.apply(null, [require("class-wrapper"), require("lodash")]); | ||
} else { | ||
root["mvc-pack"] = factory.apply(null, [root["class-wrapper"], root["lodash"]]); | ||
} | ||
})(this, function(ClassWrapper, _) { | ||
if (root === undefined && window !== undefined) root = window; | ||
if (typeof define === 'function' && define.amd) { | ||
// AMD. Register as an anonymous module unless amdModuleId is set | ||
define(["class-wrapper","lodash"], function (a0,b1) { | ||
return (root['mvc-pack'] = factory(a0,b1)); | ||
}); | ||
} else if (typeof module === 'object' && module.exports) { | ||
// Node. Does not work with strict CommonJS, but | ||
// only CommonJS-like environments that support module.exports, | ||
// like Node. | ||
module.exports = factory(require("class-wrapper"),require("lodash")); | ||
} else { | ||
root['mvc-pack'] = factory(root["class-wrapper"],root["_"]); | ||
} | ||
}(this, function (ClassWrapper, _) { | ||
// Package of combined patterns to build rich MVC modules | ||
// v0.10.0 | ||
// v0.11.0 | ||
// Copyright (c) 2016-2017 Valerii Zinchenko | ||
// Licensed under MIT (http://valerii-zinchenko.github.io/mvc-pack/blob/master/LICENSE.txt) | ||
// All source files are available at: http://github.com/[object Object] | ||
// All source files are available at https://github.com/valerii-zinchenko/mvc-pack | ||
/* | ||
@@ -106,3 +112,3 @@ * mvc-pack | ||
* | ||
* @version 3.0.0 | ||
* @version 3.0.1 | ||
*/ | ||
@@ -128,3 +134,3 @@ | ||
* | ||
* @type {Objcet} | ||
* @type {Object} | ||
*/ | ||
@@ -252,3 +258,3 @@ model: null, | ||
* | ||
* @version 3.0.0 | ||
* @version 3.1.0 | ||
*/ | ||
@@ -273,13 +279,5 @@ | ||
/** | ||
* Main view element. | ||
* | ||
* @type {DOMElement} | ||
*/ | ||
element: null, | ||
/** | ||
* View destructor. | ||
*/ | ||
destruct: function() { | ||
this.element.remove(); | ||
this.control = null; | ||
@@ -308,7 +306,5 @@ | ||
* | ||
* @returns {DOMElement} | ||
* | ||
* @abstract | ||
* | ||
* @see {@link update} | ||
* @returns {HTMLElement | HTMLElement[]} | ||
*/ | ||
@@ -319,4 +315,2 @@ render: function() {}, | ||
* Update view. | ||
* | ||
* @abstract | ||
*/ | ||
@@ -327,4 +321,2 @@ update: function() {}, | ||
* Initialize required for view elements. | ||
* | ||
* @abstract | ||
*/ | ||
@@ -335,4 +327,2 @@ _initElements: function() {}, | ||
* Attach event listeners. | ||
* | ||
* @abstract | ||
*/ | ||
@@ -361,3 +351,3 @@ _attachEvents: function() {} | ||
* | ||
* @version 2.0.0 | ||
* @version 2.1.0 | ||
*/ | ||
@@ -377,5 +367,22 @@ | ||
}, /** @lends StaticView.prototype */{ | ||
/** | ||
* Selector of a static element from a DOM | ||
* @type {String} | ||
*/ | ||
selector: 'div', | ||
/** | ||
* Main view element. | ||
* | ||
* @type {HTMLElement} | ||
*/ | ||
element: null, | ||
destruct: function() { | ||
this.element.remove(); | ||
AView.prototype.destruct.call(this); | ||
}, | ||
/** | ||
* Show view. | ||
@@ -424,3 +431,3 @@ * Remove "hidden" class. | ||
* | ||
* @version 3.0.0 | ||
* @version 3.1.0 | ||
*/ | ||
@@ -442,3 +449,3 @@ | ||
* | ||
* @type {string} | ||
* @type {String} | ||
*/ | ||
@@ -449,3 +456,3 @@ template: '<div></div>', | ||
* Here are stored all separate elements which rendered from a template | ||
* @type{HTMLCollection} | ||
* @type{HTMLElement[]} | ||
*/ | ||
@@ -460,6 +467,14 @@ elements: [], | ||
destruct: function() { | ||
this.elements.forEach(function(element) { | ||
element.remove(); | ||
}); | ||
AView.prototype.destruct.call(this); | ||
}, | ||
/** | ||
* Render the view. | ||
* | ||
* @returns {DOMElement} | ||
* @returns {HTMLElement[]} | ||
*/ | ||
@@ -475,4 +490,3 @@ render: function() { | ||
/** | ||
* Process view template and set the processing result to the [main view element]{@link elements}. | ||
* The Model will be set to the template processor. | ||
* Process view template and store the references to [the rendered elements]{@link elements}. | ||
*/ | ||
@@ -483,3 +497,6 @@ _processTemplate: function() { | ||
this.elements = this.element.children; | ||
var children = this.element.children; | ||
for (var n = 0, N = children.length; n < N; n++) { | ||
this.elements.push(children[n]); | ||
} | ||
} | ||
@@ -505,3 +522,3 @@ }); | ||
* | ||
* @version 2.0.0 | ||
* @version 3.0.0 | ||
*/ | ||
@@ -514,4 +531,4 @@ | ||
* Abstract view decorator. | ||
* Decorator works with built views. | ||
* The template of a decorator should contain an element with class "component-container" where the decorated object will be injected. | ||
* Decorator works with rendered views. | ||
* The template of a decorator should contain an element with an empty data attribute "data-mvc-container" where the decorated object will be injected. | ||
* | ||
@@ -522,3 +539,4 @@ * @class | ||
var ADecorator = Class(DynamicView, null, /** @lends ADecorator.prototype */{ | ||
template: '<div><div class="component-container"></div></div>', | ||
template: '<div data-mvc-container></div>', | ||
/** | ||
@@ -534,5 +552,5 @@ * Decorated component. | ||
* | ||
* @returns {jQueryDOMElement} | ||
* @returns {HTMLElement} | ||
*/ | ||
$component: null, | ||
container: null, | ||
@@ -544,3 +562,3 @@ /** | ||
* | ||
* @params {AView} component - View that is going to be decorated. | ||
* @param {AView} component - View that is going to be decorated. | ||
*/ | ||
@@ -567,3 +585,3 @@ setComponent: function(component) { | ||
* | ||
* @returns {jQueryDOMElement} | ||
* @returns {HTMLElement[]} | ||
*/ | ||
@@ -574,6 +592,8 @@ render: function() { | ||
if (this._component) { | ||
this.$component.appendChild(this._component.$el); | ||
this._component.elements.forEach(function(element) { | ||
this.container.appendChild(element); | ||
}, this); | ||
} | ||
return this.$el; | ||
return this.elements; | ||
}, | ||
@@ -590,11 +610,5 @@ | ||
_processTemplate: function(){ | ||
var _tmpel = document.createElement('div'); | ||
_tmpel.innerHTML = _.template(this.template)({ | ||
model: this.model, | ||
config: this.config | ||
}); | ||
DynamicView.prototype._processTemplate.call(this); | ||
this.$el = _tmpel.firstChild; | ||
this.$component = this.$el.querySelector('.component-container'); | ||
this.container = this.element.querySelector('[data-mvc-container]'); | ||
} | ||
@@ -623,3 +637,3 @@ }); | ||
* | ||
* @version 4.0.0 | ||
* @version 5.0.0 | ||
*/ | ||
@@ -630,3 +644,3 @@ | ||
/** | ||
* Abstract mode. | ||
* Mode for a model. | ||
* | ||
@@ -638,3 +652,3 @@ * @class | ||
* @param {AControl} [properties.control] - Mode's control. | ||
* @param {Object} [properties.decorators] - Object of decorators for a view. | ||
* @param {Object} [properties.decorators] - Object of decorators for a view, where the key is a decorator name and value is a decorator. | ||
* | ||
@@ -644,2 +658,4 @@ * @throws {Error} Incorrect type of the mode's properties. Expected: Object | ||
* @throws {Error} View should be inherited from AView | ||
* @throws {Error} Decorator "{name}" should be inherited from ADecorator | ||
* @throws {Error} Control should be inherited from AControl | ||
*/ | ||
@@ -662,11 +678,15 @@ var Mode = Class(function(properties) { | ||
for (var key in properties.decorators) { | ||
if (properties.decorators[key] instanceof ADecorator) { | ||
this._decorators[key] = properties.decorators[key]; | ||
} else { | ||
console.warn('Incompatible decorator\'s constructor: "' + key + '"! It should be inherited from an ADecorator'); | ||
if ( !(properties.decorators[key] instanceof ADecorator) ) { | ||
throw new Error('Decorator "' + key + '" should be inherited from ADecorator'); | ||
} | ||
this._decorators[key] = properties.decorators[key]; | ||
} | ||
} | ||
if (properties.control && properties.control instanceof AControl) { | ||
if (properties.control) { | ||
if ( !(properties.control instanceof AControl) ) { | ||
throw new Error('Control should be inherited from AControl'); | ||
} | ||
this.control = properties.control; | ||
@@ -801,3 +821,3 @@ } | ||
* | ||
* @version 2.0.0 | ||
* @version 3.0.0 | ||
*/ | ||
@@ -812,4 +832,6 @@ | ||
* @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 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,3 +854,14 @@ * @param {Object} Constructors - Collection of constructors for a mode. | ||
} | ||
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'); | ||
} | ||
} | ||
} | ||
/** | ||
@@ -848,10 +881,6 @@ * Mode builder. | ||
var decorators; | ||
if (Constructors.Decorators && utils.is(Constructors.Decorators, 'Object')) { | ||
if (Constructors.Decorators) { | ||
decorators = {}; | ||
for (var key in Constructors.Decorators) { | ||
if (utils.is(Constructors.Decorators[key], 'Function')) { | ||
decorators[key] = new Constructors.Decorators[key](config); | ||
} else { | ||
console.warn('Incompatible decorator\'s constructor: "' + key + '"! It should be inherited from an ADecorator'); | ||
} | ||
decorators[key] = new Constructors.Decorators[key](config); | ||
} | ||
@@ -1055,14 +1084,18 @@ } | ||
return { | ||
AControl: AControl, | ||
AFMVCModule: AFMVCModule, | ||
AFMode: AFMode, | ||
AModeComponent: AModeComponent, | ||
AView: AView, | ||
DynamicView: DynamicView, | ||
MVCModule: MVCModule, | ||
Mode: Mode, | ||
StaticView: StaticView, | ||
utils: utils | ||
}; | ||
}); | ||
var MVCPack = { | ||
AControl: AControl, | ||
AFMVCModule: AFMVCModule, | ||
AFMode: AFMode, | ||
AModeComponent: AModeComponent, | ||
AView: AView, | ||
DynamicView: DynamicView, | ||
ADecorator: ADecorator, | ||
MVCModule: MVCModule, | ||
Mode: Mode, | ||
StaticView: StaticView, | ||
utils: utils | ||
}; | ||
return MVCPack; | ||
})); |
// Package of combined patterns to build rich MVC modules | ||
// v0.10.0 | ||
// v0.11.0 | ||
// Copyright (c) 2016-2017 Valerii Zinchenko | ||
// Licensed under MIT (http://valerii-zinchenko.github.io/mvc-pack/blob/master/LICENSE.txt) | ||
// All source files are available at: http://github.com/[object Object] | ||
// All source files are available at https://github.com/valerii-zinchenko/mvc-pack | ||
!function(t,e){"function"==typeof define&&define.amd?define(["class-wrapper","lodash"],function(){return e.apply(null,arguments)}):"object"==typeof module&&module.exports?module.exports=e.apply(null,[require("class-wrapper"),require("lodash")]):t["mvc-pack"]=e.apply(null,[t["class-wrapper"],t.lodash])}(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,element:null,destruct:function(){this.element.remove(),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",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",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),this.elements=this.element.children}}),u=o(d,null,{template:'<div><div class="component-container"></div></div>',_component:null,$component: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.appendChild(this._component.$el),this.$el},update:function(){this._component&&this._component.update(),d.prototype.update.call(this)},_processTemplate:function(){var t=document.createElement("div");t.innerHTML=e.template(this.template)({model:this.model,config:this.config}),this.$el=t.firstChild,this.$component=this.$el.querySelector(".component-container")}}),h=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)t.decorators[e]instanceof u?this._decorators[e]=t.decorators[e]:console.warn("Incompatible decorator's constructor: \""+e+'"! It should be inherited from an ADecorator');t.control&&t.control instanceof c&&(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");return function(e,o){var n,i=new t.View(o);if(t.Decorators&&r.is(t.Decorators,"Object")){n={};for(var c in t.Decorators)r.is(t.Decorators[c],"Function")?n[c]=new t.Decorators[c](o):console.warn("Incompatible decorator's constructor: \""+c+'"! It should be inherited from an ADecorator')}var s;return t.Control&&(s=new t.Control(o)),new h({model:e,view:i,decorators:n,control:s,config:o})}},AModeComponent:i,AView:s,DynamicView:d,MVCModule:a,Mode:h,StaticView:l,utils:r}}); | ||
!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}}); |
@@ -8,5 +8,5 @@ module.exports = function(grunt) { | ||
'// v<%= pkg.version %>\n' + | ||
'// Copyright (c) 2016-2017 <%= pkg.author %>\n' + | ||
'// Copyright (c) 2016-<%= (new Date()).getFullYear() %> <%= pkg.author %>\n' + | ||
'// Licensed under <%= pkg.license %> (http://valerii-zinchenko.github.io/<%= pkg.name %>/blob/master/LICENSE.txt)\n' + | ||
'// All source files are available at: http://github.com/<%= pkg.repository %>\n'; | ||
'// All source files are available at <%= pkg.repository.url.slice(4, -4) %>\n'; | ||
@@ -34,3 +34,4 @@ grunt.initConfig({ | ||
'MVCModule', | ||
'AFMVCModule' | ||
'AFMVCModule', | ||
'index' | ||
].map(function(item) { return src + item + '.js'; }), | ||
@@ -41,34 +42,19 @@ dest: '<%= pkg.directories.dest %>/<%= pkg.name %>.js' | ||
wrap: { | ||
umd: { | ||
pkg: { | ||
src: '<%= pkg.directories.dest %>/<%= pkg.name %>.js', | ||
dest: '<%= pkg.directories.dest %>/<%= pkg.name %>.js', | ||
options: { | ||
wrapper: [ | ||
'(function (root, factory) {\n' + | ||
' if(typeof define === "function" && define.amd) {\n' + | ||
' define(["class-wrapper", "lodash"], function() {\n' + | ||
' return factory.apply(null, arguments);\n' + | ||
' });\n' + | ||
' } else if(typeof module === "object" && module.exports) {\n' + | ||
' module.exports = factory.apply(null, [require("class-wrapper"), require("lodash")]);\n' + | ||
' } else {\n' + | ||
' root["<%= pkg.name %>"] = factory.apply(null, [root["class-wrapper"], root["lodash"]]);\n' + | ||
' }\n' + | ||
'})(this, function(ClassWrapper, _) {', | ||
// code will be placed right here | ||
' return {\n' + | ||
' AControl: AControl,\n' + | ||
' AFMVCModule: AFMVCModule,\n' + | ||
' AFMode: AFMode,\n' + | ||
' AModeComponent: AModeComponent,\n' + | ||
' AView: AView,\n' + | ||
' DynamicView: DynamicView,\n' + | ||
' MVCModule: MVCModule,\n' + | ||
' Mode: Mode,\n' + | ||
' StaticView: StaticView,\n' + | ||
' utils: utils\n' + | ||
' };\n' + | ||
'});' | ||
] | ||
src: '<%= pkg.directories.dest %>/<%= pkg.name %>.js', | ||
dest: '<%= pkg.directories.dest %>/<%= pkg.name %>.js', | ||
objectToExport: 'MVCPack', | ||
globalAlias: 'mvc-pack', | ||
deps: { | ||
'default': [ | ||
{'class-wrapper': 'ClassWrapper'}, | ||
{'lodash': '_'} | ||
], | ||
global: [ | ||
'class-wrapper', | ||
'_' | ||
] | ||
} | ||
} | ||
@@ -112,3 +98,3 @@ } | ||
}, | ||
'prod-test': { | ||
'test-prod': { | ||
options: { | ||
@@ -202,4 +188,5 @@ data: { | ||
[ | ||
['build', ['clean:build', 'concat', 'wrap', 'uglify', 'template:test']], | ||
['build', ['clean:build', 'concat', 'umd', 'uglify']], | ||
['test', ['template:test', 'mocha:test']], | ||
['test-prod', ['template:test-prod', 'mocha:test']], | ||
['coverage', ['prepareForCoverage', 'template:coverage', 'mocha:coverage', 'clean:coverage', 'template:test']], | ||
@@ -206,0 +193,0 @@ ['doc', ['jsdoc']] |
@@ -18,3 +18,3 @@ /* | ||
* | ||
* @version 2.0.0 | ||
* @version 3.0.0 | ||
*/ | ||
@@ -27,4 +27,4 @@ | ||
* Abstract view decorator. | ||
* Decorator works with built views. | ||
* The template of a decorator should contain an element with class "component-container" where the decorated object will be injected. | ||
* Decorator works with rendered views. | ||
* The template of a decorator should contain an element with an empty data attribute "data-mvc-container" where the decorated object will be injected. | ||
* | ||
@@ -35,3 +35,4 @@ * @class | ||
var ADecorator = Class(DynamicView, null, /** @lends ADecorator.prototype */{ | ||
template: '<div><div class="component-container"></div></div>', | ||
template: '<div data-mvc-container></div>', | ||
/** | ||
@@ -47,5 +48,5 @@ * Decorated component. | ||
* | ||
* @returns {jQueryDOMElement} | ||
* @returns {HTMLElement} | ||
*/ | ||
$component: null, | ||
container: null, | ||
@@ -57,3 +58,3 @@ /** | ||
* | ||
* @params {AView} component - View that is going to be decorated. | ||
* @param {AView} component - View that is going to be decorated. | ||
*/ | ||
@@ -80,3 +81,3 @@ setComponent: function(component) { | ||
* | ||
* @returns {jQueryDOMElement} | ||
* @returns {HTMLElement[]} | ||
*/ | ||
@@ -87,6 +88,8 @@ render: function() { | ||
if (this._component) { | ||
this.$component.appendChild(this._component.$el); | ||
this._component.elements.forEach(function(element) { | ||
this.container.appendChild(element); | ||
}, this); | ||
} | ||
return this.$el; | ||
return this.elements; | ||
}, | ||
@@ -103,12 +106,6 @@ | ||
_processTemplate: function(){ | ||
var _tmpel = document.createElement('div'); | ||
_tmpel.innerHTML = _.template(this.template)({ | ||
model: this.model, | ||
config: this.config | ||
}); | ||
DynamicView.prototype._processTemplate.call(this); | ||
this.$el = _tmpel.firstChild; | ||
this.$component = this.$el.querySelector('.component-container'); | ||
this.container = this.element.querySelector('[data-mvc-container]'); | ||
} | ||
}); |
@@ -19,3 +19,3 @@ /* | ||
* | ||
* @version 2.0.0 | ||
* @version 3.0.0 | ||
*/ | ||
@@ -30,4 +30,6 @@ | ||
* @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 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 | ||
* | ||
@@ -50,3 +52,14 @@ * @param {Object} Constructors - Collection of constructors for a mode. | ||
} | ||
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'); | ||
} | ||
} | ||
} | ||
/** | ||
@@ -66,10 +79,6 @@ * Mode builder. | ||
var decorators; | ||
if (Constructors.Decorators && utils.is(Constructors.Decorators, 'Object')) { | ||
if (Constructors.Decorators) { | ||
decorators = {}; | ||
for (var key in Constructors.Decorators) { | ||
if (utils.is(Constructors.Decorators[key], 'Function')) { | ||
decorators[key] = new Constructors.Decorators[key](config); | ||
} else { | ||
console.warn('Incompatible decorator\'s constructor: "' + key + '"! It should be inherited from an ADecorator'); | ||
} | ||
decorators[key] = new Constructors.Decorators[key](config); | ||
} | ||
@@ -76,0 +85,0 @@ } |
@@ -20,3 +20,3 @@ /* | ||
* | ||
* @version 3.0.0 | ||
* @version 3.0.1 | ||
*/ | ||
@@ -42,3 +42,3 @@ | ||
* | ||
* @type {Objcet} | ||
* @type {Object} | ||
*/ | ||
@@ -45,0 +45,0 @@ model: null, |
@@ -21,3 +21,3 @@ /* | ||
* | ||
* @version 3.0.0 | ||
* @version 3.1.0 | ||
*/ | ||
@@ -42,13 +42,5 @@ | ||
/** | ||
* Main view element. | ||
* | ||
* @type {DOMElement} | ||
*/ | ||
element: null, | ||
/** | ||
* View destructor. | ||
*/ | ||
destruct: function() { | ||
this.element.remove(); | ||
this.control = null; | ||
@@ -77,7 +69,5 @@ | ||
* | ||
* @returns {DOMElement} | ||
* | ||
* @abstract | ||
* | ||
* @see {@link update} | ||
* @returns {HTMLElement | HTMLElement[]} | ||
*/ | ||
@@ -88,4 +78,2 @@ render: function() {}, | ||
* Update view. | ||
* | ||
* @abstract | ||
*/ | ||
@@ -96,4 +84,2 @@ update: function() {}, | ||
* Initialize required for view elements. | ||
* | ||
* @abstract | ||
*/ | ||
@@ -104,6 +90,4 @@ _initElements: function() {}, | ||
* Attach event listeners. | ||
* | ||
* @abstract | ||
*/ | ||
_attachEvents: function() {} | ||
}); |
@@ -20,3 +20,3 @@ /* | ||
* | ||
* @version 3.0.0 | ||
* @version 3.1.0 | ||
*/ | ||
@@ -38,3 +38,3 @@ | ||
* | ||
* @type {string} | ||
* @type {String} | ||
*/ | ||
@@ -45,3 +45,3 @@ template: '<div></div>', | ||
* Here are stored all separate elements which rendered from a template | ||
* @type{HTMLCollection} | ||
* @type{HTMLElement[]} | ||
*/ | ||
@@ -56,6 +56,14 @@ elements: [], | ||
destruct: function() { | ||
this.elements.forEach(function(element) { | ||
element.remove(); | ||
}); | ||
AView.prototype.destruct.call(this); | ||
}, | ||
/** | ||
* Render the view. | ||
* | ||
* @returns {DOMElement} | ||
* @returns {HTMLElement[]} | ||
*/ | ||
@@ -71,4 +79,3 @@ render: function() { | ||
/** | ||
* Process view template and set the processing result to the [main view element]{@link elements}. | ||
* The Model will be set to the template processor. | ||
* Process view template and store the references to [the rendered elements]{@link elements}. | ||
*/ | ||
@@ -79,4 +86,7 @@ _processTemplate: function() { | ||
this.elements = this.element.children; | ||
var children = this.element.children; | ||
for (var n = 0, N = children.length; n < N; n++) { | ||
this.elements.push(children[n]); | ||
} | ||
} | ||
}); |
@@ -21,3 +21,3 @@ /* | ||
* | ||
* @version 4.0.0 | ||
* @version 5.0.0 | ||
*/ | ||
@@ -28,3 +28,3 @@ | ||
/** | ||
* Abstract mode. | ||
* Mode for a model. | ||
* | ||
@@ -36,3 +36,3 @@ * @class | ||
* @param {AControl} [properties.control] - Mode's control. | ||
* @param {Object} [properties.decorators] - Object of decorators for a view. | ||
* @param {Object} [properties.decorators] - Object of decorators for a view, where the key is a decorator name and value is a decorator. | ||
* | ||
@@ -42,2 +42,4 @@ * @throws {Error} Incorrect type of the mode's properties. Expected: Object | ||
* @throws {Error} View should be inherited from AView | ||
* @throws {Error} Decorator "{name}" should be inherited from ADecorator | ||
* @throws {Error} Control should be inherited from AControl | ||
*/ | ||
@@ -60,11 +62,15 @@ var Mode = Class(function(properties) { | ||
for (var key in properties.decorators) { | ||
if (properties.decorators[key] instanceof ADecorator) { | ||
this._decorators[key] = properties.decorators[key]; | ||
} else { | ||
console.warn('Incompatible decorator\'s constructor: "' + key + '"! It should be inherited from an ADecorator'); | ||
if ( !(properties.decorators[key] instanceof ADecorator) ) { | ||
throw new Error('Decorator "' + key + '" should be inherited from ADecorator'); | ||
} | ||
this._decorators[key] = properties.decorators[key]; | ||
} | ||
} | ||
if (properties.control && properties.control instanceof AControl) { | ||
if (properties.control) { | ||
if ( !(properties.control instanceof AControl) ) { | ||
throw new Error('Control should be inherited from AControl'); | ||
} | ||
this.control = properties.control; | ||
@@ -71,0 +77,0 @@ } |
@@ -20,3 +20,3 @@ /* | ||
* | ||
* @version 2.0.0 | ||
* @version 2.1.0 | ||
*/ | ||
@@ -36,5 +36,22 @@ | ||
}, /** @lends StaticView.prototype */{ | ||
/** | ||
* Selector of a static element from a DOM | ||
* @type {String} | ||
*/ | ||
selector: 'div', | ||
/** | ||
* Main view element. | ||
* | ||
* @type {HTMLElement} | ||
*/ | ||
element: null, | ||
destruct: function() { | ||
this.element.remove(); | ||
AView.prototype.destruct.call(this); | ||
}, | ||
/** | ||
* Show view. | ||
@@ -41,0 +58,0 @@ * Remove "hidden" class. |
{ | ||
"name": "mvc-pack", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"description": "Package of combined patterns to build rich MVC modules", | ||
@@ -14,2 +14,4 @@ "main": "dest/mvc-pack.js", | ||
"test": "grunt test", | ||
"coverage": "grunt coverage", | ||
"doc": "grunt doc", | ||
"preversion": "npm test", | ||
@@ -39,5 +41,6 @@ "prepublishOnly": "grunt build" | ||
"grunt-template": "^1.0.0", | ||
"grunt-wrap": "^0.3.0", | ||
"grunt-umd": "^2.4.0", | ||
"istanbul": "^0.4.5", | ||
"jsdoc-inheritance-diagram": "^1.0.0", | ||
"libumd": "github:valerii-zinchenko/libumd", | ||
"load-grunt-tasks": "^3.5.2", | ||
@@ -44,0 +47,0 @@ "mocha": "^4.0.1", |
@@ -79,3 +79,3 @@ 'use strict'; | ||
sinon.stub(Element.prototype, 'appendChild'); | ||
sinon.spy(Element.prototype, 'appendChild'); | ||
}); | ||
@@ -96,3 +96,6 @@ teardown(function(){ | ||
test('with component', function(){ | ||
var view = new AView(); | ||
var view = new (Class(DynamicView, null, { | ||
template: '<div></div><div></div>' | ||
}))(); | ||
view.render(); | ||
@@ -102,7 +105,6 @@ deco.setComponent(view); | ||
assert.isTrue(DynamicView.prototype.render.calledOnce, 'Parent\'s "render" should be called'); | ||
assert.isTrue(Element.prototype.appendChild.calledOnce, 'Decorator should append something into his container'); | ||
assert.equal(Element.prototype.appendChild.args[0][0], view.$el, 'Decorator should append the decorated component'); | ||
// ??? For some reasons this line hangs the test runner | ||
//assert.isTrue(Element.prototype.appendChild.withArgs(view.$el).calledOnce, 'Decorator should append the decorated component'); | ||
assert.isTrue(DynamicView.prototype.render.calledTwice, 'Parent\'s "render" should be called twice'); | ||
assert.isTrue(Element.prototype.appendChild.calledTwice, 'Decorator should append all view elementes into his container'); | ||
assert.equal(Element.prototype.appendChild.args[0][0], view.elements[0], 'Decorator should append the first view\'s element'); | ||
assert.equal(Element.prototype.appendChild.args[1][0], view.elements[1], 'Decorator should append the second view\'s element'); | ||
assert.isTrue(DynamicView.prototype.render.calledBefore(Element.prototype.appendChild), 'Parent\'s "render" method should be called before the decorator\'s component will be appended'); | ||
@@ -143,19 +145,12 @@ }); | ||
setup(function(){ | ||
sinon.stub(Element.prototype, 'querySelector'); | ||
sinon.stub(_, 'template'); | ||
sinon.spy(DynamicView.prototype, '_processTemplate'); | ||
}); | ||
teardown(function(){ | ||
Element.prototype.querySelector.restore(); | ||
_.template.restore(); | ||
DynamicView.prototype._processTemplate.restore(); | ||
}); | ||
test('processing', function(){ | ||
var templateRender = sinon.stub(); | ||
templateRender.returns(deco.template); | ||
_.template.withArgs(deco.template).returns(templateRender); | ||
test('parent\'s method should be called', function(){ | ||
deco._processTemplate(); | ||
assert.isTrue(templateRender.withArgs({model: deco.model, config: deco.config}).calledOnce, 'Model and configurations should be passed into the template rendering function'); | ||
assert.isTrue(Element.prototype.querySelector.withArgs('.component-container').calledOnce, 'Container for the component with the class name "component-container" should be searched'); | ||
assert.isTrue(DynamicView.prototype._processTemplate.calledOnce); | ||
}); | ||
@@ -162,0 +157,0 @@ }); |
@@ -47,8 +47,49 @@ 'use strict'; | ||
[], | ||
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 Controller: ' + Object.prototype.toString(input) + ' with a value: ' + input, | ||
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 | ||
@@ -80,4 +121,3 @@ }, | ||
Decorators: { | ||
Deco: function(){}, | ||
notdeco: '123' | ||
Deco: function(){} | ||
} | ||
@@ -153,4 +193,3 @@ }, | ||
Decorators: { | ||
Deco: Deco, | ||
incorrectDeco: incorrectDeco | ||
Deco: Deco | ||
} | ||
@@ -157,0 +196,0 @@ }))({}); |
@@ -13,8 +13,2 @@ 'use strict'; | ||
// TODO Remove this, after upgrading to a new PhantomJS version and verifying, that this method exists there | ||
// Old PhantomJS does not have the implementation for Element.prtotype.remove, so just define a dummy function for it, to be able to run tests from command line | ||
if (!Element.prototype.remove) { | ||
Element.prototype.remove = function() {}; | ||
} | ||
setup(function(){ | ||
@@ -31,3 +25,3 @@ aView = new AView({}); | ||
suite('setView()', function(){ | ||
suite('setControl()', function(){ | ||
test('incorrect view instance', function(){ | ||
@@ -55,3 +49,3 @@ [undefined, null, false, true, 0, 1, '', '1', [], {}, function(){}].forEach(function(testCase){ | ||
assert.isNull(aView.control, 'destruct() should set view to null'); | ||
assert.isNull(aView.control, 'destruct() should set control to null'); | ||
assert.isTrue(AModeComponent.prototype.destruct.calledOnce, 'Parent\'s destruct() should be called'); | ||
@@ -58,0 +52,0 @@ }); |
@@ -5,4 +5,4 @@ 'use strict'; | ||
suite('Constructor', function(){ | ||
test('is singleton', function(){ | ||
assert.notEqual(new DynamicView({}), new DynamicView({}), 'DynamicView should not behave as singleton'); | ||
test('is not a singleton', function(){ | ||
assert.notEqual(new DynamicView(), new DynamicView(), 'DynamicView should not behave as singleton'); | ||
}); | ||
@@ -14,3 +14,3 @@ }); | ||
setup(function(){ | ||
view = new DynamicView({}); | ||
view = new DynamicView(); | ||
}); | ||
@@ -79,2 +79,32 @@ teardown(function(){ | ||
}); | ||
suite('Destruction', function(){ | ||
setup(function(){ | ||
sinon.spy(AView.prototype, 'destruct'); | ||
sinon.spy(Element.prototype, 'remove'); | ||
}); | ||
teardown(function(){ | ||
AView.prototype.destruct.restore(); | ||
Element.prototype.remove.restore(); | ||
}); | ||
test('parent\'s method should be called', function(){ | ||
var view = new DynamicView(); | ||
view.destruct(); | ||
assert.isTrue(AView.prototype.destruct.calledOnce); | ||
}); | ||
test('all elements sould be removed and then parent\s method should be called', function(){ | ||
var view = new (Class(DynamicView, null, { | ||
template: '<div></div><div></div>' | ||
}))(); | ||
view.render(); | ||
view.destruct(); | ||
assert.isTrue(Element.prototype.remove.calledTwice); | ||
assert.isTrue(AView.prototype.destruct.calledOnce); | ||
assert.isTrue(AView.prototype.destruct.calledAfter(Element.prototype.remove)); | ||
}); | ||
}); | ||
}); |
@@ -29,2 +29,28 @@ 'use strict'; | ||
}; | ||
}), | ||
[undefined, null, 0, 1, false, true, '', 'str', [], function(){}].map(function(input){ | ||
var model = {}; | ||
return { | ||
input: { | ||
model: model, | ||
view: new AView(model), | ||
decorators: { | ||
deco: input | ||
} | ||
}, | ||
exception: 'Decorator "deco" should be inherited from ADecorator' | ||
}; | ||
}), | ||
[1, true, 'str', [], function(){}, {}].map(function(input){ | ||
var model = {}; | ||
return { | ||
input: { | ||
model: model, | ||
view: new AView(model), | ||
control: input | ||
}, | ||
exception: 'Control should be inherited from AControl' | ||
}; | ||
}) | ||
@@ -42,3 +68,3 @@ ).forEach(function(testCase){ | ||
suite('incompatible control object', function(){ | ||
[undefined, null, 0, 1, false, true, '', 'str', [], function(){}, {}].forEach(function(testCase){ | ||
[undefined, null, 0, false, ''].forEach(function(testCase){ | ||
test('input: ' + testCase, function(){ | ||
@@ -90,5 +116,4 @@ var result; | ||
var decorators = { | ||
notfn: {}, | ||
incomp: function(){}, | ||
deco: new (Class(ADecorator, null, {})) | ||
deco: new (Class(ADecorator, null, {})), | ||
anotherdeco: new (Class(ADecorator, null, {})) | ||
}; | ||
@@ -95,0 +120,0 @@ |
@@ -29,1 +29,5 @@ // polifill is from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind | ||
} | ||
// Old PhantomJS (1.9.8) does not have the implementation for Element.prtotype.remove, so just define a dummy function for it, to be able to run tests from command line | ||
Element.prototype.remove = Element.prototype.remove || function() {}; |
@@ -10,7 +10,7 @@ 'use strict'; | ||
test('initialize', function(){ | ||
new StaticView({}); | ||
new StaticView(); | ||
}); | ||
test('is singleton', function(){ | ||
assert.equal(new StaticView({}), new StaticView({}), 'StaticView should behave as singleton'); | ||
assert.equal(new StaticView(), new StaticView(), 'StaticView should behave as singleton'); | ||
}); | ||
@@ -22,3 +22,3 @@ }); | ||
setup(function() { | ||
view = new StaticView({}); | ||
view = new StaticView(); | ||
}); | ||
@@ -57,2 +57,26 @@ teardown(function(){ | ||
}); | ||
suite('Destruction', function(){ | ||
setup(function(){ | ||
sinon.spy(AView.prototype, 'destruct'); | ||
sinon.spy(Element.prototype, 'remove'); | ||
}); | ||
teardown(function(){ | ||
StaticView.instance = null; | ||
AView.prototype.destruct.restore(); | ||
Element.prototype.remove.restore(); | ||
}); | ||
test('the element should be removed and then parent\s method should be called', function(){ | ||
var view = new StaticView(); | ||
view.element = document.createElement('div'); | ||
view.render(); | ||
view.destruct(); | ||
assert.isTrue(Element.prototype.remove.calledOnce); | ||
assert.isTrue(AView.prototype.destruct.calledOnce); | ||
assert.isTrue(AView.prototype.destruct.calledAfter(Element.prototype.remove)); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
106158
32
3305
17