"use strict";var PubSub=require("sublish").PubSub,slice=Array.prototype.slice,isArray=Array.isArray?Array.isArray:function(arr){return Object.prototype.toString.call(arr)==="[object Array]"},contains=Array.prototype.indexOf?function(arr,el){return!!~arr.indexOf(el)}:function(arr,el){for(var i=0;i1){if(typeof args[1]==="function"){config.write=args[1];if(args.length>2){config.watch=args[2]}}else{config.watch=args[1]}}}return config}function obs(config){function observable(value){if(arguments.length){if(typeof observable.write==="function"){observable.write.call(observable.context,value)}else{throw new Error("This observable cannot be written to!")}}else{if(typeof observable.read==="function"){return observable.read.call(observable.context)}else{throw new Error("This observable cannot be read from!")}}}ext(observable,PubSub.prototype,{context:config.context||observable,read:config.read,write:config.write,onNotify:function(onNotify){return function(){onNotify.call(observable)}}(config.onNotify||function(){}),_initialValue:config.value,_currentValue:config.value,_previousValue:undefined,_subscriptions:[]},obs.fn);PubSub.apply(observable);if(config.watch){observable.watch.apply(observable,isArray(config.watch)?config.watch:[config.watch])}return observable}obs.fn={__is_obs__:true,notify:function(){this.dirty=this._currentValue===this._initialValue;this.publish(this._currentValue,this._previousValue)},peek:function(){return this._currentValue},commit:function(){this._initialValue=this._currentValue;this.dirty=false},reset:function(){this._previousValue=this._currentValue;this._currentValue=this._initialValue;this.notify()},watch:function(){var args=slice.call(arguments,0),sub,i;for(i=0;i