source: Dev/branches/rest-dojo-ui/client/dojo/Stateful.js @ 274

Last change on this file since 274 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 4.4 KB
Line 
1define(["./_base/kernel", "./_base/declare", "./_base/lang", "./_base/array"], function(dojo, declare, lang, array) {
2        // module:
3        //              dojo/Stateful
4        // summary:
5        //              TODOC
6
7return dojo.declare("dojo.Stateful", null, {
8        // summary:
9        //              Base class for objects that provide named properties with optional getter/setter
10        //              control and the ability to watch for property changes
11        // example:
12        //      |       var obj = new dojo.Stateful();
13        //      |       obj.watch("foo", function(){
14        //      |               console.log("foo changed to " + this.get("foo"));
15        //      |       });
16        //      |       obj.set("foo","bar");
17        postscript: function(mixin){
18                if(mixin){
19                        lang.mixin(this, mixin);
20                }
21        },
22
23        get: function(/*String*/name){
24                // summary:
25                //              Get a property on a Stateful instance.
26                //      name:
27                //              The property to get.
28                //      returns:
29                //              The property value on this Stateful instance.
30                // description:
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.
34                //              For example:
35                //      |       stateful = new dojo.Stateful({foo: 3});
36                //      |       stateful.get("foo") // returns 3
37                //      |       stateful.foo // returns 3
38
39                return this[name]; //Any
40        },
41        set: function(/*String*/name, /*Object*/value){
42                // summary:
43                //              Set a property on a Stateful instance
44                //      name:
45                //              The property to set.
46                //      value:
47                //              The value to set in the property.
48                //      returns:
49                //              The function returns this dojo.Stateful instance.
50                // description:
51                //              Sets named properties on a stateful object and notifies any watchers of
52                //              the property. A programmatic setter may be defined in subclasses.
53                //              For example:
54                //      |       stateful = new dojo.Stateful();
55                //      |       stateful.watch(function(name, oldValue, value){
56                //      |               // this will be called on the set below
57                //      |       }
58                //      |       stateful.set(foo, 5);
59                //
60                //      set() may also be called with a hash of name/value pairs, ex:
61                //      |       myObj.set({
62                //      |               foo: "Howdy",
63                //      |               bar: 3
64                //      |       })
65                //      This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
66                if(typeof name === "object"){
67                        for(var x in name){
68                                this.set(x, name[x]);
69                        }
70                        return this;
71                }
72                var oldValue = this[name];
73                this[name] = value;
74                if(this._watchCallbacks){
75                        this._watchCallbacks(name, oldValue, value);
76                }
77                return this; //dojo.Stateful
78        },
79        watch: function(/*String?*/name, /*Function*/callback){
80                // summary:
81                //              Watches a property for changes
82                //      name:
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
85                // returns:
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
90                //      callback:
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.
95
96                var callbacks = this._watchCallbacks;
97                if(!callbacks){
98                        var self = this;
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++){
104                                                        try{
105                                                                propertyCallbacks[i].call(self, name, oldValue, value);
106                                                        }catch(e){
107                                                                console.error(e);
108                                                        }
109                                                }
110                                        }
111                                };
112                                notify(callbacks['_' + name]);
113                                if(!ignoreCatchall){
114                                        notify(callbacks["*"]); // the catch-all
115                                }
116                        }; // we use a function instead of an object so it will be ignored by JSON conversion
117                }
118                if(!callback && typeof name === "function"){
119                        callback = name;
120                        name = "*";
121                }else{
122                        // prepend with dash to prevent name conflicts with function (like "name" property)
123                        name = '_' + name;
124                }
125                var propertyCallbacks = callbacks[name];
126                if(typeof propertyCallbacks !== "object"){
127                        propertyCallbacks = callbacks[name] = [];
128                }
129                propertyCallbacks.push(callback);
130                return {
131                        unwatch: function(){
132                                propertyCallbacks.splice(array.indexOf(propertyCallbacks, callback), 1);
133                        }
134                }; //Object
135        }
136
137});
138
139});
Note: See TracBrowser for help on using the repository browser.