]> git.wh0rd.org - tt-rss.git/blob - lib/dojo/Stateful.js.uncompressed.js
modify dojo rebuild script to remove uncompressed files
[tt-rss.git] / lib / dojo / Stateful.js.uncompressed.js
1 define("dojo/Stateful", ["./_base/declare", "./_base/lang", "./_base/array", "dojo/when"], function(declare, lang, array, when){
2 // module:
3 // dojo/Stateful
4
5 return declare("dojo.Stateful", null, {
6 // summary:
7 // Base class for objects that provide named properties with optional getter/setter
8 // control and the ability to watch for property changes
9 //
10 // The class also provides the functionality to auto-magically manage getters
11 // and setters for object attributes/properties.
12 //
13 // Getters and Setters should follow the format of _xxxGetter or _xxxSetter where
14 // the xxx is a name of the attribute to handle. So an attribute of "foo"
15 // would have a custom getter of _fooGetter and a custom setter of _fooSetter.
16 //
17 // example:
18 // | var obj = new dojo.Stateful();
19 // | obj.watch("foo", function(){
20 // | console.log("foo changed to " + this.get("foo"));
21 // | });
22 // | obj.set("foo","bar");
23
24 // _attrPairNames: Hash
25 // Used across all instances a hash to cache attribute names and their getter
26 // and setter names.
27 _attrPairNames: {},
28
29 _getAttrNames: function(name){
30 // summary:
31 // Helper function for get() and set().
32 // Caches attribute name values so we don't do the string ops every time.
33 // tags:
34 // private
35
36 var apn = this._attrPairNames;
37 if(apn[name]){ return apn[name]; }
38 return (apn[name] = {
39 s: "_" + name + "Setter",
40 g: "_" + name + "Getter"
41 });
42 },
43
44 postscript: function(/*Object?*/ params){
45 // Automatic setting of params during construction
46 if (params){ this.set(params); }
47 },
48
49 _get: function(name, names){
50 // summary:
51 // Private function that does a get based off a hash of names
52 // names:
53 // Hash of names of custom attributes
54 return typeof this[names.g] === "function" ? this[names.g]() : this[name];
55 },
56 get: function(/*String*/name){
57 // summary:
58 // Get a property on a Stateful instance.
59 // name:
60 // The property to get.
61 // returns:
62 // The property value on this Stateful instance.
63 // description:
64 // Get a named property on a Stateful object. The property may
65 // potentially be retrieved via a getter method in subclasses. In the base class
66 // this just retrieves the object's property.
67 // For example:
68 // | stateful = new dojo.Stateful({foo: 3});
69 // | stateful.get("foo") // returns 3
70 // | stateful.foo // returns 3
71
72 return this._get(name, this._getAttrNames(name)); //Any
73 },
74 set: function(/*String*/name, /*Object*/value){
75 // summary:
76 // Set a property on a Stateful instance
77 // name:
78 // The property to set.
79 // value:
80 // The value to set in the property.
81 // returns:
82 // The function returns this dojo.Stateful instance.
83 // description:
84 // Sets named properties on a stateful object and notifies any watchers of
85 // the property. A programmatic setter may be defined in subclasses.
86 // For example:
87 // | stateful = new dojo.Stateful();
88 // | stateful.watch(function(name, oldValue, value){
89 // | // this will be called on the set below
90 // | }
91 // | stateful.set(foo, 5);
92 //
93 // set() may also be called with a hash of name/value pairs, ex:
94 // | myObj.set({
95 // | foo: "Howdy",
96 // | bar: 3
97 // | })
98 // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
99
100 // If an object is used, iterate through object
101 if(typeof name === "object"){
102 for(var x in name){
103 if(name.hasOwnProperty(x) && x !="_watchCallbacks"){
104 this.set(x, name[x]);
105 }
106 }
107 return this;
108 }
109
110 var names = this._getAttrNames(name),
111 oldValue = this._get(name, names),
112 setter = this[names.s],
113 result;
114 if(typeof setter === "function"){
115 // use the explicit setter
116 result = setter.apply(this, Array.prototype.slice.call(arguments, 1));
117 }else{
118 // no setter so set attribute directly
119 this[name] = value;
120 }
121 if(this._watchCallbacks){
122 var self = this;
123 // If setter returned a promise, wait for it to complete, otherwise call watches immediatly
124 when(result, function(){
125 self._watchCallbacks(name, oldValue, value);
126 });
127 }
128 return this; // dojo/Stateful
129 },
130 _changeAttrValue: function(name, value){
131 // summary:
132 // Internal helper for directly changing an attribute value.
133 //
134 // name: String
135 // The property to set.
136 // value: Mixed
137 // The value to set in the property.
138 //
139 // description:
140 // Directly change the value of an attribute on an object, bypassing any
141 // accessor setter. Also handles the calling of watch and emitting events.
142 // It is designed to be used by descendent class when there are two values
143 // of attributes that are linked, but calling .set() is not appropriate.
144
145 var oldValue = this.get(name);
146 this[name] = value;
147 if(this._watchCallbacks){
148 this._watchCallbacks(name, oldValue, value);
149 }
150 return this; // dojo/Stateful
151 },
152 watch: function(/*String?*/name, /*Function*/callback){
153 // summary:
154 // Watches a property for changes
155 // name:
156 // Indicates the property to watch. This is optional (the callback may be the
157 // only parameter), and if omitted, all the properties will be watched
158 // returns:
159 // An object handle for the watch. The unwatch method of this object
160 // can be used to discontinue watching this property:
161 // | var watchHandle = obj.watch("foo", callback);
162 // | watchHandle.unwatch(); // callback won't be called now
163 // callback:
164 // The function to execute when the property changes. This will be called after
165 // the property has been changed. The callback will be called with the |this|
166 // set to the instance, the first argument as the name of the property, the
167 // second argument as the old value and the third argument as the new value.
168
169 var callbacks = this._watchCallbacks;
170 if(!callbacks){
171 var self = this;
172 callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
173 var notify = function(propertyCallbacks){
174 if(propertyCallbacks){
175 propertyCallbacks = propertyCallbacks.slice();
176 for(var i = 0, l = propertyCallbacks.length; i < l; i++){
177 propertyCallbacks[i].call(self, name, oldValue, value);
178 }
179 }
180 };
181 notify(callbacks['_' + name]);
182 if(!ignoreCatchall){
183 notify(callbacks["*"]); // the catch-all
184 }
185 }; // we use a function instead of an object so it will be ignored by JSON conversion
186 }
187 if(!callback && typeof name === "function"){
188 callback = name;
189 name = "*";
190 }else{
191 // prepend with dash to prevent name conflicts with function (like "name" property)
192 name = '_' + name;
193 }
194 var propertyCallbacks = callbacks[name];
195 if(typeof propertyCallbacks !== "object"){
196 propertyCallbacks = callbacks[name] = [];
197 }
198 propertyCallbacks.push(callback);
199
200 // TODO: Remove unwatch in 2.0
201 var handle = {};
202 handle.unwatch = handle.remove = function(){
203 var index = array.indexOf(propertyCallbacks, callback);
204 if(index > -1){
205 propertyCallbacks.splice(index, 1);
206 }
207 };
208 return handle; //Object
209 }
210
211 });
212
213 });