]>
git.wh0rd.org - tt-rss.git/blob - lib/dojo/Stateful.js.uncompressed.js
1 define("dojo/Stateful", ["./_base/declare", "./_base/lang", "./_base/array", "dojo/when"], function(declare
, lang
, array
, when
){
5 return declare("dojo.Stateful", null, {
7 // Base class for objects that provide named properties with optional getter/setter
8 // control and the ability to watch for property changes
10 // The class also provides the functionality to auto-magically manage getters
11 // and setters for object attributes/properties.
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.
18 // | var obj = new dojo.Stateful();
19 // | obj.watch("foo", function(){
20 // | console.log("foo changed to " + this.get("foo"));
22 // | obj.set("foo","bar");
24 // _attrPairNames: Hash
25 // Used across all instances a hash to cache attribute names and their getter
29 _getAttrNames: function(name
){
31 // Helper function for get() and set().
32 // Caches attribute name values so we don't do the string ops every time.
36 var apn
= this._attrPairNames
;
37 if(apn
[name
]){ return apn
[name
]; }
39 s
: "_" + name
+ "Setter",
40 g
: "_" + name
+ "Getter"
44 postscript: function(/*Object?*/ params
){
45 // Automatic setting of params during construction
46 if (params
){ this.set(params
); }
49 _get: function(name
, names
){
51 // Private function that does a get based off a hash of names
53 // Hash of names of custom attributes
54 return typeof this[names
.g
] === "function" ? this[names
.g
]() : this[name
];
56 get: function(/*String*/name
){
58 // Get a property on a Stateful instance.
60 // The property to get.
62 // The property value on this Stateful instance.
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.
68 // | stateful = new dojo.Stateful({foo: 3});
69 // | stateful.get("foo") // returns 3
70 // | stateful.foo // returns 3
72 return this._get(name
, this._getAttrNames(name
)); //Any
74 set: function(/*String*/name
, /*Object*/value
){
76 // Set a property on a Stateful instance
78 // The property to set.
80 // The value to set in the property.
82 // The function returns this dojo.Stateful instance.
84 // Sets named properties on a stateful object and notifies any watchers of
85 // the property. A programmatic setter may be defined in subclasses.
87 // | stateful = new dojo.Stateful();
88 // | stateful.watch(function(name, oldValue, value){
89 // | // this will be called on the set below
91 // | stateful.set(foo, 5);
93 // set() may also be called with a hash of name/value pairs, ex:
98 // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
100 // If an object is used, iterate through object
101 if(typeof name
=== "object"){
103 if(name
.hasOwnProperty(x
) && x
!="_watchCallbacks"){
104 this.set(x
, name
[x
]);
110 var names
= this._getAttrNames(name
),
111 oldValue
= this._get(name
, names
),
112 setter
= this[names
.s
],
114 if(typeof setter
=== "function"){
115 // use the explicit setter
116 result
= setter
.apply(this, Array
.prototype.slice
.call(arguments
, 1));
118 // no setter so set attribute directly
121 if(this._watchCallbacks
){
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
);
128 return this; // dojo/Stateful
130 _changeAttrValue: function(name
, value
){
132 // Internal helper for directly changing an attribute value.
135 // The property to set.
137 // The value to set in the property.
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.
145 var oldValue
= this.get(name
);
147 if(this._watchCallbacks
){
148 this._watchCallbacks(name
, oldValue
, value
);
150 return this; // dojo/Stateful
152 watch: function(/*String?*/name
, /*Function*/callback
){
154 // Watches a property for changes
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
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
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.
169 var callbacks
= this._watchCallbacks
;
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
);
181 notify(callbacks
['_' + name
]);
183 notify(callbacks
["*"]); // the catch-all
185 }; // we use a function instead of an object so it will be ignored by JSON conversion
187 if(!callback
&& typeof name
=== "function"){
191 // prepend with dash to prevent name conflicts with function (like "name" property)
194 var propertyCallbacks
= callbacks
[name
];
195 if(typeof propertyCallbacks
!== "object"){
196 propertyCallbacks
= callbacks
[name
] = [];
198 propertyCallbacks
.push(callback
);
200 // TODO: Remove unwatch in 2.0
202 handle
.unwatch
= handle
.remove = function(){
203 var index
= array
.indexOf(propertyCallbacks
, callback
);
205 propertyCallbacks
.splice(index
, 1);
208 return handle
; //Object