summaryrefslogtreecommitdiff
path: root/lib/dojo/Stateful.js.uncompressed.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dojo/Stateful.js.uncompressed.js')
-rw-r--r--lib/dojo/Stateful.js.uncompressed.js213
1 files changed, 213 insertions, 0 deletions
diff --git a/lib/dojo/Stateful.js.uncompressed.js b/lib/dojo/Stateful.js.uncompressed.js
new file mode 100644
index 000000000..c445885fe
--- /dev/null
+++ b/lib/dojo/Stateful.js.uncompressed.js
@@ -0,0 +1,213 @@
+define("dojo/Stateful", ["./_base/declare", "./_base/lang", "./_base/array", "dojo/when"], function(declare, lang, array, when){
+ // module:
+ // dojo/Stateful
+
+return declare("dojo.Stateful", null, {
+ // summary:
+ // Base class for objects that provide named properties with optional getter/setter
+ // control and the ability to watch for property changes
+ //
+ // The class also provides the functionality to auto-magically manage getters
+ // and setters for object attributes/properties.
+ //
+ // Getters and Setters should follow the format of _xxxGetter or _xxxSetter where
+ // the xxx is a name of the attribute to handle. So an attribute of "foo"
+ // would have a custom getter of _fooGetter and a custom setter of _fooSetter.
+ //
+ // example:
+ // | var obj = new dojo.Stateful();
+ // | obj.watch("foo", function(){
+ // | console.log("foo changed to " + this.get("foo"));
+ // | });
+ // | obj.set("foo","bar");
+
+ // _attrPairNames: Hash
+ // Used across all instances a hash to cache attribute names and their getter
+ // and setter names.
+ _attrPairNames: {},
+
+ _getAttrNames: function(name){
+ // summary:
+ // Helper function for get() and set().
+ // Caches attribute name values so we don't do the string ops every time.
+ // tags:
+ // private
+
+ var apn = this._attrPairNames;
+ if(apn[name]){ return apn[name]; }
+ return (apn[name] = {
+ s: "_" + name + "Setter",
+ g: "_" + name + "Getter"
+ });
+ },
+
+ postscript: function(/*Object?*/ params){
+ // Automatic setting of params during construction
+ if (params){ this.set(params); }
+ },
+
+ _get: function(name, names){
+ // summary:
+ // Private function that does a get based off a hash of names
+ // names:
+ // Hash of names of custom attributes
+ return typeof this[names.g] === "function" ? this[names.g]() : this[name];
+ },
+ get: function(/*String*/name){
+ // summary:
+ // Get a property on a Stateful instance.
+ // name:
+ // The property to get.
+ // returns:
+ // The property value on this Stateful instance.
+ // description:
+ // Get a named property on a Stateful object. The property may
+ // potentially be retrieved via a getter method in subclasses. In the base class
+ // this just retrieves the object's property.
+ // For example:
+ // | stateful = new dojo.Stateful({foo: 3});
+ // | stateful.get("foo") // returns 3
+ // | stateful.foo // returns 3
+
+ return this._get(name, this._getAttrNames(name)); //Any
+ },
+ set: function(/*String*/name, /*Object*/value){
+ // summary:
+ // Set a property on a Stateful instance
+ // name:
+ // The property to set.
+ // value:
+ // The value to set in the property.
+ // returns:
+ // The function returns this dojo.Stateful instance.
+ // description:
+ // Sets named properties on a stateful object and notifies any watchers of
+ // the property. A programmatic setter may be defined in subclasses.
+ // For example:
+ // | stateful = new dojo.Stateful();
+ // | stateful.watch(function(name, oldValue, value){
+ // | // this will be called on the set below
+ // | }
+ // | stateful.set(foo, 5);
+ //
+ // set() may also be called with a hash of name/value pairs, ex:
+ // | myObj.set({
+ // | foo: "Howdy",
+ // | bar: 3
+ // | })
+ // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
+
+ // If an object is used, iterate through object
+ if(typeof name === "object"){
+ for(var x in name){
+ if(name.hasOwnProperty(x) && x !="_watchCallbacks"){
+ this.set(x, name[x]);
+ }
+ }
+ return this;
+ }
+
+ var names = this._getAttrNames(name),
+ oldValue = this._get(name, names),
+ setter = this[names.s],
+ result;
+ if(typeof setter === "function"){
+ // use the explicit setter
+ result = setter.apply(this, Array.prototype.slice.call(arguments, 1));
+ }else{
+ // no setter so set attribute directly
+ this[name] = value;
+ }
+ if(this._watchCallbacks){
+ var self = this;
+ // If setter returned a promise, wait for it to complete, otherwise call watches immediatly
+ when(result, function(){
+ self._watchCallbacks(name, oldValue, value);
+ });
+ }
+ return this; // dojo/Stateful
+ },
+ _changeAttrValue: function(name, value){
+ // summary:
+ // Internal helper for directly changing an attribute value.
+ //
+ // name: String
+ // The property to set.
+ // value: Mixed
+ // The value to set in the property.
+ //
+ // description:
+ // Directly change the value of an attribute on an object, bypassing any
+ // accessor setter. Also handles the calling of watch and emitting events.
+ // It is designed to be used by descendent class when there are two values
+ // of attributes that are linked, but calling .set() is not appropriate.
+
+ var oldValue = this.get(name);
+ this[name] = value;
+ if(this._watchCallbacks){
+ this._watchCallbacks(name, oldValue, value);
+ }
+ return this; // dojo/Stateful
+ },
+ watch: function(/*String?*/name, /*Function*/callback){
+ // summary:
+ // Watches a property for changes
+ // name:
+ // Indicates the property to watch. This is optional (the callback may be the
+ // only parameter), and if omitted, all the properties will be watched
+ // returns:
+ // An object handle for the watch. The unwatch method of this object
+ // can be used to discontinue watching this property:
+ // | var watchHandle = obj.watch("foo", callback);
+ // | watchHandle.unwatch(); // callback won't be called now
+ // callback:
+ // The function to execute when the property changes. This will be called after
+ // the property has been changed. The callback will be called with the |this|
+ // set to the instance, the first argument as the name of the property, the
+ // second argument as the old value and the third argument as the new value.
+
+ var callbacks = this._watchCallbacks;
+ if(!callbacks){
+ var self = this;
+ callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
+ var notify = function(propertyCallbacks){
+ if(propertyCallbacks){
+ propertyCallbacks = propertyCallbacks.slice();
+ for(var i = 0, l = propertyCallbacks.length; i < l; i++){
+ propertyCallbacks[i].call(self, name, oldValue, value);
+ }
+ }
+ };
+ notify(callbacks['_' + name]);
+ if(!ignoreCatchall){
+ notify(callbacks["*"]); // the catch-all
+ }
+ }; // we use a function instead of an object so it will be ignored by JSON conversion
+ }
+ if(!callback && typeof name === "function"){
+ callback = name;
+ name = "*";
+ }else{
+ // prepend with dash to prevent name conflicts with function (like "name" property)
+ name = '_' + name;
+ }
+ var propertyCallbacks = callbacks[name];
+ if(typeof propertyCallbacks !== "object"){
+ propertyCallbacks = callbacks[name] = [];
+ }
+ propertyCallbacks.push(callback);
+
+ // TODO: Remove unwatch in 2.0
+ var handle = {};
+ handle.unwatch = handle.remove = function(){
+ var index = array.indexOf(propertyCallbacks, callback);
+ if(index > -1){
+ propertyCallbacks.splice(index, 1);
+ }
+ };
+ return handle; //Object
+ }
+
+});
+
+});