Comparing version 0.2.3 to 0.2.4
@@ -110,2 +110,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
this.modelListeners = []; | ||
this.dynamicListeners = []; | ||
this.model = model; | ||
@@ -130,2 +131,18 @@ this.initModelEvents(); | ||
/** | ||
* Attach handler to View DOM events like are click, or model events. | ||
* @param eventType any DOM Event type | ||
* @param selector "model" or simple class selector like are: ".my-class". | ||
* Selectors like are ".a .b .c" does not supported. | ||
*/ | ||
on(eventType, selector, handler) { | ||
const handlerArgs = ControllerMeta_1.findHandlerArguments(this, handler.name); | ||
handler = handler.bind(this); | ||
this.dynamicListeners.push({ | ||
eventType, | ||
selector, | ||
handler, | ||
handlerArgs | ||
}); | ||
} | ||
/** | ||
* Destroy controller and clear memory. | ||
@@ -161,7 +178,7 @@ * Detach all listeners. | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isDomListener = exports.isModelListener = exports.getListeners = exports.arg = exports.on = void 0; | ||
exports.isDomListener = exports.isModelListener = exports.findHandlerArguments = exports.getListeners = exports.arg = exports.on = void 0; | ||
/** | ||
* Attach handler to View DOM events like are click, or model events. | ||
* @param eventType any DOM Event type | ||
* @param selector "model" or simple class selector like are: ".my-class". | ||
* @param eventTypeOrModel any DOM Event type or Model constructor | ||
* @param selectorOrModelEventType selector like are: ".my-class" or model eventType | ||
* Selectors like are ".a .b .c" does not supported. | ||
@@ -237,5 +254,14 @@ */ | ||
const listeners = []; | ||
listenersMeta.push(...controller.dynamicListeners); | ||
for (const listenerMeta of listenersMeta) { | ||
const handler = controller[listenerMeta.methodName].bind(controller); | ||
const handlerArgs = findHandlerArguments(controller, listenerMeta.methodName); | ||
let handler; | ||
let handlerArgs = []; | ||
if (listenerMeta.methodName) { | ||
handler = controller[listenerMeta.methodName].bind(controller); | ||
handlerArgs = findHandlerArguments(controller, listenerMeta.methodName); | ||
} | ||
else { | ||
handler = listenerMeta.handler; | ||
handlerArgs = listenerMeta.handlerArgs; | ||
} | ||
const listener = { | ||
@@ -261,2 +287,3 @@ eventType: listenerMeta.eventType, | ||
} | ||
exports.findHandlerArguments = findHandlerArguments; | ||
function isModelListener(listener) { | ||
@@ -512,3 +539,3 @@ return (typeof listener.selector !== "string"); | ||
createControllers() { | ||
const Constructors = this.controllers(); | ||
const Controllers = this.controllers(this.model); | ||
this.controllersInstances = []; | ||
@@ -520,7 +547,15 @@ const originalEmit = this.model.emit; | ||
}; | ||
for (const Constructor of Constructors) { | ||
CurrentConstructor = Constructor; | ||
const controller = new Constructor(this.model); | ||
domEvents.addController(controller, this); | ||
this.controllersInstances.push(controller); | ||
for (const ConstructorOrInstance of Controllers) { | ||
if (typeof ConstructorOrInstance === "function") { | ||
CurrentConstructor = ConstructorOrInstance; | ||
const controller = new CurrentConstructor(this.model); | ||
domEvents.addController(controller, this); | ||
this.controllersInstances.push(controller); | ||
} | ||
else { | ||
const controller = ConstructorOrInstance; | ||
CurrentConstructor = controller.constructor; | ||
domEvents.addController(controller, this); | ||
this.controllersInstances.push(controller); | ||
} | ||
} | ||
@@ -563,3 +598,3 @@ this.model.emit = originalEmit; | ||
*/ | ||
controllers() { | ||
controllers(model) { | ||
return []; | ||
@@ -566,0 +601,0 @@ } |
@@ -1,2 +0,2 @@ | ||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("ReactDOM"),require("React"),require("EventEmitterModule"));else if("function"==typeof define&&define.amd)define(["ReactDOM","React","EventEmitterModule"],t);else{var n="object"==typeof exports?t(require("ReactDOM"),require("React"),require("EventEmitterModule")):t(e.ReactDOM,e.React,e.EventEmitterModule);for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}(window,(function(e,t,n){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=4)}([function(t,n){t.exports=e},function(e,t,n){"use strict";function r(e,t){return(e.constructor.prototype._handlersArguments||[]).filter(e=>e.methodName===t).sort((e,t)=>e.argumentIndex-t.argumentIndex).map(e=>e.eventPropertyPath)}function o(e){return"string"!=typeof e.selector}Object.defineProperty(t,"__esModule",{value:!0}),t.isDomListener=t.isModelListener=t.getListeners=t.arg=t.on=void 0,t.on=function(e,t){let n,r;if("string"==typeof e){n=e,r=t;if(!/^\.[\w-]+$/.test(r))throw new Error(`invalid selector "${r}", selector should be just className like are ".some-class"`)}else n=t,r=e;return(e,t,o)=>{e._listenersMeta||(e._listenersMeta=[]);const s={eventType:n,selector:r,methodName:t};e._listenersMeta.push(s)}},t.arg=function(e,t,...n){return(r,o,s)=>{r._handlersArguments||(r._handlersArguments=[]);const i={methodName:o,argumentIndex:s,eventPropertyPath:[]};if("string"==typeof e){const r=[e];t&&r.push(t),n.length&&r.push(...n),i.eventPropertyPath=r}else{const t=e;i.eventPropertyPath=t}r._handlersArguments.push(i)}},t.getListeners=function(e){const t=e.constructor.prototype._listenersMeta||[],n=[];for(const o of t){const t=e[o.methodName].bind(e),s=r(e,o.methodName),i={eventType:o.eventType,selector:o.selector,handlerArgs:s,handler:t};n.push(i)}return n},t.isModelListener=o,t.isDomListener=function(e){return!o(e)}},function(e,n){e.exports=t},function(e,t){e.exports=n},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.arg=t.on=t.Controller=t.View=t.Model=t.EventEmitter=t.ReactDOM=t.React=void 0;const i=s(n(2));t.React=i;const l=s(n(0));t.ReactDOM=l;const c=n(3);Object.defineProperty(t,"EventEmitter",{enumerable:!0,get:function(){return c.EventEmitter}});const u=n(1);Object.defineProperty(t,"on",{enumerable:!0,get:function(){return u.on}}),Object.defineProperty(t,"arg",{enumerable:!0,get:function(){return u.arg}});const d=n(5);Object.defineProperty(t,"Model",{enumerable:!0,get:function(){return d.Model}});const a=n(6);Object.defineProperty(t,"View",{enumerable:!0,get:function(){return a.View}});const f=n(12);if(Object.defineProperty(t,"Controller",{enumerable:!0,get:function(){return f.Controller}}),"undefined"!=typeof window){const e=window;e.MVC={React:i,ReactDOM:l,EventEmitter:c.EventEmitter,Model:d.Model,View:a.View,Controller:f.Controller,on:u.on,arg:u.arg},e.React||(e.React=i),e.ReactDOM||(e.ReactDOM=l),e.EventEmitter||(e.EventEmitter=c.EventEmitter)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Model=void 0;const r=n(3);class o extends r.EventEmitter{set(e,t={}){const n={};let r=!1;for(const t in e){const o=e[t];o!==this[t]&&(r=!0,this[t]=o,n[t]=o)}r&&this.emit("change",n,t)}on(e,t){return super.on(e,t)}}t.Model=o},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.View=void 0;const i=s(n(2)),l=s(n(0)),c=new(n(7).DOMEvents);class u extends i.Component{constructor(e){super(e),this.model=e.model,this.createControllers(),this.listenModelChanges()}createControllers(){const e=this.controllers();this.controllersInstances=[];const t=this.model.emit;let n;this.model.emit=e=>{throw new Error(`${n.name}: it is forbidden to emit any model event inside the controller constructor. Triggered "${e}"`)};for(const t of e){n=t;const e=new t(this.model);c.addController(e,this),this.controllersInstances.push(e)}this.model.emit=t}listenModelChanges(){this.model.on("change",e=>{this.setState({changes:e})})}render(){return this.template(this.model)}componentDidMount(){l.findDOMNode(this)._model=this.model}componentWillUnmount(){this.onDestroy();delete l.findDOMNode(this)._model,c.destroyListeners(this);for(const e of this.controllersInstances)e.destroy();this.controllersInstances=[]}onDestroy(){}controllers(){return[]}}t.View=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.DOMEvents=void 0;const r=n(8),o=n(1);t.DOMEvents=class{constructor(){this.listeners=[]}addController(e,t){const n=o.getListeners(e);for(const e of n)this.addListener(e,t)}destroyListeners(e){const t=this.listeners.filter(t=>t.view===e);for(const e of t){e.destroy();const t=this.listeners.indexOf(e);this.listeners.splice(t,1)}}addListener(e,t){if(!o.isDomListener(e))return;const n=new r.DOMListener({eventType:e.eventType,selector:e.selector,handlerArgs:e.handlerArgs,handler:e.handler,view:t});n.listen(),this.listeners.push(n)}}},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.DOMListener=void 0;const i=s(n(0)),l=n(9),c=n(10),u=n(11);t.DOMListener=class{constructor(e){this.realEventType=function(e){if("blur"===e)return"focusout";if("focus"===e)return"focusin";return e}(e.eventType),this.selector=e.selector,this.handlerArgs=e.handlerArgs,this.handler=e.handler,this.view=e.view}listen(){this.domHandler=e=>{this.onDOMEvent(e)},document.addEventListener(this.realEventType,this.domHandler)}destroy(){document.removeEventListener(this.realEventType,this.domHandler),delete this.view,delete this.handler,delete this.domHandler,delete this.handlerArgs}onDOMEvent(e){if(this.isValidEvent(e)){const t=this.getHandlerArgs(e);this.handler(...t)}}isValidEvent(e){const t=i.findDOMNode(this.view);return l.isValidTarget({componentEl:t,selector:this.selector,target:e.target})}getHandlerArgs(e){return this.handlerArgs.map(t=>{if("function"==typeof t){const n=t,r=u.getNearestModelByEvent(e,n);if(!r)throw new Error("cannot find model: "+n.name);return r}return c.getPropertyFromEvent(e,t)})}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isValidTarget=void 0,t.isValidTarget=function(e){let t=e.target,n=!1,r=!1;const o=e.selector.replace(".","");for(;t;){if(t.classList.contains(o)&&(r=!0),t===e.componentEl){n=!0;break}t=t.parentElement}return n&&r}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getPropertyFromEvent=void 0,t.getPropertyFromEvent=function(e,t){let n=e;for(const e of t)n=n[e];return n}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getNearestModelByEvent=void 0,t.getNearestModelByEvent=function(e,t){let n=e.target;for(;n;){const e=n._model;if(e instanceof t)return e;n=n.parentElement}return null}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Controller=void 0;const r=n(1);t.Controller=class{constructor(e){this.modelListeners=[],this.model=e,this.initModelEvents()}initModelEvents(){const e=r.getListeners(this).filter(e=>r.isModelListener(e));for(const t of e){const e=t.eventType,n=(...e)=>{t.handler(...e)};this.modelListeners.push({eventType:e,handler:n}),this.model.on(e,n)}}destroy(){this.onDestroy();for(const e of this.modelListeners)this.model.removeListener(e.eventType,e.handler);delete this.model}onDestroy(){}}}])})); | ||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("ReactDOM"),require("React"),require("EventEmitterModule"));else if("function"==typeof define&&define.amd)define(["ReactDOM","React","EventEmitterModule"],t);else{var n="object"==typeof exports?t(require("ReactDOM"),require("React"),require("EventEmitterModule")):t(e.ReactDOM,e.React,e.EventEmitterModule);for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}(window,(function(e,t,n){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=4)}([function(t,n){t.exports=e},function(e,t,n){"use strict";function r(e,t){return(e.constructor.prototype._handlersArguments||[]).filter(e=>e.methodName===t).sort((e,t)=>e.argumentIndex-t.argumentIndex).map(e=>e.eventPropertyPath)}function o(e){return"string"!=typeof e.selector}Object.defineProperty(t,"__esModule",{value:!0}),t.isDomListener=t.isModelListener=t.findHandlerArguments=t.getListeners=t.arg=t.on=void 0,t.on=function(e,t){let n,r;if("string"==typeof e){n=e,r=t;if(!/^\.[\w-]+$/.test(r))throw new Error(`invalid selector "${r}", selector should be just className like are ".some-class"`)}else n=t,r=e;return(e,t,o)=>{e._listenersMeta||(e._listenersMeta=[]);const s={eventType:n,selector:r,methodName:t};e._listenersMeta.push(s)}},t.arg=function(e,t,...n){return(r,o,s)=>{r._handlersArguments||(r._handlersArguments=[]);const i={methodName:o,argumentIndex:s,eventPropertyPath:[]};if("string"==typeof e){const r=[e];t&&r.push(t),n.length&&r.push(...n),i.eventPropertyPath=r}else{const t=e;i.eventPropertyPath=t}r._handlersArguments.push(i)}},t.getListeners=function(e){const t=e.constructor.prototype._listenersMeta||[],n=[];t.push(...e.dynamicListeners);for(const o of t){let t,s=[];o.methodName?(t=e[o.methodName].bind(e),s=r(e,o.methodName)):(t=o.handler,s=o.handlerArgs);const i={eventType:o.eventType,selector:o.selector,handlerArgs:s,handler:t};n.push(i)}return n},t.findHandlerArguments=r,t.isModelListener=o,t.isDomListener=function(e){return!o(e)}},function(e,n){e.exports=t},function(e,t){e.exports=n},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.arg=t.on=t.Controller=t.View=t.Model=t.EventEmitter=t.ReactDOM=t.React=void 0;const i=s(n(2));t.React=i;const l=s(n(0));t.ReactDOM=l;const c=n(3);Object.defineProperty(t,"EventEmitter",{enumerable:!0,get:function(){return c.EventEmitter}});const u=n(1);Object.defineProperty(t,"on",{enumerable:!0,get:function(){return u.on}}),Object.defineProperty(t,"arg",{enumerable:!0,get:function(){return u.arg}});const d=n(5);Object.defineProperty(t,"Model",{enumerable:!0,get:function(){return d.Model}});const a=n(6);Object.defineProperty(t,"View",{enumerable:!0,get:function(){return a.View}});const f=n(12);if(Object.defineProperty(t,"Controller",{enumerable:!0,get:function(){return f.Controller}}),"undefined"!=typeof window){const e=window;e.MVC={React:i,ReactDOM:l,EventEmitter:c.EventEmitter,Model:d.Model,View:a.View,Controller:f.Controller,on:u.on,arg:u.arg},e.React||(e.React=i),e.ReactDOM||(e.ReactDOM=l),e.EventEmitter||(e.EventEmitter=c.EventEmitter)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Model=void 0;const r=n(3);class o extends r.EventEmitter{set(e,t={}){const n={};let r=!1;for(const t in e){const o=e[t];o!==this[t]&&(r=!0,this[t]=o,n[t]=o)}r&&this.emit("change",n,t)}on(e,t){return super.on(e,t)}}t.Model=o},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.View=void 0;const i=s(n(2)),l=s(n(0)),c=new(n(7).DOMEvents);class u extends i.Component{constructor(e){super(e),this.model=e.model,this.createControllers(),this.listenModelChanges()}createControllers(){const e=this.controllers(this.model);this.controllersInstances=[];const t=this.model.emit;let n;this.model.emit=e=>{throw new Error(`${n.name}: it is forbidden to emit any model event inside the controller constructor. Triggered "${e}"`)};for(const t of e)if("function"==typeof t){n=t;const e=new n(this.model);c.addController(e,this),this.controllersInstances.push(e)}else{const e=t;n=e.constructor,c.addController(e,this),this.controllersInstances.push(e)}this.model.emit=t}listenModelChanges(){this.model.on("change",e=>{this.setState({changes:e})})}render(){return this.template(this.model)}componentDidMount(){l.findDOMNode(this)._model=this.model}componentWillUnmount(){this.onDestroy();delete l.findDOMNode(this)._model,c.destroyListeners(this);for(const e of this.controllersInstances)e.destroy();this.controllersInstances=[]}onDestroy(){}controllers(e){return[]}}t.View=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.DOMEvents=void 0;const r=n(8),o=n(1);t.DOMEvents=class{constructor(){this.listeners=[]}addController(e,t){const n=o.getListeners(e);for(const e of n)this.addListener(e,t)}destroyListeners(e){const t=this.listeners.filter(t=>t.view===e);for(const e of t){e.destroy();const t=this.listeners.indexOf(e);this.listeners.splice(t,1)}}addListener(e,t){if(!o.isDomListener(e))return;const n=new r.DOMListener({eventType:e.eventType,selector:e.selector,handlerArgs:e.handlerArgs,handler:e.handler,view:t});n.listen(),this.listeners.push(n)}}},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.DOMListener=void 0;const i=s(n(0)),l=n(9),c=n(10),u=n(11);t.DOMListener=class{constructor(e){this.realEventType=function(e){if("blur"===e)return"focusout";if("focus"===e)return"focusin";return e}(e.eventType),this.selector=e.selector,this.handlerArgs=e.handlerArgs,this.handler=e.handler,this.view=e.view}listen(){this.domHandler=e=>{this.onDOMEvent(e)},document.addEventListener(this.realEventType,this.domHandler)}destroy(){document.removeEventListener(this.realEventType,this.domHandler),delete this.view,delete this.handler,delete this.domHandler,delete this.handlerArgs}onDOMEvent(e){if(this.isValidEvent(e)){const t=this.getHandlerArgs(e);this.handler(...t)}}isValidEvent(e){const t=i.findDOMNode(this.view);return l.isValidTarget({componentEl:t,selector:this.selector,target:e.target})}getHandlerArgs(e){return this.handlerArgs.map(t=>{if("function"==typeof t){const n=t,r=u.getNearestModelByEvent(e,n);if(!r)throw new Error("cannot find model: "+n.name);return r}return c.getPropertyFromEvent(e,t)})}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isValidTarget=void 0,t.isValidTarget=function(e){let t=e.target,n=!1,r=!1;const o=e.selector.replace(".","");for(;t;){if(t.classList.contains(o)&&(r=!0),t===e.componentEl){n=!0;break}t=t.parentElement}return n&&r}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getPropertyFromEvent=void 0,t.getPropertyFromEvent=function(e,t){let n=e;for(const e of t)n=n[e];return n}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getNearestModelByEvent=void 0,t.getNearestModelByEvent=function(e,t){let n=e.target;for(;n;){const e=n._model;if(e instanceof t)return e;n=n.parentElement}return null}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Controller=void 0;const r=n(1);t.Controller=class{constructor(e){this.modelListeners=[],this.dynamicListeners=[],this.model=e,this.initModelEvents()}initModelEvents(){const e=r.getListeners(this).filter(e=>r.isModelListener(e));for(const t of e){const e=t.eventType,n=(...e)=>{t.handler(...e)};this.modelListeners.push({eventType:e,handler:n}),this.model.on(e,n)}}on(e,t,n){const o=r.findHandlerArguments(this,n.name);n=n.bind(this),this.dynamicListeners.push({eventType:e,selector:t,handler:n,handlerArgs:o})}destroy(){this.onDestroy();for(const e of this.modelListeners)this.model.removeListener(e.eventType,e.handler);delete this.model}onDestroy(){}}}])})); | ||
//# sourceMappingURL=only-mvc.min.js.map |
import { Model } from "./Model"; | ||
import { getListeners, isModelListener } from "./ControllerMeta"; | ||
import { getListeners, isModelListener, findHandlerArguments } from "./ControllerMeta"; | ||
@@ -7,2 +7,3 @@ export abstract class Controller<TModel extends Model> { | ||
private modelListeners: any[] = []; | ||
private dynamicListeners: any[] = []; | ||
@@ -35,2 +36,24 @@ constructor(model: TModel) { | ||
/** | ||
* Attach handler to View DOM events like are click, or model events. | ||
* @param eventType any DOM Event type | ||
* @param selector "model" or simple class selector like are: ".my-class". | ||
* Selectors like are ".a .b .c" does not supported. | ||
*/ | ||
on( | ||
eventType: keyof HTMLElementEventMap, | ||
selector: string, | ||
handler: (...args: any[]) => void | ||
) { | ||
const handlerArgs = findHandlerArguments(this, handler.name); | ||
handler = handler.bind(this); | ||
this.dynamicListeners.push({ | ||
eventType, | ||
selector, | ||
handler, | ||
handlerArgs | ||
}); | ||
} | ||
/** | ||
* Destroy controller and clear memory. | ||
@@ -37,0 +60,0 @@ * Detach all listeners. |
@@ -15,3 +15,5 @@ import { Model } from "./Model"; | ||
selector: string | TModelConstructor; | ||
methodName: string; | ||
methodName?: string; | ||
handler?: (...args: any[]) => void; | ||
handlerArgs?: HandlerArg[]; | ||
} | ||
@@ -30,4 +32,4 @@ | ||
* Attach handler to View DOM events like are click, or model events. | ||
* @param eventType any DOM Event type | ||
* @param selector "model" or simple class selector like are: ".my-class". | ||
* @param eventTypeOrModel any DOM Event type or Model constructor | ||
* @param selectorOrModelEventType selector like are: ".my-class" or model eventType | ||
* Selectors like are ".a .b .c" does not supported. | ||
@@ -135,9 +137,23 @@ */ | ||
listenersMeta.push( | ||
...(controller as any).dynamicListeners | ||
); | ||
for (const listenerMeta of listenersMeta) { | ||
const handler = (controller as any)[ listenerMeta.methodName ].bind(controller); | ||
const handlerArgs = findHandlerArguments( | ||
controller, | ||
listenerMeta.methodName | ||
); | ||
let handler: (...args: any[]) => void; | ||
let handlerArgs: HandlerArg[] = []; | ||
if ( listenerMeta.methodName ) { | ||
handler = (controller as any)[ listenerMeta.methodName ].bind(controller); | ||
handlerArgs = findHandlerArguments( | ||
controller, | ||
listenerMeta.methodName | ||
); | ||
} | ||
else { | ||
handler = listenerMeta.handler as (...args: any[]) => void; | ||
handlerArgs = listenerMeta.handlerArgs as HandlerArg[]; | ||
} | ||
const listener: IListener = { | ||
@@ -156,3 +172,3 @@ eventType: listenerMeta.eventType, | ||
function findHandlerArguments(controller: Controller<any>, methodName: string): HandlerArg[] { | ||
export function findHandlerArguments(controller: Controller<any>, methodName: string): HandlerArg[] { | ||
const proto = controller.constructor.prototype; | ||
@@ -159,0 +175,0 @@ |
@@ -33,3 +33,3 @@ import * as React from "react"; | ||
private createControllers() { | ||
const Constructors = this.controllers(); | ||
const Controllers = this.controllers(this.model); | ||
this.controllersInstances = []; | ||
@@ -44,9 +44,19 @@ | ||
for (const Constructor of Constructors) { | ||
CurrentConstructor = Constructor; | ||
for (const ConstructorOrInstance of Controllers) { | ||
if ( typeof ConstructorOrInstance === "function" ) { | ||
CurrentConstructor = ConstructorOrInstance; | ||
const controller = new Constructor(this.model); | ||
domEvents.addController(controller, this); | ||
const controller = new CurrentConstructor(this.model); | ||
domEvents.addController(controller, this); | ||
this.controllersInstances.push(controller); | ||
this.controllersInstances.push(controller); | ||
} | ||
else { | ||
const controller = ConstructorOrInstance; | ||
CurrentConstructor = controller.constructor; | ||
domEvents.addController(controller, this); | ||
this.controllersInstances.push(controller); | ||
} | ||
} | ||
@@ -101,5 +111,8 @@ | ||
*/ | ||
controllers(): (new (model: TModel) => Controller<TModel>)[] { | ||
controllers(model: TModel): ( | ||
(new (model: TModel) => Controller<TModel>) | | ||
Controller<TModel> | ||
)[] { | ||
return []; | ||
} | ||
} |
{ | ||
"name": "mvc-tsx", | ||
"version": "0.2.3", | ||
"version": "0.2.4", | ||
"description": "MVC based on React", | ||
@@ -5,0 +5,0 @@ "main": "bundle/mvc-and-deps.min.js", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
5500020
56438