Skip to content

Instantly share code, notes, and snippets.

@FireNeslo
Created July 26, 2013 14:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FireNeslo/6089356 to your computer and use it in GitHub Desktop.
Save FireNeslo/6089356 to your computer and use it in GitHub Desktop.
Observer like object to maintain a reference to data that can or will change a lot.
/**
Creates a new Objserver.
@class Observes an object and updates its value on changes that are applied.
@param [value] - Optional init value; -
*/
function Objserver(value) {
this.$value = value;
this.$change = [];
}
function jsonPath(obj,string) {
var parts = string
.replace(/\[/g, '.')
.replace(/\]/g, '')
.split("."),
path = obj;
parts.forEach(function(part){
path = path[part];
});
return path;
}
/**
* @memberOf Objserver
* Adds a change listener that is fired if somthing changes
* @returns {Objserver} self - For chaining
*/
Objserver.prototype.onChange = function(cb) {
this.$change.push(cb);
return this;
};
/**
* @memberOf Objserver
* @param {function} listener - Listener to remove.
* @returns {Objserver} self - For chaining
*/
Objserver.prototype.off = function(cb) {
this.$change.splice(this.$change.indexOf(cb), 1);
return this;
};
/**
* Trigger change event
* @memberOf Objserver
* @param newval - The new value
* @param newval - The old value
* @returns {Objserver} self - For chaining
*/
Objserver.prototype.change = function(newval, oldval) {
var _self = this;
this.$change.forEach(function(fn, index) {
var $event = {
class : Objserver,
instance : _self,
value : _self.$value
};
fn.call($event, newval, oldval);
});
return this;
};
/**
* Get current value
* @memberOf Objserver
* @returns value current value
*/
Objserver.prototype.val = function() {
return this.$value;
}
/**
* Bind the value to some object to keep that object informed on updates.
* @memberOf Objserver
* @param {object} object - Object to bind to
* @param {string} name - Attribute name
* @returns {Objserver} self - For chaining
*/
Objserver.prototype.bind = function(object, name) {
object[name] = this.$value;
this.change(function(value) {
object[name] = value;
});
return this;
};
/**
* Maps function on object, native map fo arrays or unboxing for promises
* @memberOf Objserver
* @param {function} fn - The function to map.
* @returns {Objserver} self - For chaining
*/
Objserver.prototype.map = function(fn) {
var _self = this;
if(this.$value.then) {
_self.$value.then(function(value) {
_self.ap(fn);
})
}
var newVal = this.$value.map(fn), oldVal = this.$value;
this.$value = newVal;
this.change(newVal, oldVal);
return this;
};
/**
* Map / Apply method
* @memberOf Objserver
* @param {function|Promise|object} cb - The Object/Promise or function to apply.
* @param {string} jsonpath - the path to the value you supplied.
* @returns {Objserver} self - For chaining
*/
Objserver.prototype.ap = function(cb,jsonpath) {
var _self = this,
oldVal,
newVal;
if(this.$value && this.$value.then) {
_self.$value.then(function(value) {
_self.$value = value;
_self.ap(cb);
});
} else if(cb && cb.then) {
oldVal = this.$value;
cb.then(function(value) {
newVal = jsonpath ?
jsonPath(value, jsonpath) :
value;
_self.$value = newVal;
_self.change(newVal, oldVal);
});
} else if(!angular.isFunction(cb)) {
oldVal = _self.$value;
newVal = jsonpath ?
jsonPath(cb, jsonpath) :
cb;
_self.$value = newVal;
this.change(newVal, oldVal);
} else {
oldVal = this.$value;
newVal = cb(this.$value);
this.$value = newVal;
this.change(newVal, oldVal);
}
return this;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment