Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
colxi committed Jul 15, 2018
1 parent b2a190f commit 37e057b
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 1 deletion.
39 changes: 39 additions & 0 deletions .eslintrc.json
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}
]
}
}
11 changes: 11 additions & 0 deletions .gitignore
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
12 changes: 11 additions & 1 deletion README.md
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

```
...
```
Binary file added logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions package.json
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"
}
140 changes: 140 additions & 0 deletions src/deep-oberver.js
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;

})();

0 comments on commit 37e057b

Please sign in to comment.