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

imvvm

Package Overview
Dependencies
Maintainers
1
Versions
52
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

imvvm - npm Package Compare versions

Comparing version 0.6.16 to 0.6.19

3

bower.json
{
"name": "imvvm",
"version": "0.6.16",
"version": "0.6.19",
"homepage": "https://github.com/entrendipity/imvvm",

@@ -20,3 +20,2 @@ "authors": [

"immutable",
"node",
"presentation model",

@@ -23,0 +22,0 @@ "imvvm"

@@ -1,4 +0,12 @@

## 0.0.1a
## 0.6.17
- alpha
- `this.extend` dreprecated. Replaced with `IMVVM.extend`. Will not be available in version `0.7.0+`
- The following functions are no longer exposed to the View
+ getDomainDataContext
+ getInitialState
+ getWatchedState
+ \_\_getDescriptor - this has been entirely removed
- Started promoting the use of the module pattern in order to hide implementation specific descriptor definitions/functions from the View. This is reflected in the reference implementation.
- Updated reference implementation.

@@ -74,3 +74,3 @@ !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){

for(dataContext in domain){
nextState[dataContext] = new dataContexts[dataContext](nextState);
nextState[dataContext] = new dataContexts[dataContext](nextState[dataContext]);
}

@@ -91,3 +91,10 @@

if(typeof callback === 'function'){
appState = new ApplicationDataContext(nextState, prevState, redoState, enableUndo);
callback();
return;
}
} else {
if(!!newStateKeys.length){

@@ -116,3 +123,3 @@ if(caller === appNamespace){

nextState[transientStateKeys[keyIdx]] = extend(appState[transientStateKeys[keyIdx]], transientState[transientStateKeys[keyIdx]]);
nextState[transientStateKeys[keyIdx]] = new dataContexts[transientStateKeys[keyIdx]](nextState);
nextState[transientStateKeys[keyIdx]] = new dataContexts[transientStateKeys[keyIdx]](nextState[transientStateKeys[keyIdx]]);
} else {

@@ -203,3 +210,2 @@ nextState[transientStateKeys[keyIdx]] = transientState[transientStateKeys[keyIdx]];

}

@@ -214,5 +220,3 @@ appState = new ApplicationDataContext(nextState, prevState, redoState, enableUndo);

processedState = {};
//Provided for the main app to return to the View
return appState;
};

@@ -222,3 +226,2 @@

ApplicationDataContext = domainModel.call(this, appStateChangedHandler.bind(this, appNamespace));
/*Need to look at DomainViewModel state and nextState and Domain Model and updating*/
appState = new ApplicationDataContext(void(0), void(0), void(0), enableUndo, true);

@@ -228,10 +231,12 @@ appState.state = appState.state || {};

domain = appState.getDomainDataContext();
delete appState.__proto__.getDomainDataContext;
for(dataContext in domain){
if(domain.hasOwnProperty(dataContext)){
dataContexts[dataContext] = domain[dataContext].call(this, appStateChangedHandler.bind(this, dataContext)).bind(this, dataContext);
appState.state[dataContext] = new dataContexts[dataContext](appState.state);
dataContexts[dataContext] = domain[dataContext].call(this, appStateChangedHandler.bind(this, dataContext));
appState.state[dataContext] = new dataContexts[dataContext](appState.state[dataContext]);
if('getWatchedState' in appState[dataContext]){
watchedState = appState[dataContext].getWatchedState();
delete appState[dataContext].__proto__.getWatchedState;
for(watchedItem in watchedState){

@@ -290,2 +295,4 @@ if(watchedState.hasOwnProperty(watchedItem)){

Object.freeze(appState);
console.warn('\"this.extend\" has been deprecated and will not be available in 0.7. Please use \"IMVVM.extend\".');
return appState;

@@ -350,4 +357,4 @@ };

if('__processedObject__' in this.originalSpec){
return this.originalSpec.__processedObject__;
if('__processedSpec__' in this.originalSpec){
return this.originalSpec.__processedSpec__;
}

@@ -360,7 +367,2 @@

this.originalSpec[key].enumerable = true;
if('aliasFor' in this.originalSpec[key]){
aliases[this.originalSpec[key].aliasFor] = key;
delete this.originalSpec[key].aliasFor;
}
if('viewModel' in this.originalSpec[key]) {

@@ -370,9 +372,16 @@ viewModels[key] = this.originalSpec[key].viewModel;

delete this.originalSpec[key].set;
} else if('kind' in this.originalSpec[key]){
if(this.originalSpec[key].kind === 'pseudo'){
this.originalSpec[key].enumerable = false;
} else { //'instance' || 'array'
autoFreeze.push({fieldName: key, kind: this.originalSpec[key].kind});
} else {
if('aliasFor' in this.originalSpec[key]){
aliases[this.originalSpec[key].aliasFor] = key;
delete this.originalSpec[key].aliasFor;
}
delete this.originalSpec[key].kind;
if('kind' in this.originalSpec[key]){
if(this.originalSpec[key].kind === 'pseudo'){
this.originalSpec[key].enumerable = false;
} else { //'instance' || 'array'
autoFreeze.push({fieldName: key, kind: this.originalSpec[key].kind});
}
delete this.originalSpec[key].kind;
}
}

@@ -387,3 +396,3 @@ descriptor[key] = this.originalSpec[key];

if(!('extend' in proto)){
proto.extend = utils.extend;
proto.extend = utils.extend;
}

@@ -397,3 +406,3 @@

this.originalSpec.__processedObject__ = {
this.originalSpec.__processedSpec__ = {
descriptor: descriptor,

@@ -406,3 +415,3 @@ proto: proto,

return this.originalSpec.__processedObject__;
return this.originalSpec.__processedSpec__;
};

@@ -418,3 +427,4 @@

createDomainViewModel: IMVVMClass.createClass.bind(this, DomainViewModelBase, 'DomainViewModel'),
mixin: mixin
mixin: mixin,
extend: extend
};

@@ -500,3 +510,4 @@

//Add state prop so that it can be referenced from within getInitialState
nextState = ('getInitialState' in domainModel) ? domainModel.getInitialState.call(domainModel) : {};
nextState = ('getInitialState' in domainModel) ? domainModel.getInitialState.call(domainModel) : {};
delete domainModel.__proto__.getInitialState;
} else if('state' in nextState){

@@ -554,4 +565,5 @@ delete nextState.state;

desc.stateChangedHandler = stateChangedHandler;
desc.proto.__getDescriptor = function(){
return desc;
if('getInitialState' in desc.originalSpec){
desc.proto.getInitialState = desc.originalSpec.getInitialState;
}

@@ -593,3 +605,4 @@

if('getInitialState' in model){
nextState = extend(nextState, model.getInitialState.call(model));
nextState = extend(nextState, model.getInitialState.call(model));
delete model.__proto__.getInitialState;
}

@@ -637,3 +650,3 @@ }

var dataContext = function(VMName, nextAppState) {
var dataContext = function(nextVMState) {

@@ -655,9 +668,8 @@ //nextState has already been extended with prevState in core

if(!!nextAppState){
if(nextAppState[VMName] === void(0)){
nextState = ('getInitialState' in viewModel) ?
extend(nextState, viewModel.getInitialState.call(viewModel)) : nextState;
} else {
nextState = ('state' in nextAppState[VMName] ? nextAppState[VMName].state : nextAppState[VMName]);
}
if(nextVMState === void(0)){
nextState = ('getInitialState' in viewModel) ?
extend(nextState, viewModel.getInitialState.call(viewModel)) : nextState;
delete viewModel.__proto__.getInitialState;
} else {
nextState = ('state' in nextVMState ? nextVMState.state : nextVMState);
}

@@ -676,5 +688,6 @@

if(viewModel[freezeFields[fld].fieldName]){
tempDesc = viewModel[freezeFields[fld].fieldName].__getDescriptor();
tempDesc = viewModel[freezeFields[fld].fieldName].constructor.originalSpec.__processedSpec__;
tempModel = Object.create(tempDesc.proto, tempDesc.descriptor);
delete tempModel.__proto__.getInitialState;
Object.defineProperty(tempModel, 'state', {

@@ -681,0 +694,0 @@ configurable: true,

@@ -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("stateChangedHandler must be a function!")}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)){r=("getInitialState" in s)?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)}}for(p=t.length-1;p>=0;p--){if(t[p].kind==="array"){r[t[p].fieldName]=r[t[p].fieldName]||[];Object.freeze(r[t[p].fieldName])}else{throw new TypeError('kind:"instance" can only be specified in a ViewModel.')}}Object.defineProperty(s,"state",{configurable:false,enumerable:false,writable:false,value:r});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(s,q,o){var t=n.freezeFields,r,p=Object.create(n.proto,n.descriptor);if(s===void (0)){o=true}else{if(typeof s==="boolean"){o=s;s=void (0)}else{if(typeof q==="boolean"){o=q;q=void (0)}}}s=k(s,q);Object.defineProperty(p,"state",{configurable:true,enumerable:false,writable:true,value:s});s=k(s,p);if(o){for(var u in n.aliases){if(n.aliases.hasOwnProperty(u)&&u in s){s[n.aliases[u]]=s[u];delete s[u]}}if("getInitialState" in p){s=k(s,p.getInitialState.call(p))}}for(r=t.length-1;r>=0;r--){if(t[r].kind==="array"){s[t[r].fieldName]=s[t[r].fieldName]||[];Object.freeze(s[t[r].fieldName])}else{throw new TypeError('kind:"instance" can only be specified in a ViewModel.')}}Object.defineProperty(p,"state",{configurable:false,enumerable:false,writable:false,value:s});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){if(q[t]===void (0)){s=("getInitialState" in p)?k(s,p.getInitialState.call(p)):s}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:true,enumerable:false,writable:true,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{s[u[r].fieldName]=s[u[r].fieldName]||[];Object.freeze(s[u[r].fieldName])}}Object.defineProperty(p,"state",{configurable:false,enumerable:false,writable:false,value:s});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("stateChangedHandler must be a function!")}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[D])}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]}}}}if(typeof Q==="function"){u=new A(S,O,G,k);Q();return}}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[transientStateKeys[H]])}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={}};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();delete u.__proto__.getDomainDataContext;for(t in B){if(B.hasOwnProperty(t)){r[t]=B[t].call(this,n.bind(this,t));u.state[t]=new r[t](u.state[t]);if("getWatchedState" in u[t]){x=u[t].getWatchedState();delete u[t].__proto__.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);console.warn('"this.extend" has been deprecated and will not be available in 0.7. Please use "IMVVM.extend".');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("__processedSpec__" in this.originalSpec){return this.originalSpec.__processedSpec__}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("viewModel" in this.originalSpec[C]){B[C]=this.originalSpec[C].viewModel;delete this.originalSpec[C].viewModel;delete this.originalSpec[C].set}else{if("aliasFor" in this.originalSpec[C]){A[this.originalSpec[C].aliasFor]=C;delete this.originalSpec[C].aliasFor}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.__processedSpec__={descriptor:E,proto:D,originalSpec:this.originalSpec||{},freezeFields:z,aliases:A};return this.originalSpec.__processedSpec__};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,extend:o};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)){r=("getInitialState" in s)?s.getInitialState.call(s):{};delete s.__proto__.getInitialState}else{if("state" in r){delete r.state;Object.defineProperty(s,"state",{configurable:true,enumerable:false,writable:true,value:r});r=k(r,s)}}for(p=t.length-1;p>=0;p--){if(t[p].kind==="array"){r[t[p].fieldName]=r[t[p].fieldName]||[];Object.freeze(r[t[p].fieldName])}else{throw new TypeError('kind:"instance" can only be specified in a ViewModel.')}}Object.defineProperty(s,"state",{configurable:false,enumerable:false,writable:false,value:r});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;if("getInitialState" in n.originalSpec){n.proto.getInitialState=n.originalSpec.getInitialState}var l=function(s,q,o){var t=n.freezeFields,r,p=Object.create(n.proto,n.descriptor);if(s===void (0)){o=true}else{if(typeof s==="boolean"){o=s;s=void (0)}else{if(typeof q==="boolean"){o=q;q=void (0)}}}s=k(s,q);Object.defineProperty(p,"state",{configurable:true,enumerable:false,writable:true,value:s});s=k(s,p);if(o){for(var u in n.aliases){if(n.aliases.hasOwnProperty(u)&&u in s){s[n.aliases[u]]=s[u];delete s[u]}}if("getInitialState" in p){s=k(s,p.getInitialState.call(p));delete p.__proto__.getInitialState}}for(r=t.length-1;r>=0;r--){if(t[r].kind==="array"){s[t[r].fieldName]=s[t[r].fieldName]||[];Object.freeze(s[t[r].fieldName])}else{throw new TypeError('kind:"instance" can only be specified in a ViewModel.')}}Object.defineProperty(p,"state",{configurable:false,enumerable:false,writable:false,value:s});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){var r={},s=n.freezeFields,q,p=Object.create(n.proto,n.descriptor),u,o;Object.defineProperty(p,"state",{configurable:true,enumerable:false,writable:true,value:r});if(t===void (0)){r=("getInitialState" in p)?k(r,p.getInitialState.call(p)):r;delete p.__proto__.getInitialState}else{r=("state" in t?t.state:t)}Object.defineProperty(p,"state",{configurable:false,enumerable:false,writable:false,value:r});for(q=s.length-1;q>=0;q--){if(s[q].kind==="instance"){if(p[s[q].fieldName]){u=p[s[q].fieldName].constructor.originalSpec.__processedSpec__;o=Object.create(u.proto,u.descriptor);delete o.__proto__.getInitialState;Object.defineProperty(o,"state",{configurable:true,enumerable:false,writable:true,value:p[s[q].fieldName].state});o.__proto__.setState=function(v,w){return u.stateChangedHandler.call(this,k(o.state,v),o.state,w)}.bind(p);Object.freeze(p[s[q].fieldName])}}else{r[s[q].fieldName]=r[s[q].fieldName]||[];Object.freeze(r[s[q].fieldName])}}Object.defineProperty(p,"state",{configurable:false,enumerable:false,writable:false,value:r});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)});

@@ -15,2 +15,3 @@ /*jshint unused: false */

name: {
aliasFor: 'hobby',
get: function(){

@@ -17,0 +18,0 @@ return this.state.name;

@@ -6,161 +6,165 @@ /*jshint unused: false */

var PersonModel = IMVVM.createModel({
var PersonModel = (function(){
getInitialState: function(){
var Hobby = function(){
return new HobbyModel().apply(this, arguments);
};
var uuid = function () {
/*jshint bitwise:false */
var i, random;
var uuid = '';
var id, hobbies = [];
id = this.id || this.uuid();
hobbies = DataService.getHobbiesData(this.id).map(function(hobby){
return this.Hobby(hobby, true);
}.bind(this));
for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0;
if (i === 8 || i === 12 || i === 16 || i === 20) {
uuid += '-';
}
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
.toString(16);
}
return uuid;
};
return {
age: this.calculateAge(this.dob),
id: id,
hobbies: hobbies
};
},
var calculateAge = function(dob){ // dob is a date
var DOB = new Date(dob);
var ageDate = new Date(Date.now() - DOB.getTime()); // miliseconds from
var age = Math.abs(ageDate.getFullYear() - 1970);
return isNaN(age) ? 'Enter your Birthday' : age + ' years old';
};
Hobby: function(){
return new HobbyModel().apply(this, arguments);
},
var personModel = IMVVM.createModel({
getInitialState: function(){
id: {
get: function(){
return this.state.id;
}
},
var id, hobbies = [];
id = this.id || uuid();
hobbies = DataService.getHobbiesData(this.id).map(function(hobby){
return new Hobby(hobby, true);
}.bind(this));
firstName: {
get: function(){ return this.state.firstName; },
set: function(newValue){
var nextState = {};
nextState.firstName = newValue.length === 0 ? void(0) : newValue;
this.setState(nextState);
}
},
return {
age: calculateAge(this.dob),
id: id,
hobbies: hobbies
};
},
lastName: {
get: function(){ return this.state.lastName; },
set: function(newValue){
var nextState = {};
nextState.lastName = newValue.length === 0 ? void(0) : newValue;
this.setState(nextState);
}
},
fullName: {
kind: 'pseudo',
get: function(){
if(this.lastName === void(0)){
return this.firstName;
id: {
get: function(){
return this.state.id;
}
return this.firstName + ' ' + this.lastName;
},
set: function(newValue){
var nextState = {};
var nameArr = newValue.split(' ');
var isSpace = newValue.slice(-1)[0] === ' ';
var firstname = nameArr[0];
var lastname = nameArr.slice(1).join(' ');
nextState.firstName = firstname.length === 0 ? void(0) : firstname;
nextState.lastName = lastname.length === 0 && !isSpace ? void(0) : lastname;
this.setState(nextState);
}
},
firstName: {
get: function(){ return this.state.firstName; },
set: function(newValue){
var nextState = {};
nextState.firstName = newValue.length === 0 ? void(0) : newValue;
this.setState(nextState);
}
},
occupation: {
aliasFor: 'job',
get: function(){
return this.state.occupation;
lastName: {
get: function(){ return this.state.lastName; },
set: function(newValue){
var nextState = {};
nextState.lastName = newValue.length === 0 ? void(0) : newValue;
this.setState(nextState);
}
},
set: function(newValue){
this.setState({'occupation': newValue });
}
},
dob: {
get: function(){
return this.state.dob;
fullName: {
kind: 'pseudo',
get: function(){
if(this.lastName === void(0)){
return this.firstName;
}
return this.firstName + ' ' + this.lastName;
},
set: function(newValue){
var nextState = {};
var nameArr = newValue.split(' ');
var isSpace = newValue.slice(-1)[0] === ' ';
var firstname = nameArr[0];
var lastname = nameArr.slice(1).join(' ');
nextState.firstName = firstname.length === 0 ? void(0) : firstname;
nextState.lastName = lastname.length === 0 && !isSpace ? void(0) : lastname;
this.setState(nextState);
}
},
set: function(newValue){
var nextState = {};
if(newValue.length === 10){
nextState.age = this.calculateAge(newValue);
occupation: {
aliasFor: 'job',
get: function(){
return this.state.occupation;
},
set: function(newValue){
this.setState({'occupation': newValue });
}
if(newValue.length === 0){
nextState.age = 'C\'mon. When\'s your Birthday?';
},
dob: {
get: function(){
return this.state.dob;
},
set: function(newValue){
var nextState = {};
if(newValue.length === 10){
nextState.age = calculateAge(newValue);
}
if(newValue.length === 0){
nextState.age = 'C\'mon. When\'s your Birthday?';
}
nextState.dob = newValue;
this.setState(nextState);
}
nextState.dob = newValue;
this.setState(nextState);
}
},
//Calculated field <- dob
age: {
get: function(){
return this.state.age;
}
},
calculateAge: function(dob){ // dob is a date
var DOB = new Date(dob);
var ageDate = new Date(Date.now() - DOB.getTime()); // miliseconds from
var age = Math.abs(ageDate.getFullYear() - 1970);
return isNaN(age) ? 'Enter your Birthday' : age + ' years old';
},
},
//Calculated field <- dob
age: {
get: function(){
return this.state.age;
}
},
gender: {
get: function(){ return this.state.gender; },
set: function(newValue){
this.setState({'gender': newValue});
}
},
gender: {
get: function(){ return this.state.gender; },
set: function(newValue){
this.setState({'gender': newValue});
}
},
hobbies: {
kind: 'array',
get: function(){ return this.state.hobbies; },
set: function(newArray){
this.setState({'hobbies': newArray});
}
},
addHobby: function(value){
var arr;
for (var i = this.hobbies.length - 1; i >= 0; i--) {
if(this.hobbies[i].name === value.name){
return;
hobbies: {
kind: 'array',
get: function(){ return this.state.hobbies; },
set: function(newArray){
this.setState({'hobbies': newArray});
}
}
arr = this.hobbies.slice(0);
this.hobbies = arr.concat(value);
},
deleteHobby: function(value){
this.hobbies = this.hobbies.filter(function(hobby){
return hobby.id !== value;
});
},
},
uuid: function () {
/*jshint bitwise:false */
var i, random;
var uuid = '';
for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0;
if (i === 8 || i === 12 || i === 16 || i === 20) {
uuid += '-';
addHobby: function(value){
var arr;
for (var i = this.hobbies.length - 1; i >= 0; i--) {
if(this.hobbies[i].name === value.name){
return;
}
}
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
.toString(16);
}
return uuid;
},
arr = this.hobbies.slice(0);
this.hobbies = arr.concat(value);
},
deleteHobby: function(value){
this.hobbies = this.hobbies.filter(function(hobby){
return hobby.id !== value;
});
},
});
});
return personModel;
}());

@@ -6,53 +6,22 @@ /*jshint unused: false */

var HobbiesViewModel = IMVVM.createViewModel({
var HobbiesViewModel = (function(){
getWatchedState: function() {
return {
'persons': {
alias: 'personsContext', //optional - if provided then will be added to prototype
fields: { //optional
'selectedPerson': this.onPersonChangedHandler
}
},
'busy': {
alias: 'busy'
var uuid = function () {
/*jshint bitwise:false */
var i, random;
var uuid = '';
for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0;
if (i === 8 || i === 12 || i === 16 || i === 20) {
uuid += '-';
}
};
},
//Use when this needs change state triggered by others action
onPersonChangedHandler: function(nextState, prevState, field, context){
if(this.current !== void(0) && context === 'persons' &&
nextState.id !== prevState.id){
return { hobbies: { current: void(0) }, busy: false };
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
.toString(16);
}
},
return uuid;
};
hobbies: {
kind: 'pseudo',
get: function(){
return this.state.personsContext.selectedPerson.hobbies;
}
},
var hobbyStateChangedHandler = function(nextState, prevState/*, callback*/){
busyText: {
kind: 'pseudo', //kind: 'pseudo' because its not calculated but is supplied externally
get: function(){
return this.state.busy ? 'Im Busy! Go away...' : 'Not doing too much.';
}
},
current: {
kind: 'instance',
get: function(){
return this.state.current;
}
},
Hobby: function(hobbyState, init){
return new HobbyModel(this.hobbyStateChangedHandler)(hobbyState, init);
},
hobbyStateChangedHandler: function(nextState, prevState/*, callback*/){
var newState = {};

@@ -62,3 +31,3 @@ var hobbiesArr = this.hobbies.map(function(hobby){

newState.current = this.Hobby(nextState);
newState.current = new Hobby(nextState);
return newState.current;

@@ -73,69 +42,104 @@ }

},
};
selectHobby: function(id){
for (var i = this.hobbies.length - 1; i >= 0; i--) {
if ((this.current === void(0) || this.current.id !== id) && this.hobbies[i].id === id){
this.setState({current: this.Hobby(this.hobbies[i])}, {busy: true});
/*
//OR use a callback
this.setState({current: this.Hobby(this.hobbies[i])}, function(){
this.setState(void(0), {busy: true});
}.bind(this));
*/
//Use when this needs change state triggered by others action
var onPersonChangedHandler = function(nextState, prevState, field, context){
if(this.current !== void(0) && context === 'persons' &&
nextState.id !== prevState.id){
return { hobbies: { current: void(0) }, busy: false };
}
};
break;
var Hobby = function(){
return new HobbyModel(hobbyStateChangedHandler).apply(this, arguments);
};
var hobbiesViewModel = IMVVM.createViewModel({
getWatchedState: function() {
return {
'persons': {
alias: 'personsContext', //optional - if provided then will be added to prototype
fields: { //optional
'selectedPerson': onPersonChangedHandler
}
},
'busy': {
alias: 'busy'
}
};
},
hobbies: {
kind: 'pseudo',
get: function(){
return this.state.personsContext.selectedPerson.hobbies;
}
}
},
addHobby: function(value){
if(value !== ''){
this.state.personsContext.selectedPerson.
addHobby(this.Hobby({ id:this.uuid(), name:value }, true));
}
},
deleteHobby: function(value){
/*
},
If we were to simply call
busyText: {
kind: 'pseudo', //kind: 'pseudo' because its not calculated but is supplied externally
get: function(){
return this.state.busy ? 'Im Busy! Go away...' : 'Not doing too much.';
}
},
this.state.personsContext.selectedPerson.deleteHobby(value);
current: {
kind: 'instance',
get: function(){
return this.state.current;
}
},
then IMVVM is notified that the call was made from the 'persons' context
and not from the 'hobbies' context. Therefore any subscribers to 'hobbies.current'
are unaware of changes to 'hobbies.current'.
selectHobby: function(id){
for (var i = this.hobbies.length - 1; i >= 0; i--) {
if ((this.current === void(0) || this.current.id !== id) && this.hobbies[i].id === id){
this.setState({current: new Hobby(this.hobbies[i])}, {busy: true});
/*
//OR use a callback
this.setState({current: Hobby(this.hobbies[i])}, function(){
this.setState(void(0), {busy: true});
}.bind(this));
*/
If the selected hobby is deleted, then call setState from 'hobbies' ViewModel,
so that the 'persons' context gets updated and busy can be set on the 'domain'
break;
}
}
},
addHobby: function(value){
if(value !== ''){
this.state.personsContext.selectedPerson.
addHobby(new Hobby({ id: uuid(), name:value }, true));
}
},
deleteHobby: function(value){
/*
*/
If we were to simply call
if(this.current.id === value){
this.setState({ current: void(0) }, { busy: false }, function(){
this.state.personsContext.selectedPerson.deleteHobby(value);
}.bind(this));
} else {
this.state.personsContext.selectedPerson.deleteHobby(value);
}
},
this.state.personsContext.selectedPerson.deleteHobby(value);
uuid: function () {
/*jshint bitwise:false */
var i, random;
var uuid = '';
then IMVVM is notified that the call was made from the 'persons' context
and not from the 'hobbies' context. Therefore any subscribers to 'hobbies.current'
are unaware of changes to 'hobbies.current'.
for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0;
if (i === 8 || i === 12 || i === 16 || i === 20) {
uuid += '-';
If the selected hobby is deleted, then call setState from 'hobbies' ViewModel,
so that the 'persons' context gets updated and busy can be set on the 'domain'
*/
if(this.current && this.current.id === value){
this.setState({ current: void(0) }, { busy: false }, function(){
this.state.personsContext.selectedPerson.deleteHobby(value);
}.bind(this));
} else {
this.state.personsContext.selectedPerson.deleteHobby(value);
}
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
.toString(16);
}
return uuid;
},
});
});
return hobbiesViewModel;
}());

@@ -6,43 +6,9 @@ /*jshint unused: false */

var PersonsViewModel = IMVVM.createViewModel({
var PersonsViewModel = (function(){
getInitialState: function(){
var nextState = {};
nextState.collection = DataService.getPersonData().map(function(person, idx){
if (idx === 0){
nextState.selectedPerson = this.Person(person, true);
return nextState.selectedPerson;
}
return this.Person(person, true);
}.bind(this));
return nextState;
},
getWatchedState: function() {
return {
'hobbies': {
alias: 'hobbiesContext',
},
'online': {
alias: 'imOnline'
}
};
},
imOnline: {
kind:'pseudo',
get: function(){
return this.state.imOnline;
}
},
Person: function(){
return new PersonModel(this.personStateChangedHandler).apply(this, arguments);
},
personStateChangedHandler: function(nextState, prevState/*, callback*/){
var personStateChangedHandler = function(nextState, prevState/*, callback*/){
var persons = {};
persons.collection = this.collection.map(function(person){
if(person.id === nextState.id){
persons.selectedPerson = this.Person(nextState);
persons.selectedPerson = new Person(nextState);
return persons.selectedPerson;

@@ -53,62 +19,100 @@ }

this.setState(persons);
},
};
var Person = function(){
return new PersonModel(personStateChangedHandler).apply(this, arguments);
};
selectedHobby: {
kind: 'pseudo',
get: function() {
return this.state.hobbiesContext.current ? this.state.hobbiesContext.current.name: void(0);
}
},
var personsViewModel = IMVVM.createViewModel({
selectedPerson: {
kind: 'instance',
get: function() { return this.state.selectedPerson; }
},
getInitialState: function(){
var nextState = {};
nextState.collection = DataService.getPersonData().map(function(person, idx){
if (idx === 0){
nextState.selectedPerson = new Person(person, true);
return nextState.selectedPerson;
}
return new Person(person, true);
}.bind(this));
return nextState;
},
getWatchedState: function() {
return {
'hobbies': {
alias: 'hobbiesContext',
},
'online': {
alias: 'imOnline'
}
};
},
collection: {
kind: 'array',
get: function(){ return this.state.collection; },
},
imOnline: {
kind:'pseudo',
get: function(){
return this.state.imOnline;
}
},
selectPerson: function(id){
for (var i = this.collection.length - 1; i >= 0; i--) {
if(this.selectedPerson.id !== id && this.collection[i].id === id){
this.setState({ selectedPerson: this.Person(this.collection[i]) });
break;
selectedHobby: {
kind: 'pseudo',
get: function() {
return this.state.hobbiesContext.current ? this.state.hobbiesContext.current.name: void(0);
}
}
},
},
addPerson: function(value){
var nextState = {};
var name;
selectedPerson: {
kind: 'instance',
get: function() { return this.state.selectedPerson; }
},
if(value && value.length > 0){
name = value.split(' ');
nextState.selectedPerson = this.Person({
firstName: name[0],
lastName: name.slice(1).join(' ')
}, true);
nextState.collection = this.collection.slice(0);
nextState.collection = nextState.collection.concat(nextState.selectedPerson);
this.setState(nextState);
}
},
collection: {
kind: 'array',
get: function(){ return this.state.collection; },
},
deletePerson: function(uid){
var nextState = {};
nextState.collection = this.collection.filter(function(person){
return person.id !== uid;
});
nextState.selectedPerson = void(0);
if(nextState.collection.length > 0){
if (this.selectedPerson.id === uid){
nextState.selectedPerson = this.Person(nextState.collection[0]);
} else {
nextState.selectedPerson = this.Person(this.selectedPerson);
selectPerson: function(id){
for (var i = this.collection.length - 1; i >= 0; i--) {
if(this.selectedPerson.id !== id && this.collection[i].id === id){
this.setState({ selectedPerson: new Person(this.collection[i]) });
break;
}
}
}
this.setState(nextState);
},
},
});
addPerson: function(value){
var nextState = {};
var name;
if(value && value.length > 0){
name = value.split(' ');
nextState.selectedPerson = new Person({
firstName: name[0],
lastName: name.slice(1).join(' ')
}, true);
nextState.collection = this.collection.slice(0);
nextState.collection = nextState.collection.concat(nextState.selectedPerson);
this.setState(nextState);
}
},
deletePerson: function(uid){
var nextState = {};
nextState.collection = this.collection.filter(function(person){
return person.id !== uid;
});
nextState.selectedPerson = void(0);
if(nextState.collection.length > 0){
if (this.selectedPerson.id === uid){
nextState.selectedPerson = new Person(nextState.collection[0]);
} else {
nextState.selectedPerson = new Person(this.selectedPerson);
}
}
this.setState(nextState);
},
});
return personsViewModel;
}());

@@ -5,5 +5,5 @@ 'use strict';

getPersonData: function() {
return [{id:'1', firstName:'Frank', lastName: "Smith", gender:'male', dob:'1980-03-03', job:'dentist', hobbies: ['reading', 'golfing', 'computer programming']},
{id:'2', firstName:'Lisa', lastName: "Jones", gender:'female', dob:'1985-02-22', job:'accountant', hobbies: ['reading']},
{id:'3', firstName: "John", lastName: "Citizen", gender:'male', dob:'1975-12-11', job:'unemployed', hobbies: ['watching TV']}];
return [{id:'1', firstName:'Frank', lastName: "Smith", gender:'male', dob:'1980-03-03', job:'Dentist'},
{id:'2', firstName:'Lisa', lastName: "Jones", gender:'female', dob:'1985-02-22', job:'Accountant'},
{id:'3', firstName: "John", lastName: "Citizen", gender:'male', dob:'1975-12-11', job:'Unemployed'}];
},

@@ -14,11 +14,11 @@ getHobbiesData: function(uid) {

id:'1',
hobbies: [{id:'1', name: 'reading'}, {id:'2', name: 'golfing'}, {id:'3', name: 'computer programming'}]
hobbies: [{id:'1', hobby: 'reading'}, {id:'2', hobby: 'golfing'}, {id:'3', hobby: 'cutting code'}]
},
{
id:'2',
hobbies: [{id:'1', name: 'reading'}]
hobbies: [{id:'1', hobby: 'reading'}]
},
{
id:'3',
hobbies: [{id:'1', name: 'watching TV'}]
hobbies: [{id:'1', hobby: 'watching YouTube'}]
}];

@@ -25,0 +25,0 @@ var personHobbies = hobbies.filter(function(person){

{
"name": "imvvm",
"description": "Immutable MVVM for React",
"version": "0.6.16",
"version": "0.6.19",
"keywords": [

@@ -10,3 +10,2 @@ "mvvm",

"immutable",
"node",
"presentation model",

@@ -16,3 +15,6 @@ "imvvm"

"homepage": "https://github.com/entrendipity/imvvm",
"author": "Frank Panetta <frank.panetta@entrendipity.com.au>",
"author": {
"name": "Frank Panetta",
"email": "frank.panetta@entrendipity.com.au"
},
"repository": {

@@ -31,2 +33,2 @@ "type": "git",

}
}
}

@@ -54,3 +54,14 @@ IMVVM

## Getting Started
###Install and start the example application (which is intended to act as a reference implementation).
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.
```
$ npm install
$ cd app
$ bower install
$ bower install imvvm
$ cd ..
$ grunt serve
```
### Create a Model

@@ -63,4 +74,4 @@

return {
age: this.calculateAge(this.dob),
id: this.id ? this.id : this.uuid()
age: calculateAge(this.dob),
id: this.id ? this.id : uuid()
};

@@ -91,3 +102,3 @@ },

if(newValue.length === 10){
age = this.calculateAge(newValue);
age = calculateAge(newValue);
}

@@ -118,25 +129,3 @@ if(newValue.length === 0){

},
calculateAge: function(dob){
var DOB = new Date(dob);
var ageDate = new Date(Date.now() - DOB.getTime());
var age = Math.abs(ageDate.getFullYear() - 1970);
return isNaN(age) ? 'Enter your Birthday' : age + ' years old';
},
uuid: function () {
var i, random;
var uuid = '';
for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0;
if (i === 8 || i === 12 || i === 16 || i === 20) {
uuid += '-';
}
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
.toString(16);
}
return uuid;
},
});

@@ -150,3 +139,3 @@ ```

#####age
`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.
`age` is a calculated field. It is set by setting `dob`. `dob` uses a 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.

@@ -156,2 +145,19 @@ ### Create a ViewModel

```javascript
var personStateChangedHandler = function(nextState, prevState){
var persons = {};
persons.collection = this.collection.map(function(person){
if(person.id === nextState.id){
persons.selectedPerson = new Person(nextState);
return persons.selectedPerson;
}
return person;
}.bind(this));
this.setState(persons);
};
var Person = function(){
return new PersonModel(personStateChangedHandler).apply(this, arguments);
};
var PersonsViewModel = IMVVM.createViewModel({

@@ -163,6 +169,6 @@

if (idx === 0){
nextState.selectedPerson = this.Person(person, true);
nextState.selectedPerson = new Person(person, true);
return nextState.selectedPerson;
}
return this.Person(person, true);
return new Person(person, true);
}.bind(this));

@@ -200,19 +206,2 @@ return nextState;

personStateChangedHandler: function(nextState, prevState){
var persons = {};
persons.collection = this.collection.map(function(person){
if(person.id === nextState.id){
persons.selectedPerson = this.Person(nextState);
return persons.selectedPerson;
}
return person;
}.bind(this));
this.setState(persons);
},
Person: function(){
return new PersonModel(this.personStateChangedHandler).apply(this, arguments);
},
selectedHobby: {

@@ -228,3 +217,3 @@ kind: 'pseudo',

if(this.selectedPerson.id !== id && this.collection[i].id === id){
this.setState({ selectedPerson: this.Person(this.collection[i]) });
this.setState({ selectedPerson: new Person(this.collection[i]) });
break;

@@ -241,3 +230,3 @@ }

name = value.split(' ');
nextState.selectedPerson = this.Person({
nextState.selectedPerson = new Person({
firstName: name[0],

@@ -260,5 +249,5 @@ lastName: name.slice(1).join(' ')

if (this.selectedPerson.id === uid){
nextState.selectedPerson = this.Person(nextState.collection[0]);
nextState.selectedPerson = new Person(nextState.collection[0]);
} else {
nextState.selectedPerson = this.Person(this.selectedPerson);
nextState.selectedPerson = new Person(this.selectedPerson);
}

@@ -302,2 +291,9 @@ }

```javascript
var onPersonChangedHandler = function(nextState, prevState, field, context){
if(this.current !== void(0) && context === 'persons' &&
nextState.id !== prevState.id){
return { hobbies: { current: void(0) }, busy: false };
}
};
var HobbiesViewModel = IMVVM.createViewModel({

@@ -310,3 +306,3 @@

fields: {
'selectedPerson': this.onPersonChangedHandler
'selectedPerson': onPersonChangedHandler
}

@@ -319,9 +315,2 @@ },

},
onPersonChangedHandler: function(nextState, prevState, field, context){
if(this.current !== void(0) && context === 'persons' &&
nextState.id !== prevState.id){
return { hobbies: { current: void(0) }, busy: false };
}
},

@@ -334,7 +323,7 @@ ...

this.setState({current: this.Hobby(this.hobbies[i])}, {busy: true});
this.setState({current: new Hobby(this.hobbies[i])}, {busy: true});
/*
//OR use a callback
this.setState({current: this.Hobby(this.hobbies[i])}, function(){
this.setState({current: new Hobby(this.hobbies[i])}, function(){
this.setState(void(0), {busy: true});

@@ -357,3 +346,3 @@ }.bind(this));

Both the `alias` and `fields` properties are optional.
Both the `alias` and `fields` properties are optional. However at least one must be present.

@@ -366,3 +355,3 @@ #####onPersonChangedHandler

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)}}`).
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: new Person(personState)}}`).

@@ -425,4 +414,17 @@ Also noted within comments, is that this can be achieved within a callback, ensuring to pass `void(0)` as the first parameter to `setState`.

#####persons
The `persons` property is setting up a data context called 'persons'. It has a special decorator called `viewModel` which specifies which ViewModel is associated to this data context.
The `persons` property sets up a data context called 'persons'. It has a special decorator called `viewModel`, which specifies the associated ViewModel for this data context.
___
>___This is probably a good time to explain a little about what gets exposed to the View.___
>
>When a Model, ViewModel or DomainViewModel is instantiated, IMVVM takes all the defined functions and places them on the Object's prototype. It also takes all the field descriptors and assigns them as properties for the newly created object.
>
>So all functions and fields defined within a Model, ViewModel or DomainModel, are visible to other objects. This means that the View has visibility and access to these functions and fields, including any implementation specific functions, which probably should be kept separate from the View.
>
>What would be preferred, is to only expose the properties and functions the View needs. To accomplish this, define variables, properties or functions outside of your Models, ViewModels and DomainViewModels, and simply reference them. That way the View API is kept nice and clean and your implementation is kept separate.
>
>Refer to the reference implementation (i.e. example application), which uses this technique.
___
### Hook up the View

@@ -548,14 +550,2 @@ Once you have created your Models. ViewModels and DomainViewModel, you're ready to hook it up the the View. All you need to do is specify the mixin and IMVVM will attach a `domainDataContext` to the state object that will be kept in sync with you're ViewModel.

##Running the example application
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.
```
$ npm install
$ cd app
$ bower install
$ bower install imvvm
$ cd ..
$ grunt serve
```
##API

@@ -579,2 +569,3 @@

__specification__ - see [Specification](#specification)
___

@@ -618,17 +609,3 @@ #####function createModel(object specification)

_Available in:_ DomainViewModel, ViewModel, Model
___
#####object extend(object currentState[, object... nextState])
Creates a shallow copy of currentState. Adds/replaces properties with properties of subsequent objects.
*parameters*
__currentState__
Old state object.
__nextState__
Next state objects.
_Available in:_ DomainViewModel, ViewModel, Model
___

@@ -662,2 +639,3 @@ #####object undo()

_Available in:_ DomainViewModel
___

@@ -701,3 +679,5 @@ #####canUndo

######Watching DomainViewModel state
___n.b. `alias` and `fields` are optional, however at least one must be present. This is intentional. `alias` is an indicator that the ViewModel should attach the specified dataContext to the `state` object. If `alias` is not specified then it will not be attached.___
######Watching Domain Data Context state
field\: \{

@@ -707,2 +687,4 @@ alias\: preferredName

___n.b. `alias` is not optional, in this istance, as only fields can be referenced to the Domain dataContext.___
___example___

@@ -777,3 +759,2 @@ ```javascript

```javascript

@@ -785,3 +766,3 @@ personStateChangedHandler: function(nextState, prevState){

persons.selected = this.Person(nextState, person, true);
persons.selected = new Person(nextState, person, true);
return persons.selected;

@@ -826,7 +807,7 @@ }

var nextState = this.extend(personObj, {firstName: 'Fred'});
persons.selectedPerson = this.Person(nextState);
persons.selectedPerson = new Person(nextState);
```
```javascript
persons.selectedPerson = this.Person(personObj, {firstName: 'Fred'});
persons.selectedPerson = new Person(personObj, {firstName: 'Fred'});
```

@@ -840,3 +821,3 @@

__Usage example__
___Usage example___

@@ -846,5 +827,5 @@ ___n.b. This is suggested usage and not part of the API___

```javascript
Person: function(){
return new PersonModel(this.personStateChangedHandler).apply(this, arguments);
},
var Person: function(){
return new PersonModel(personStateChangedHandler).apply(this, arguments);
},
```

@@ -858,4 +839,2 @@

___
####Descriptor

@@ -903,11 +882,11 @@ ___

```javascript
occupation: {
aliasFor: 'job',
get: function(){
return this.state.occupation;
},
set: function(newValue){
this.setState({'occupation': newValue });
}
occupation: {
aliasFor: 'job',
get: function(){
return this.state.occupation;
},
set: function(newValue){
this.setState({'occupation': newValue });
}
},
```

@@ -950,2 +929,26 @@

###Helpers
####extend
___
#####object extend(object currentState[, object... nextState])
Creates a shallow copy of currentState. Adds/replaces properties with properties of subsequent objects.
*parameters*
__currentState__
Old state object.
__nextState__
Next state objects.
___Usage example___
```javascript
var nextState = IMVVM.extend(currentState, nextState);
```
_Available in:_ DomainViewModel, ViewModel, Model
## Browser Support

@@ -952,0 +955,0 @@ Most ECMAScript 5 compliant browsers.

@@ -67,3 +67,3 @@

for(dataContext in domain){
nextState[dataContext] = new dataContexts[dataContext](nextState);
nextState[dataContext] = new dataContexts[dataContext](nextState[dataContext]);
}

@@ -84,3 +84,10 @@

if(typeof callback === 'function'){
appState = new ApplicationDataContext(nextState, prevState, redoState, enableUndo);
callback();
return;
}
} else {
if(!!newStateKeys.length){

@@ -109,3 +116,3 @@ if(caller === appNamespace){

nextState[transientStateKeys[keyIdx]] = extend(appState[transientStateKeys[keyIdx]], transientState[transientStateKeys[keyIdx]]);
nextState[transientStateKeys[keyIdx]] = new dataContexts[transientStateKeys[keyIdx]](nextState);
nextState[transientStateKeys[keyIdx]] = new dataContexts[transientStateKeys[keyIdx]](nextState[transientStateKeys[keyIdx]]);
} else {

@@ -196,3 +203,2 @@ nextState[transientStateKeys[keyIdx]] = transientState[transientStateKeys[keyIdx]];

}

@@ -207,5 +213,3 @@ appState = new ApplicationDataContext(nextState, prevState, redoState, enableUndo);

processedState = {};
//Provided for the main app to return to the View
return appState;
};

@@ -215,3 +219,2 @@

ApplicationDataContext = domainModel.call(this, appStateChangedHandler.bind(this, appNamespace));
/*Need to look at DomainViewModel state and nextState and Domain Model and updating*/
appState = new ApplicationDataContext(void(0), void(0), void(0), enableUndo, true);

@@ -221,10 +224,12 @@ appState.state = appState.state || {};

domain = appState.getDomainDataContext();
delete appState.__proto__.getDomainDataContext;
for(dataContext in domain){
if(domain.hasOwnProperty(dataContext)){
dataContexts[dataContext] = domain[dataContext].call(this, appStateChangedHandler.bind(this, dataContext)).bind(this, dataContext);
appState.state[dataContext] = new dataContexts[dataContext](appState.state);
dataContexts[dataContext] = domain[dataContext].call(this, appStateChangedHandler.bind(this, dataContext));
appState.state[dataContext] = new dataContexts[dataContext](appState.state[dataContext]);
if('getWatchedState' in appState[dataContext]){
watchedState = appState[dataContext].getWatchedState();
delete appState[dataContext].__proto__.getWatchedState;
for(watchedItem in watchedState){

@@ -283,3 +288,5 @@ if(watchedState.hasOwnProperty(watchedItem)){

Object.freeze(appState);
console.warn('\"this.extend\" has been deprecated and will not be available in 0.7. Please use \"IMVVM.extend\".');
return appState;
};

@@ -57,4 +57,4 @@

if('__processedObject__' in this.originalSpec){
return this.originalSpec.__processedObject__;
if('__processedSpec__' in this.originalSpec){
return this.originalSpec.__processedSpec__;
}

@@ -67,7 +67,2 @@

this.originalSpec[key].enumerable = true;
if('aliasFor' in this.originalSpec[key]){
aliases[this.originalSpec[key].aliasFor] = key;
delete this.originalSpec[key].aliasFor;
}
if('viewModel' in this.originalSpec[key]) {

@@ -77,9 +72,16 @@ viewModels[key] = this.originalSpec[key].viewModel;

delete this.originalSpec[key].set;
} else if('kind' in this.originalSpec[key]){
if(this.originalSpec[key].kind === 'pseudo'){
this.originalSpec[key].enumerable = false;
} else { //'instance' || 'array'
autoFreeze.push({fieldName: key, kind: this.originalSpec[key].kind});
} else {
if('aliasFor' in this.originalSpec[key]){
aliases[this.originalSpec[key].aliasFor] = key;
delete this.originalSpec[key].aliasFor;
}
delete this.originalSpec[key].kind;
if('kind' in this.originalSpec[key]){
if(this.originalSpec[key].kind === 'pseudo'){
this.originalSpec[key].enumerable = false;
} else { //'instance' || 'array'
autoFreeze.push({fieldName: key, kind: this.originalSpec[key].kind});
}
delete this.originalSpec[key].kind;
}
}

@@ -94,3 +96,3 @@ descriptor[key] = this.originalSpec[key];

if(!('extend' in proto)){
proto.extend = utils.extend;
proto.extend = utils.extend;
}

@@ -104,3 +106,3 @@

this.originalSpec.__processedObject__ = {
this.originalSpec.__processedSpec__ = {
descriptor: descriptor,

@@ -113,3 +115,3 @@ proto: proto,

return this.originalSpec.__processedObject__;
return this.originalSpec.__processedSpec__;
};

@@ -125,5 +127,6 @@

createDomainViewModel: IMVVMClass.createClass.bind(this, DomainViewModelBase, 'DomainViewModel'),
mixin: mixin
mixin: mixin,
extend: extend
};
module.exports = IMVVM;

@@ -76,3 +76,4 @@

//Add state prop so that it can be referenced from within getInitialState
nextState = ('getInitialState' in domainModel) ? domainModel.getInitialState.call(domainModel) : {};
nextState = ('getInitialState' in domainModel) ? domainModel.getInitialState.call(domainModel) : {};
delete domainModel.__proto__.getInitialState;
} else if('state' in nextState){

@@ -79,0 +80,0 @@ delete nextState.state;

@@ -12,4 +12,5 @@

desc.stateChangedHandler = stateChangedHandler;
desc.proto.__getDescriptor = function(){
return desc;
if('getInitialState' in desc.originalSpec){
desc.proto.getInitialState = desc.originalSpec.getInitialState;
}

@@ -51,3 +52,4 @@

if('getInitialState' in model){
nextState = extend(nextState, model.getInitialState.call(model));
nextState = extend(nextState, model.getInitialState.call(model));
delete model.__proto__.getInitialState;
}

@@ -54,0 +56,0 @@ }

@@ -13,3 +13,3 @@

var dataContext = function(VMName, nextAppState) {
var dataContext = function(nextVMState) {

@@ -31,9 +31,8 @@ //nextState has already been extended with prevState in core

if(!!nextAppState){
if(nextAppState[VMName] === void(0)){
nextState = ('getInitialState' in viewModel) ?
extend(nextState, viewModel.getInitialState.call(viewModel)) : nextState;
} else {
nextState = ('state' in nextAppState[VMName] ? nextAppState[VMName].state : nextAppState[VMName]);
}
if(nextVMState === void(0)){
nextState = ('getInitialState' in viewModel) ?
extend(nextState, viewModel.getInitialState.call(viewModel)) : nextState;
delete viewModel.__proto__.getInitialState;
} else {
nextState = ('state' in nextVMState ? nextVMState.state : nextVMState);
}

@@ -52,5 +51,6 @@

if(viewModel[freezeFields[fld].fieldName]){
tempDesc = viewModel[freezeFields[fld].fieldName].__getDescriptor();
tempDesc = viewModel[freezeFields[fld].fieldName].constructor.originalSpec.__processedSpec__;
tempModel = Object.create(tempDesc.proto, tempDesc.descriptor);
delete tempModel.__proto__.getInitialState;
Object.defineProperty(tempModel, 'state', {

@@ -57,0 +57,0 @@ configurable: true,

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc