Comparing version 0.6.10 to 0.6.11
{ | ||
"name": "imvvm", | ||
"version": "0.6.10", | ||
"version": "0.6.11", | ||
"homepage": "https://github.com/entrendipity/imvvm", | ||
@@ -5,0 +5,0 @@ "authors": [ |
@@ -38,3 +38,4 @@ !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.IMVVM=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ | ||
var nextState = {}, | ||
prevState = {}, | ||
prevState = void(0), | ||
redoState = void(0), | ||
newStateKeys, | ||
@@ -63,6 +64,6 @@ keyIdx, | ||
if(Object.getPrototypeOf(newState).constructor.classType === "DomainViewModel") { | ||
nextState = extend(newState); | ||
prevState = newState.previousState; | ||
redoState = newAppState; | ||
//Need to reset ViewModel with instance object so that setState is associated with | ||
@@ -202,3 +203,3 @@ //the current ViewModel. This reason this ccurs is that when a ViewModel is created it | ||
appState = new ApplicationDataContext(nextState, prevState, enableUndo); | ||
appState = new ApplicationDataContext(nextState, prevState, redoState, enableUndo); | ||
Object.freeze(appState); | ||
@@ -219,3 +220,3 @@ Object.freeze(appState.state); | ||
/*Need to look at DomainViewModel state and nextState and Domain Model and updating*/ | ||
appState = new ApplicationDataContext(void(0), void(0), enableUndo, true); | ||
appState = new ApplicationDataContext(void(0), void(0), void(0), enableUndo, true); | ||
appState.state = appState.state || {}; | ||
@@ -282,3 +283,3 @@ | ||
appState = new ApplicationDataContext(appState, void(0), enableUndo); | ||
appState = new ApplicationDataContext(appState, void(0), void(0), enableUndo); | ||
Object.freeze(appState.state); | ||
@@ -425,3 +426,13 @@ Object.freeze(appState); | ||
var dataContext = function(nextState, prevState, enableUndo, initialize) { | ||
desc.proto.undo = function(){ | ||
this.setState(this.previousState, !!this.previousState ? this : void(0)); | ||
}; | ||
desc.proto.redo = function(){ | ||
if(this.canRedo){ | ||
this.setState(this.nextState, this.nextState.nextState); | ||
} | ||
}; | ||
var dataContext = function(nextState, prevState, redoState, enableUndo, initialize) { | ||
@@ -432,9 +443,45 @@ var freezeFields = desc.freezeFields, | ||
if(!!enableUndo && !!prevState){ | ||
Object.defineProperty(domainModel, 'previousState', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: prevState | ||
}); | ||
if(!!enableUndo){ | ||
if(!!prevState){ | ||
Object.defineProperty(domainModel, 'previousState', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: prevState | ||
}); | ||
Object.defineProperty(domainModel, 'canUndo', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: true | ||
}); | ||
} else { | ||
Object.defineProperty(domainModel, 'canUndo', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: false | ||
}); | ||
} | ||
if(!!redoState && 'state' in redoState){ | ||
Object.defineProperty(domainModel, 'nextState', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: redoState | ||
}); | ||
Object.defineProperty(domainModel, 'canRedo', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: true | ||
}); | ||
} else { | ||
Object.defineProperty(domainModel, 'canRedo', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: false | ||
}); | ||
} | ||
} | ||
@@ -441,0 +488,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(b){if("object"==typeof exports){module.exports=b()}else{if("function"==typeof define&&define.amd){define(b)}else{var a;"undefined"!=typeof window?a=window:"undefined"!=typeof global?a=global:"undefined"!=typeof self&&(a=self),a.IMVVM=b()}}}(function(){var d,b,a;return(function c(f,k,h){function g(n,l){if(!k[n]){if(!f[n]){var i=typeof require=="function"&&require;if(!l&&i){return i(n,!0)}if(e){return e(n,!0)}throw new Error("Cannot find module '"+n+"'")}var m=k[n]={exports:{}};f[n][0].call(m.exports,function(o){var p=f[n][1][o];return g(p?p:o)},m,m.exports,c,f,k,h)}return k[n].exports}var e=typeof require=="function"&&require;for(var j=0;j<h.length;j++){g(h[j])}return g})({1:[function(h,g,f){var e=h("./src/imvvm.js");g.exports=e},{"./src/imvvm.js":3}],2:[function(h,g,f){var e=h("./utils");var i=e.extend;f.getInitialState=function(l,m,v,k){if(typeof v!=="function"){throw new TypeError()}k===void (0)?true:k;var A,u={},r={},B,j={},y={},t,q={},o={},x,w,z,s,p;var n=function(E,I,K,P){var R={},N={},L,G,F,D,H,J=[],O,M,C,Q;if(typeof K==="function"){P=K;K={}}I=I||{};L=Object.keys(I);if(Object.getPrototypeOf(I).constructor.classType==="DomainViewModel"){R=i(I);N=I.previousState;for(D in B){R[D]=new r[D](R)}for(D in B){if(B.hasOwnProperty(D)){for(H in j[D]){if(j[D].hasOwnProperty(H)){R[D].state[j[D][H]]=(H in B)?i(R[H].state):R[H]}}}}}else{if(!!L.length){if(E===l){R=i(I)}else{R[E]=i(I)}}q=i(R,q,K);transientStateKeys=Object.keys(q);if(transientStateKeys.length===0){return}if(typeof P==="function"){P();return}F=transientStateKeys.length-1;for(G=F;G>=0;G--){if(transientStateKeys[G] in B){R[transientStateKeys[G]]=i(u[transientStateKeys[G]],q[transientStateKeys[G]]);R[transientStateKeys[G]]=new r[transientStateKeys[G]](R)}else{R[transientStateKeys[G]]=q[transientStateKeys[G]]}}o=i(o,R);R=i(u,o);q={};for(G=F;G>=0;G--){if(transientStateKeys[G] in y){for(M in y[transientStateKeys[G]]){if(y[transientStateKeys[G]].hasOwnProperty(M)){if(L.indexOf(M)!==-1){C=y[transientStateKeys[G]][M];for(Q in C){if(C.hasOwnProperty(Q)){q=i(q,C[Q].call(u[Q],R[transientStateKeys[G]][M],u[transientStateKeys[G]][M],M,transientStateKeys[G]))}}}}}}}if(!!Object.keys(q).length){n(void (0),{},q);return}J=Object.keys(o);O=J.length-1;for(G=O;G>=0;G--){if(E===l){if(J[G] in j[l]){for(D in j[l][J[G]]){if(j[l][J[G]].hasOwnProperty(D)){R[D].state[j[l][J[G]][D]]=R[J[G]]}if(D in j){for(dataContext2 in j[D]){if(j[D].hasOwnProperty(dataContext2)){R[D].state[j[D][dataContext2]]=(dataContext2 in B)?i(R[dataContext2].state):R[dataContext2]}}}}}}else{if(J[G] in j){for(D in j[J[G]]){if(j[J[G]].hasOwnProperty(D)){R[J[G]].state[j[J[G]][D]]=(D in B)?i(R[D].state):R[D]}if(D in j){for(dataContext2 in j[D]){if(j[D].hasOwnProperty(dataContext2)){R[D].state[j[D][dataContext2]]=(dataContext2 in B)?i(R[dataContext2].state):R[dataContext2]}}}}}}}N=u}if(!!N){Object.freeze(N)}u=new A(R,N,k);Object.freeze(u);Object.freeze(u.state);v(u);q={};o={};return u};A=m.call(this,n.bind(this,l));u=new A(void (0),void (0),k,true);u.state=u.state||{};B=u.getDomainDataContext();for(t in B){if(B.hasOwnProperty(t)){r[t]=B[t].call(this,n.bind(this,t)).bind(this,t);u.state[t]=new r[t](u.state);if("getWatchedState" in u[t]){x=u[t].getWatchedState();for(w in x){if(x.hasOwnProperty(w)){if(w in B||w in u.state){if("alias" in x[w]){if(!(t in j)){j[t]={}}j[t][w]=x[w].alias;if(!(w in B)){if(!(l in j)){j[l]={}}if(!(t in j[l])){j[l][w]={}}j[l][w][t]=x[w].alias}}for(z in x[w].fields){if(x[w].fields.hasOwnProperty(z)){if(w in B){s={};if(!(w in y)){y[w]={}}s[z]={};s[z][t]=x[w].fields[z];y[w]=s}}}}}}}}}for(t in B){if(B.hasOwnProperty(t)){for(p in j[t]){if(j[t].hasOwnProperty(p)){u[t].state[j[t][p]]=(p in B)?i(u[p].state):u[p]}}}}u=new A(u,void (0),k);Object.freeze(u.state);Object.freeze(u);return u}},{"./utils":8}],3:[function(f,g,j){var k=f("./imvvmModel");var p=f("./imvvmViewModel");var i=f("./imvvmDomainViewModel");var r=f("./mixin");var q=f("./utils");var o=q.extend;var m=q.mixInto;var l=function(){};var h=function(){};var n=function(){};m(l,k.Mixin);m(h,p.Mixin);m(n,i.Mixin);var e={createClass:function(u,v,t){var y=function(){};y.prototype=new u();y.prototype.constructor=y;var x=y;var w=function(z){var A=new x();return A.construct.apply(w,arguments)};w.componentConstructor=y;y.ConvenienceConstructor=w;w.originalSpec=t;w.type=y;y.prototype.type=y;w.classType=v;y.prototype.classType=v;w.getDescriptor=function(){var E={},D=this.prototype,B={},z=[],A={},C;if("__processedObject__" in this.originalSpec){return this.originalSpec.__processedObject__}for(C in this.originalSpec){if(this.originalSpec.hasOwnProperty(C)){if("get" in this.originalSpec[C]||"set" in this.originalSpec[C]){this.originalSpec[C].enumerable=true;if("aliasFor" in this.originalSpec[C]){A[this.originalSpec[C].aliasFor]=C;delete this.originalSpec[C].aliasFor}if("viewModel" in this.originalSpec[C]){B[C]=this.originalSpec[C].viewModel;delete this.originalSpec[C].viewModel;delete this.originalSpec[C].set}else{if("kind" in this.originalSpec[C]){if(this.originalSpec[C].kind==="pseudo"){this.originalSpec[C].enumerable=false}else{z.push({fieldName:C,kind:this.originalSpec[C].kind})}delete this.originalSpec[C].kind}}E[C]=this.originalSpec[C]}else{D[C]=this.originalSpec[C]}}}if(!("extend" in D)){D.extend=q.extend}if(!!Object.keys(B).length){D.getDomainDataContext=function(){return B}}this.originalSpec.__processedObject__={descriptor:E,proto:D,originalSpec:this.originalSpec||{},freezeFields:z,aliases:A};return this.originalSpec.__processedObject__};return w}};var s={createModel:e.createClass.bind(this,l,"Model"),createViewModel:e.createClass.bind(this,h,"ViewModel"),createDomainViewModel:e.createClass.bind(this,n,"DomainViewModel"),mixin:r};g.exports=s},{"./imvvmDomainViewModel":4,"./imvvmModel":5,"./imvvmViewModel":6,"./mixin":7,"./utils":8}],4:[function(j,h,f){var e=j("./utils");var k=e.extend;var g=e.getDescriptor;var i={Mixin:{construct:function(m){var n=this.getDescriptor(this);n.proto.setState=m;var l=function(q,u,t,o){var s=n.freezeFields,r=Object.create(n.proto,n.descriptor),p;if(!!t&&!!u){Object.defineProperty(r,"previousState",{configurable:false,enumerable:false,writable:false,value:u})}if(q===void (0)&&("getInitialState" in r)){q=r.getInitialState.call(r)}else{if("state" in q){delete q.state;Object.defineProperty(r,"state",{configurable:true,enumerable:false,writable:true,value:q});q=k(q,r)}}Object.defineProperty(r,"state",{configurable:false,enumerable:false,writable:false,value:q});for(p=s.length-1;p>=0;p--){Object.freeze(r[s[p].fieldName])}return r};return l}}};h.exports=i},{"./utils":8}],5:[function(i,h,f){var e=i("./utils");var k=e.extend;var g=e.getDescriptor;var j={Mixin:{construct:function(m){var n=this.getDescriptor(this);n.stateChangedHandler=m;n.proto.__getDescriptor=function(){return n};var l=function(r,o){var s=n.freezeFields,q,p=Object.create(n.proto,n.descriptor);if(r===void (0)){o=true}r=r||{};Object.defineProperty(p,"state",{configurable:true,enumerable:false,writable:true,value:r});r=k(r,p);if(o){if(!!r){for(var t in n.aliases){if(n.aliases.hasOwnProperty(t)&&t in r){r[n.aliases[t]]=r[t];delete r[t]}}}if("getInitialState" in p){r=k(r,p.getInitialState.call(p))}}Object.defineProperty(p,"state",{configurable:false,enumerable:false,writable:false,value:r});for(q=s.length-1;q>=0;q--){Object.freeze(p[s[q].fieldName])}return Object.freeze(p)};return l}}};h.exports=j},{"./utils":8}],6:[function(j,i,g){var f=j("./utils");var k=f.extend;var h=f.getDescriptor;var e={Mixin:{construct:function(m){var n=this.getDescriptor(this);n.proto.setState=m;var l=function(t,q){var s={},u=n.freezeFields,r,p=Object.create(n.proto,n.descriptor),v,o;Object.defineProperty(p,"state",{configurable:true,enumerable:false,writable:true,value:s});if(q[t]===void (0)){if("getInitialState" in p){s=k(s,p.getInitialState.call(p))}}else{s=("state" in q[t]?q[t].state:q[t])}Object.defineProperty(p,"state",{configurable:false,enumerable:false,writable:false,value:s});for(r=u.length-1;r>=0;r--){if(u[r].kind==="instance"){if(p[u[r].fieldName]){v=p[u[r].fieldName].__getDescriptor();o=Object.create(v.proto,v.descriptor);Object.defineProperty(o,"state",{configurable:false,enumerable:false,writable:false,value:p[u[r].fieldName].state});o.__proto__.setState=function(w,x){return v.stateChangedHandler.call(this,k(o.state,w),o.state,x)}.bind(p);Object.freeze(p[u[r].fieldName])}}else{Object.freeze(p[u[r].fieldName])}}return Object.freeze(p)};return l}}};i.exports=e},{"./utils":8}],7:[function(j,i,h){var f=j("./core");var e="__IMVVM__";var g={stateChangedHandler:function(k){this.setState({domainDataContext:k})},getInitialState:function(){var k=f.getInitialState(e,this.props.domainModel,this.stateChangedHandler,this.props.enableUndo);return{domainDataContext:k}}};i.exports=g},{"./core":2}],8:[function(h,g,f){var e={extend:function(){var j={};for(var l=0;l<arguments.length;l++){var m=arguments[l];for(var k in m){if(m.hasOwnProperty(k)){j[k]=m[k]}}}return j},mixInto:function(j,k){var i;for(i in k){if(!k.hasOwnProperty(i)){continue}j.prototype[i]=k[i]}}};g.exports=e},{}]},{},[1])(1)}); | ||
!function(b){if("object"==typeof exports){module.exports=b()}else{if("function"==typeof define&&define.amd){define(b)}else{var a;"undefined"!=typeof window?a=window:"undefined"!=typeof global?a=global:"undefined"!=typeof self&&(a=self),a.IMVVM=b()}}}(function(){var d,b,a;return(function c(f,k,h){function g(n,l){if(!k[n]){if(!f[n]){var i=typeof require=="function"&&require;if(!l&&i){return i(n,!0)}if(e){return e(n,!0)}throw new Error("Cannot find module '"+n+"'")}var m=k[n]={exports:{}};f[n][0].call(m.exports,function(o){var p=f[n][1][o];return g(p?p:o)},m,m.exports,c,f,k,h)}return k[n].exports}var e=typeof require=="function"&&require;for(var j=0;j<h.length;j++){g(h[j])}return g})({1:[function(h,g,f){var e=h("./src/imvvm.js");g.exports=e},{"./src/imvvm.js":3}],2:[function(h,g,f){var e=h("./utils");var i=e.extend;f.getInitialState=function(l,m,v,k){if(typeof v!=="function"){throw new TypeError()}k===void (0)?true:k;var A,u={},r={},B,j={},y={},t,q={},o={},x,w,z,s,p;var n=function(E,J,L,Q){var S={},O=void (0),G=void (0),M,H,F,D,I,K=[],P,N,C,R;if(typeof L==="function"){Q=L;L={}}J=J||{};M=Object.keys(J);if(Object.getPrototypeOf(J).constructor.classType==="DomainViewModel"){S=i(J);O=J.previousState;G=L;for(D in B){S[D]=new r[D](S)}for(D in B){if(B.hasOwnProperty(D)){for(I in j[D]){if(j[D].hasOwnProperty(I)){S[D].state[j[D][I]]=(I in B)?i(S[I].state):S[I]}}}}}else{if(!!M.length){if(E===l){S=i(J)}else{S[E]=i(J)}}q=i(S,q,L);transientStateKeys=Object.keys(q);if(transientStateKeys.length===0){return}if(typeof Q==="function"){Q();return}F=transientStateKeys.length-1;for(H=F;H>=0;H--){if(transientStateKeys[H] in B){S[transientStateKeys[H]]=i(u[transientStateKeys[H]],q[transientStateKeys[H]]);S[transientStateKeys[H]]=new r[transientStateKeys[H]](S)}else{S[transientStateKeys[H]]=q[transientStateKeys[H]]}}o=i(o,S);S=i(u,o);q={};for(H=F;H>=0;H--){if(transientStateKeys[H] in y){for(N in y[transientStateKeys[H]]){if(y[transientStateKeys[H]].hasOwnProperty(N)){if(M.indexOf(N)!==-1){C=y[transientStateKeys[H]][N];for(R in C){if(C.hasOwnProperty(R)){q=i(q,C[R].call(u[R],S[transientStateKeys[H]][N],u[transientStateKeys[H]][N],N,transientStateKeys[H]))}}}}}}}if(!!Object.keys(q).length){n(void (0),{},q);return}K=Object.keys(o);P=K.length-1;for(H=P;H>=0;H--){if(E===l){if(K[H] in j[l]){for(D in j[l][K[H]]){if(j[l][K[H]].hasOwnProperty(D)){S[D].state[j[l][K[H]][D]]=S[K[H]]}if(D in j){for(dataContext2 in j[D]){if(j[D].hasOwnProperty(dataContext2)){S[D].state[j[D][dataContext2]]=(dataContext2 in B)?i(S[dataContext2].state):S[dataContext2]}}}}}}else{if(K[H] in j){for(D in j[K[H]]){if(j[K[H]].hasOwnProperty(D)){S[K[H]].state[j[K[H]][D]]=(D in B)?i(S[D].state):S[D]}if(D in j){for(dataContext2 in j[D]){if(j[D].hasOwnProperty(dataContext2)){S[D].state[j[D][dataContext2]]=(dataContext2 in B)?i(S[dataContext2].state):S[dataContext2]}}}}}}}O=u}if(!!O){Object.freeze(O)}u=new A(S,O,G,k);Object.freeze(u);Object.freeze(u.state);v(u);q={};o={};return u};A=m.call(this,n.bind(this,l));u=new A(void (0),void (0),void (0),k,true);u.state=u.state||{};B=u.getDomainDataContext();for(t in B){if(B.hasOwnProperty(t)){r[t]=B[t].call(this,n.bind(this,t)).bind(this,t);u.state[t]=new r[t](u.state);if("getWatchedState" in u[t]){x=u[t].getWatchedState();for(w in x){if(x.hasOwnProperty(w)){if(w in B||w in u.state){if("alias" in x[w]){if(!(t in j)){j[t]={}}j[t][w]=x[w].alias;if(!(w in B)){if(!(l in j)){j[l]={}}if(!(t in j[l])){j[l][w]={}}j[l][w][t]=x[w].alias}}for(z in x[w].fields){if(x[w].fields.hasOwnProperty(z)){if(w in B){s={};if(!(w in y)){y[w]={}}s[z]={};s[z][t]=x[w].fields[z];y[w]=s}}}}}}}}}for(t in B){if(B.hasOwnProperty(t)){for(p in j[t]){if(j[t].hasOwnProperty(p)){u[t].state[j[t][p]]=(p in B)?i(u[p].state):u[p]}}}}u=new A(u,void (0),void (0),k);Object.freeze(u.state);Object.freeze(u);return u}},{"./utils":8}],3:[function(f,g,j){var k=f("./imvvmModel");var p=f("./imvvmViewModel");var i=f("./imvvmDomainViewModel");var r=f("./mixin");var q=f("./utils");var o=q.extend;var m=q.mixInto;var l=function(){};var h=function(){};var n=function(){};m(l,k.Mixin);m(h,p.Mixin);m(n,i.Mixin);var e={createClass:function(u,v,t){var y=function(){};y.prototype=new u();y.prototype.constructor=y;var x=y;var w=function(z){var A=new x();return A.construct.apply(w,arguments)};w.componentConstructor=y;y.ConvenienceConstructor=w;w.originalSpec=t;w.type=y;y.prototype.type=y;w.classType=v;y.prototype.classType=v;w.getDescriptor=function(){var E={},D=this.prototype,B={},z=[],A={},C;if("__processedObject__" in this.originalSpec){return this.originalSpec.__processedObject__}for(C in this.originalSpec){if(this.originalSpec.hasOwnProperty(C)){if("get" in this.originalSpec[C]||"set" in this.originalSpec[C]){this.originalSpec[C].enumerable=true;if("aliasFor" in this.originalSpec[C]){A[this.originalSpec[C].aliasFor]=C;delete this.originalSpec[C].aliasFor}if("viewModel" in this.originalSpec[C]){B[C]=this.originalSpec[C].viewModel;delete this.originalSpec[C].viewModel;delete this.originalSpec[C].set}else{if("kind" in this.originalSpec[C]){if(this.originalSpec[C].kind==="pseudo"){this.originalSpec[C].enumerable=false}else{z.push({fieldName:C,kind:this.originalSpec[C].kind})}delete this.originalSpec[C].kind}}E[C]=this.originalSpec[C]}else{D[C]=this.originalSpec[C]}}}if(!("extend" in D)){D.extend=q.extend}if(!!Object.keys(B).length){D.getDomainDataContext=function(){return B}}this.originalSpec.__processedObject__={descriptor:E,proto:D,originalSpec:this.originalSpec||{},freezeFields:z,aliases:A};return this.originalSpec.__processedObject__};return w}};var s={createModel:e.createClass.bind(this,l,"Model"),createViewModel:e.createClass.bind(this,h,"ViewModel"),createDomainViewModel:e.createClass.bind(this,n,"DomainViewModel"),mixin:r};g.exports=s},{"./imvvmDomainViewModel":4,"./imvvmModel":5,"./imvvmViewModel":6,"./mixin":7,"./utils":8}],4:[function(j,h,f){var e=j("./utils");var k=e.extend;var g=e.getDescriptor;var i={Mixin:{construct:function(m){var n=this.getDescriptor(this);n.proto.setState=m;n.proto.undo=function(){this.setState(this.previousState,!!this.previousState?this:void (0))};n.proto.redo=function(){if(this.canRedo){this.setState(this.nextState,this.nextState.nextState)}};var l=function(r,v,q,u,o){var t=n.freezeFields,s=Object.create(n.proto,n.descriptor),p;if(!!u){if(!!v){Object.defineProperty(s,"previousState",{configurable:false,enumerable:false,writable:false,value:v});Object.defineProperty(s,"canUndo",{configurable:false,enumerable:false,writable:false,value:true})}else{Object.defineProperty(s,"canUndo",{configurable:false,enumerable:false,writable:false,value:false})}if(!!q&&"state" in q){Object.defineProperty(s,"nextState",{configurable:false,enumerable:false,writable:false,value:q});Object.defineProperty(s,"canRedo",{configurable:false,enumerable:false,writable:false,value:true})}else{Object.defineProperty(s,"canRedo",{configurable:false,enumerable:false,writable:false,value:false})}}if(r===void (0)&&("getInitialState" in s)){r=s.getInitialState.call(s)}else{if("state" in r){delete r.state;Object.defineProperty(s,"state",{configurable:true,enumerable:false,writable:true,value:r});r=k(r,s)}}Object.defineProperty(s,"state",{configurable:false,enumerable:false,writable:false,value:r});for(p=t.length-1;p>=0;p--){Object.freeze(s[t[p].fieldName])}return s};return l}}};h.exports=i},{"./utils":8}],5:[function(i,h,f){var e=i("./utils");var k=e.extend;var g=e.getDescriptor;var j={Mixin:{construct:function(m){var n=this.getDescriptor(this);n.stateChangedHandler=m;n.proto.__getDescriptor=function(){return n};var l=function(r,o){var s=n.freezeFields,q,p=Object.create(n.proto,n.descriptor);if(r===void (0)){o=true}r=r||{};Object.defineProperty(p,"state",{configurable:true,enumerable:false,writable:true,value:r});r=k(r,p);if(o){if(!!r){for(var t in n.aliases){if(n.aliases.hasOwnProperty(t)&&t in r){r[n.aliases[t]]=r[t];delete r[t]}}}if("getInitialState" in p){r=k(r,p.getInitialState.call(p))}}Object.defineProperty(p,"state",{configurable:false,enumerable:false,writable:false,value:r});for(q=s.length-1;q>=0;q--){Object.freeze(p[s[q].fieldName])}return Object.freeze(p)};return l}}};h.exports=j},{"./utils":8}],6:[function(j,i,g){var f=j("./utils");var k=f.extend;var h=f.getDescriptor;var e={Mixin:{construct:function(m){var n=this.getDescriptor(this);n.proto.setState=m;var l=function(t,q){var s={},u=n.freezeFields,r,p=Object.create(n.proto,n.descriptor),v,o;Object.defineProperty(p,"state",{configurable:true,enumerable:false,writable:true,value:s});if(q[t]===void (0)){if("getInitialState" in p){s=k(s,p.getInitialState.call(p))}}else{s=("state" in q[t]?q[t].state:q[t])}Object.defineProperty(p,"state",{configurable:false,enumerable:false,writable:false,value:s});for(r=u.length-1;r>=0;r--){if(u[r].kind==="instance"){if(p[u[r].fieldName]){v=p[u[r].fieldName].__getDescriptor();o=Object.create(v.proto,v.descriptor);Object.defineProperty(o,"state",{configurable:false,enumerable:false,writable:false,value:p[u[r].fieldName].state});o.__proto__.setState=function(w,x){return v.stateChangedHandler.call(this,k(o.state,w),o.state,x)}.bind(p);Object.freeze(p[u[r].fieldName])}}else{Object.freeze(p[u[r].fieldName])}}return Object.freeze(p)};return l}}};i.exports=e},{"./utils":8}],7:[function(j,i,h){var f=j("./core");var e="__IMVVM__";var g={stateChangedHandler:function(k){this.setState({domainDataContext:k})},getInitialState:function(){var k=f.getInitialState(e,this.props.domainModel,this.stateChangedHandler,this.props.enableUndo);return{domainDataContext:k}}};i.exports=g},{"./core":2}],8:[function(h,g,f){var e={extend:function(){var j={};for(var l=0;l<arguments.length;l++){var m=arguments[l];for(var k in m){if(m.hasOwnProperty(k)){j[k]=m[k]}}}return j},mixInto:function(j,k){var i;for(i in k){if(!k.hasOwnProperty(i)){continue}j.prototype[i]=k[i]}}};g.exports=e},{}]},{},[1])(1)}); |
@@ -12,3 +12,3 @@ /** | ||
//noUndo is optional - default is false | ||
//enableUndo is optional - default is false | ||
React.renderComponent(<ApplicationView | ||
@@ -15,0 +15,0 @@ domainModel={DomainViewModel} |
@@ -33,6 +33,2 @@ /*jshint unused: vars */ | ||
undo: function(){ | ||
this.setState(this.previousState); | ||
}, | ||
personCount: { | ||
@@ -39,0 +35,0 @@ kind:'pseudo', |
@@ -20,2 +20,7 @@ /** | ||
}, | ||
redo: function(e){ | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
this.props.appContext.redo(); | ||
}, | ||
toggleOnlineState: function(e){ | ||
@@ -50,5 +55,8 @@ e.preventDefault(); | ||
<form className="navbar-form navbar-left" role="search"> | ||
<button onClick={this.undo} className="btn btn-default"> | ||
<button onClick={this.undo} disabled={!this.props.appContext.canUndo} className="btn btn-default"> | ||
Undo | ||
</button> | ||
<button onClick={this.redo} disabled={!this.props.appContext.canRedo} className="btn btn-default"> | ||
Redo | ||
</button> | ||
<button onClick={this.toggleOnlineState} className={onlineBtnClass}> | ||
@@ -55,0 +63,0 @@ {onlineBtnTxt} |
{ | ||
"name": "imvvm", | ||
"description": "Immutable MVVM for React", | ||
"version": "0.6.10", | ||
"version": "0.6.11", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "imvvm", |
@@ -142,5 +142,5 @@ IMVVM | ||
#####getInitialState() | ||
The `getInitialState` function initializes any fields that require a value on creation. Such values include, default values and calculated fields. This function has access to state that has been supplied during initializtion, and therefore `this` will be able to refer to the state. | ||
The `getInitialState` function initializes any fields that require a value during initialization. Such values include, default values and calculated fields. This function has access to the state which was passed into the constructor, and is able to reference this state via `this.state.property`. | ||
#####name | ||
`name` is a simple field descriptor. It defines a getter and setter. The getter returns state that resides in the state's property of the same name. The setter uses the passed in value to transition to the model to the next state, by passing the value, as an object to the setState function. This will then notify any ViewModels that have registered a stateChangeHandler with this model. | ||
`name` is a simple field descriptor. It defines a getter and setter. The getter returns state that resides in the state's property of the same name. The setter will transition the model to the next state, when a value is assigned to it. It uses the value and passes it, as an object, to the setState function. This will notify any ViewModels that have registered a stateChangedHandler with this model. | ||
#####age | ||
@@ -263,9 +263,9 @@ `age` is a calculated field. It is set by setting `dob`. `dob` uses the calculateAge function to set the value of age and passes both the dob and age values to setState. Please note that `age` needed to be initialized in the getInitialState() function. | ||
The `getInitialState` function initializes any fields that require a value and | ||
initialize models to establish the data for the Viewmodel. Unlike Models, the ViewModel does not have access to `state`. | ||
can initialize models to establish the data for the Viewmodel. Unlike Models, the ViewModel does not have access to `state`. | ||
#####getWatchedState() | ||
The `getWatchedState` function establises links between ViewModels. What is happening in this instance, is that we are watching the hobbies data context and refering to it, within this viewModel, with the alias of hobbiesContext. So we are then able to refer to is from teh state object as `this.state.hobbiesContext...`. Enabling us to display fields from other ViewModels and also update thier values. | ||
The `getWatchedState` function establises links between ViewModels. In the code above, `getWatchedState` is referencing the `hobbies` data context with the alias of hobbiesContext. This enables the ViewModel to refer to `hobbies` as `hobbiesContext` (i.e. `this.state.hobbiesContext...`). Enabling fields to be displayed from other ViewModels and will be automatically update thier values. | ||
We can also reference fields from the DomainViewModel. We simply specify the field name and supply an alias. Then it can be refered to within the state object. | ||
We can also reference fields from the DomainViewModel. We simply specify the field name and supply an alias. Then it can be referred to from the state object. | ||
#####imOnline | ||
The `imOnline` field is referencing the linked DomainModel field `online` with the alias of `imOnline`. It is simply forwarding the online value it recieves from the DomainViewModel to the View and has no influence over its output. It is for this reason that the field descriptor has a `kind` decorator of `pseudo`. Any field that obtains its value from elsewhere, should be flagged with the decorator `kind:'pseudo'`, unless it is an `instance` or `array`. | ||
The `imOnline` field is referencing the linked DomainModel field `online` with an alias of `imOnline`. It simply forwards the online value it recieves from the DomainViewModel to the View and has no influence over its output. It is for this reason that the field descriptor has a `kind` decorator of `pseudo`. Fields that obtain their value from other sources and have no influence on the output value, should be flagged with the decorator `kind:'pseudo'`, unless it is a calculated field, a `kind:'instance'` field or a `kind:'array'`. | ||
#####selectedPerson | ||
@@ -277,14 +277,14 @@ `selectedPerson` is another field that has a `kind` decorator. The `selectedPerson` field is of kind `instance`. Which simply means that it will return a model instance. | ||
_The reason that the kindd decorator is used is because IMVVM does some extra processing with these types._ | ||
_The reason that the kind decorator is used is because IMVVM does some extra processing with these types._ | ||
#####personStateChangedHandler | ||
`personStateChangedHandler` will be invoked anytime `setState` is called within the model that it is registered with. This function processes the change in the ViewModel and notifies the DomainModel so that the DomainModel can transition to the next state. | ||
`personStateChangedHandler` will be invoked anytime `setState` is called within the model that it is registered to. This function processes changes in the ViewModel and notifies the DomainModel of any changes so that the DomainModel can transition to the next state. | ||
#####Person | ||
`Person` is a wrapper around the `PersonModel` constructor. It makes `PersonModel` easier to invoke and acts like a factory of sorts. The parameters passed to `Person` are passed directly to the `PersonModel` constructor, but not before registering the stateChangedHandler `personStateChangedHandler`, to ensure that all state changes in PersonModel and handled approapriately. | ||
`Person` is a wrapper around the `PersonModel` constructor. It makes `PersonModel` easier to invoke and acts like a Model Factory of sorts. The parameters passed to `Person` are passed directly to the `PersonModel` constructor, but not before registering the stateChangedHandler `personStateChangedHandler`, to ensure that all state changes in PersonModel notify interested Models/ViewModels and is handled approapriately. | ||
#####selectPerson, addPerson & deletePerson | ||
These functions are exposed to the View and enaable tasks to be performed in the ViewModel. However, most interactions will occur via the `selectedPerson` which exposes the model instance to the View. | ||
These functions are exposed to the View and enable tasks to be performed in the ViewModel. However, the View will also interact with any Models the ViewModel exposes to it. In this instance the ViewModel exposes the PersonModel via the `selectedPerson` property. See [A word on how to update a Model from the View](#a-word-on-how-to-update-a-model-from-the-view) | ||
I've added a snippet of HobbiesViewModel, from the example application to explain a little more about `getWatchedState`. | ||
I've added a code snippet of HobbiesViewModel, from the example application to help explain a little more about `getWatchedState`. | ||
@@ -343,13 +343,15 @@ __HobbiesViewModel snippet__ | ||
#####getWatchedState() | ||
Notice in this instance of the `getWatchedState` function the `persons` object has an extra property called fields. This specifies that we are not only linking to the `persons` data context, but we would also like to be notified when `persons.selectedPerson` changes, and if it does change trigger the `onPersonChanged` handler. | ||
Notice in this instance of the `getWatchedState` function, the `persons` object has an extra property called `fields`. `fields` the ViewModel should be notified when `persons.selectedPerson` changes, and if it does change trigger the `onPersonChanged` handler. | ||
Both the `alias` and `fields` properties are optional. | ||
#####onPersonChangedHandler | ||
`onPersonChangedHandler` will be triggered whenever any of the fields that it is assigned to changes. It is important to note that, if there is a change a state object is returned. If there is no change, return either void(0) or don't return anything. It should also be noted that the returned state object has a property with the data context, `hobbies`, and the associated object next state. This is necessary so that any data context or domain property can be updated from this ViewModel by simply specfying it in the returned object. | ||
`onPersonChangedHandler` will be triggered whenever any of the fields that it is assigned to changes. It is important to note that if there is a change, `onPersonChangedHandler` must return a state object. If no change has occurred, return either void(0) or don't return anything. It should also be noted that the returned state object has a property with the data context, `hobbies`, and the associated next state object. This is necessary so that any data context or domain property can be updated from this ViewModel by specfying it in the returned object. | ||
#####selectHobby | ||
The `selectHobby` function is nothing special. What is different about it is the 'setState' function. ViewModels get an extra parameter, which enables the ViewModel to update state in other data contexts. The second parameter takes a state object, not dissimilar to the state object that is returned from `onPersonChangedHandler`. The second parameter accepts an object that specifies the data context\domain property and associated state. | ||
The `selectHobby` function is nothing special. What is different about it, is the `setState` function. A ViewModel's `setState` function has an extra parameter which enables the ViewModel to update state in other data contexts. The second parameter takes a state object, not dissimilar to the state object that is returned from `onPersonChangedHandler`. The second parameter accepts an object that specifies the data context or domain property and its associated state. | ||
For instance `this.setState({current: this.Hobby(this.hobbies[i])}, {busy: true});`. The first parameter is the next state for `hobbies` data context, the second parameter specifies that `busy`, in the domain data context should be changed to `true`. This second parameter also accepts, for example, `{persons: {selectedPerson: this.Person(personState)}}`. | ||
For instance `this.setState({current: this.Hobby(this.hobbies[i])}, {busy: true});`. The first parameter is the next state for the `hobbies` data context, the second parameter specifies that `busy`, a property in the domain data context, should be changed to `true`. This second parameter also accepts other data contexts (e.g. `{persons: {selectedPerson: this.Person(personState)}}`). | ||
Also noted in the comments is that this can be achieved with a callback, ensuring to pass `void(0)` as the first parameter to `setState`. | ||
Also noted within comments, is that this can be achieved within a callback, ensuring to pass `void(0)` as the first parameter to `setState`. | ||
@@ -429,2 +431,3 @@ ***n.b. You may have noticed that not all fields have setters, however, the values are still able to be updated. This is what `setState` does. You only need to supply a setter if you would like the View to update the field directly.*** | ||
} | ||
}); | ||
@@ -457,3 +460,3 @@ ``` | ||
***A word on how to use the exposed Model -> selectedPerson*** | ||
#####A word on how to update a Model from the View | ||
@@ -534,3 +537,3 @@ As mentioned above, the `PersonsViewModel` has a `persons` data context. This data context exposes a `Person` model instance via the `selectedPerson` property. | ||
##Running the example application | ||
The example application is a good starting place when figuring out how things work. So to get it running, navigate to the `./example` directory and run the following commands. | ||
The example application is a good starting place when figuring out how things work. To get it running, navigate to the `./example` directory and run the following commands. | ||
@@ -617,3 +620,13 @@ ``` | ||
_Available in:_ DomainViewModel, ViewModel, Model | ||
___ | ||
#####object undo() | ||
`undo` transitions state to the previous state. Requires [`enableUndo`](#enableundo-boolean-default--false) to be `true` to enable this functionality. | ||
_Available in:_ DomainViewModel | ||
___ | ||
#####object redo() | ||
`redo` transitions state to the next state. Requires [`enableUndo`](#enableundo-boolean-default--false) to be `true` to enable this functionality. | ||
_Available in:_ DomainViewModel | ||
####Properties | ||
@@ -631,2 +644,21 @@ ___ | ||
___ | ||
#####nextState | ||
Holds Domain Data Context next state. | ||
_Available in:_ DomainViewModel | ||
___ | ||
#####canUndo | ||
`true` - can transition to previous state. | ||
`false` - can not transition to previous state. | ||
_Available in:_ DomainViewModel | ||
___ | ||
#####canRedo | ||
`true` - can revert back to next state. | ||
`false` - can not revert back to next state. | ||
_Available in:_ DomainViewModel | ||
###Specification | ||
@@ -821,4 +853,5 @@ ####Functions | ||
__example__ | ||
In original data source, key was referenced a `job`, but model will expose it a `occupation`. This is a one way transformation. If it is required to persist the data as `job`, that will need to be done within the application. | ||
In the original data source, `job` was is property name. However, `aliasFor` will expose `job` as `occupation` to the View. This is a one way transformation. If it is required to persist the data as `job`, that will need to be transformed back within the application. | ||
```javascript | ||
@@ -825,0 +858,0 @@ occupation: { |
@@ -31,3 +31,4 @@ | ||
var nextState = {}, | ||
prevState = {}, | ||
prevState = void(0), | ||
redoState = void(0), | ||
newStateKeys, | ||
@@ -56,6 +57,6 @@ keyIdx, | ||
if(Object.getPrototypeOf(newState).constructor.classType === "DomainViewModel") { | ||
nextState = extend(newState); | ||
prevState = newState.previousState; | ||
redoState = newAppState; | ||
//Need to reset ViewModel with instance object so that setState is associated with | ||
@@ -195,3 +196,3 @@ //the current ViewModel. This reason this ccurs is that when a ViewModel is created it | ||
appState = new ApplicationDataContext(nextState, prevState, enableUndo); | ||
appState = new ApplicationDataContext(nextState, prevState, redoState, enableUndo); | ||
Object.freeze(appState); | ||
@@ -212,3 +213,3 @@ Object.freeze(appState.state); | ||
/*Need to look at DomainViewModel state and nextState and Domain Model and updating*/ | ||
appState = new ApplicationDataContext(void(0), void(0), enableUndo, true); | ||
appState = new ApplicationDataContext(void(0), void(0), void(0), enableUndo, true); | ||
appState.state = appState.state || {}; | ||
@@ -275,3 +276,3 @@ | ||
appState = new ApplicationDataContext(appState, void(0), enableUndo); | ||
appState = new ApplicationDataContext(appState, void(0), void(0), enableUndo); | ||
Object.freeze(appState.state); | ||
@@ -278,0 +279,0 @@ Object.freeze(appState); |
@@ -13,3 +13,13 @@ | ||
var dataContext = function(nextState, prevState, enableUndo, initialize) { | ||
desc.proto.undo = function(){ | ||
this.setState(this.previousState, !!this.previousState ? this : void(0)); | ||
}; | ||
desc.proto.redo = function(){ | ||
if(this.canRedo){ | ||
this.setState(this.nextState, this.nextState.nextState); | ||
} | ||
}; | ||
var dataContext = function(nextState, prevState, redoState, enableUndo, initialize) { | ||
@@ -20,9 +30,45 @@ var freezeFields = desc.freezeFields, | ||
if(!!enableUndo && !!prevState){ | ||
Object.defineProperty(domainModel, 'previousState', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: prevState | ||
}); | ||
if(!!enableUndo){ | ||
if(!!prevState){ | ||
Object.defineProperty(domainModel, 'previousState', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: prevState | ||
}); | ||
Object.defineProperty(domainModel, 'canUndo', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: true | ||
}); | ||
} else { | ||
Object.defineProperty(domainModel, 'canUndo', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: false | ||
}); | ||
} | ||
if(!!redoState && 'state' in redoState){ | ||
Object.defineProperty(domainModel, 'nextState', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: redoState | ||
}); | ||
Object.defineProperty(domainModel, 'canRedo', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: true | ||
}); | ||
} else { | ||
Object.defineProperty(domainModel, 'canRedo', { | ||
configurable: false, | ||
enumerable: false, | ||
writable: false, | ||
value: false | ||
}); | ||
} | ||
} | ||
@@ -29,0 +75,0 @@ |
165867
2490
913