-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
228 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
{ | ||
"env": { | ||
"browser": true, | ||
"es6": true, | ||
"node" : true | ||
}, | ||
"extends": "eslint:recommended", | ||
"parserOptions": { | ||
"sourceType": "module", | ||
"ecmaVersion": 8 | ||
}, | ||
"plugins": [ | ||
], | ||
"rules": { | ||
"no-useless-escape" : "off", | ||
"no-constant-condition" : "off", | ||
"no-unused-vars" : "warn", | ||
"no-console": "off", | ||
"no-mixed-spaces-and-tabs" : "warn", | ||
"indent": [ | ||
"warn", | ||
4, | ||
{"SwitchCase": 1} | ||
], | ||
"linebreak-style": [ | ||
"error", | ||
"unix" | ||
], | ||
"quotes": [ | ||
"error", | ||
"single" | ||
], | ||
"semi": [ | ||
"warn", | ||
"always", | ||
{"omitLastInOneLineBlock" : true} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#OS junk files | ||
[Tt]humbs.db | ||
*.DS_Store | ||
|
||
#Sublime | ||
*.sublime-workspace | ||
|
||
#Common | ||
/.sass-cache | ||
/node_modules | ||
/npm-debug.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,11 @@ | ||
# deep-observer | ||
#Deep Observer | ||
|
||
Tiny Object Observe library, to watch Objects for changes and execute callbacks to track them. | ||
|
||
|
||
- Based in Proxyes | ||
- Compatible with all JS primitive types | ||
|
||
``` | ||
... | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "deep-observer", | ||
"version": "1.0.0", | ||
"description": "Deep Object Observe, and and execute callbacks on changes are applied (add,update,delete)", | ||
"main": "./src/deep-observer.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/colxi/deep-observer.git" | ||
}, | ||
"keywords": [ | ||
"object", | ||
"observe", | ||
"observer", | ||
"watch", | ||
"objec", | ||
"watch" | ||
], | ||
"author": "colxi", | ||
"license": "GPL-3.0", | ||
"bugs": { | ||
"url": "https://github.com/colxi/deep-observer/issues" | ||
}, | ||
"homepage": "https://github.com/colxi/deep-observer#readme" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
(function(){ | ||
'use strict'; | ||
|
||
/** | ||
* OBSERVED Object contains all the Observable generated proxies. The generated | ||
* or provided ID NAME is used as the index | ||
*/ | ||
const OBSERVED = {}; | ||
|
||
/** | ||
* OBSERVED_WS WeakSet containing all the weak references to all the active | ||
* Observables (and inner observed Objects and Arrays). This lets detect when a | ||
* reference to something already observed be reused | ||
*/ | ||
const OBSERVED_WS = new WeakSet(); | ||
|
||
/** | ||
* isObjLiteralOrArray : Modified version to include arrays, taken from : | ||
* https://stackoverflow.com/questions/1173549/] | ||
* | ||
* Arguments: | ||
* _obj Item to analyze | ||
* | ||
* Return: | ||
* Boolean | ||
* | ||
*/ | ||
const isObjLiteralOrArray = function(_obj){ | ||
var _test = _obj; | ||
return ( typeof _obj !== 'object' || _obj === null ? | ||
false : | ||
( | ||
(function () { | ||
if( Array.isArray(_obj) ) return true; | ||
while (!false) { | ||
if ( Object.getPrototypeOf( _test = Object.getPrototypeOf(_test) ) === null) { | ||
break; | ||
} | ||
} | ||
return Object.getPrototypeOf(_obj) === _test; | ||
})() | ||
) | ||
); | ||
}; | ||
|
||
|
||
/** | ||
* newObserver | ||
* @param {[newObservertype]} modelContents [description] | ||
* @param {[type]} keyPath [description] | ||
* @param {Function} callback [description] | ||
* @return {[type]} [description] | ||
*/ | ||
const newObserver = function( value, keyPath, callback){ | ||
let result; | ||
|
||
if( OBSERVED_WS.has(value) ){ | ||
// IGNORE ASIGNEMENT | ||
// provided item is a reference of somthing already observed. | ||
// return the same item, instead of a new one | ||
result = value; | ||
}else{ | ||
// PERFORM ASIGNEMENT | ||
// item is a new reference not yet observed, create new proxy | ||
|
||
// | ||
let _target = Array.isArray(value) ? []:{}; | ||
|
||
let ObserbableObject = new Proxy( _target , { | ||
set : function(target, property, value){ | ||
// save old value and detect action type | ||
let oldValue = target[property]; | ||
let action = target.hasOwnProperty(property) ? 'update' : 'add'; | ||
|
||
// if performing an update and new value equals old value, | ||
// no action is required, becacause no changes are being applied | ||
if( action === 'update' && oldValue===value ) return true; | ||
|
||
if( isObjLiteralOrArray(value) ){ | ||
// if value to SET is an Object or Array, create a new | ||
// proxy, with updated keypath | ||
target[property] = newObserver(value , keyPath+'.'+property,callback); | ||
}else{ | ||
// anything else, set the new value | ||
target[property] = value; | ||
} | ||
|
||
// invoke the callback | ||
callback({action:action,keyPath:keyPath, object: target, name:property, oldValue : oldValue}); | ||
return true; | ||
}, | ||
|
||
deleteProperty(target, property) { | ||
let oldValue = target[property]; | ||
delete target[property]; | ||
// invoke the callback | ||
callback({action:'delete',keyPath:keyPath, object: target, name:property, oldValue : oldValue}); | ||
return true; | ||
}, | ||
|
||
get : function(target, property){ | ||
// | ||
return target[property]; | ||
} | ||
}); | ||
|
||
// assign the properties to the ObserbableObject | ||
Object.assign( ObserbableObject, value ); | ||
// add the object to the observed objects | ||
OBSERVED_WS.add(ObserbableObject); | ||
|
||
result = ObserbableObject; | ||
} | ||
|
||
return result; | ||
}; | ||
|
||
/** | ||
* [Observer description] | ||
* @param {Object} conf [description] | ||
*/ | ||
const Observer = function( conf = {} ){ | ||
const modelName = conf.name || 'OBSERVED-'+Math.floor( Math.random()* Date.now() ); | ||
const content = conf.item || undefined; | ||
|
||
// if contents are provided, behave as a setter | ||
if(typeof content !== 'undefined'){ | ||
OBSERVED[modelName] = newObserver(content, modelName, conf.callback || new Function()); | ||
} | ||
|
||
return OBSERVED[modelName]; | ||
}; | ||
|
||
|
||
// done! | ||
if (typeof module !== 'undefined' && module.exports) exports.Observer = Observer; | ||
else window.Observer = Observer; | ||
|
||
})(); | ||
|