1 define("dojo/Stateful", ["./_base/kernel", "./_base/declare", "./_base/lang", "./_base/array"], function(dojo, declare, lang, array) {
7 return dojo.declare("dojo.Stateful", null, {
9 // Base class for objects that provide named properties with optional getter/setter
10 // control and the ability to watch for property changes
12 // | var obj = new dojo.Stateful();
13 // | obj.watch("foo", function(){
14 // | console.log("foo changed to " + this.get("foo"));
16 // | obj.set("foo","bar");
17 postscript: function(mixin){
19 lang.mixin(this, mixin);
23 get: function(/*String*/name){
25 // Get a property on a Stateful instance.
27 // The property to get.
29 // The property value on this Stateful instance.
31 // Get a named property on a Stateful object. The property may
32 // potentially be retrieved via a getter method in subclasses. In the base class
33 // this just retrieves the object's property.
35 // | stateful = new dojo.Stateful({foo: 3});
36 // | stateful.get("foo") // returns 3
37 // | stateful.foo // returns 3
39 return this[name]; //Any
41 set: function(/*String*/name, /*Object*/value){
43 // Set a property on a Stateful instance
45 // The property to set.
47 // The value to set in the property.
49 // The function returns this dojo.Stateful instance.
51 // Sets named properties on a stateful object and notifies any watchers of
52 // the property. A programmatic setter may be defined in subclasses.
54 // | stateful = new dojo.Stateful();
55 // | stateful.watch(function(name, oldValue, value){
56 // | // this will be called on the set below
58 // | stateful.set(foo, 5);
60 // set() may also be called with a hash of name/value pairs, ex:
65 // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
66 if(typeof name === "object"){
72 var oldValue = this[name];
74 if(this._watchCallbacks){
75 this._watchCallbacks(name, oldValue, value);
77 return this; //dojo.Stateful
79 watch: function(/*String?*/name, /*Function*/callback){
81 // Watches a property for changes
83 // Indicates the property to watch. This is optional (the callback may be the
84 // only parameter), and if omitted, all the properties will be watched
86 // An object handle for the watch. The unwatch method of this object
87 // can be used to discontinue watching this property:
88 // | var watchHandle = obj.watch("foo", callback);
89 // | watchHandle.unwatch(); // callback won't be called now
91 // The function to execute when the property changes. This will be called after
92 // the property has been changed. The callback will be called with the |this|
93 // set to the instance, the first argument as the name of the property, the
94 // second argument as the old value and the third argument as the new value.
96 var callbacks = this._watchCallbacks;
99 callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
100 var notify = function(propertyCallbacks){
101 if(propertyCallbacks){
102 propertyCallbacks = propertyCallbacks.slice();
103 for(var i = 0, l = propertyCallbacks.length; i < l; i++){
105 propertyCallbacks[i].call(self, name, oldValue, value);
112 notify(callbacks['_' + name]);
114 notify(callbacks["*"]); // the catch-all
116 }; // we use a function instead of an object so it will be ignored by JSON conversion
118 if(!callback && typeof name === "function"){
122 // prepend with dash to prevent name conflicts with function (like "name" property)
125 var propertyCallbacks = callbacks[name];
126 if(typeof propertyCallbacks !== "object"){
127 propertyCallbacks = callbacks[name] = [];
129 propertyCallbacks.push(callback);
132 propertyCallbacks.splice(array.indexOf(propertyCallbacks, callback), 1);