Yahoo! UI Library

Container 2.3.0

(function(){/** * Config is a utility used within an Object to allow the implementer to * maintain a list of local configuration properties and listen for changes * to those properties dynamically using CustomEvent. The initial values are * also maintained so that the configuration can be reset at any given point * to its initial state. * @namespace YAHOO.util * @class Config * @constructor * @param {Object} owner The owner Object to which this Config Object belongs */YAHOO.util.Config=function(owner){if(owner){this.init(owner);}if(!owner){YAHOO.log("No owner specified for Config object","error");}};varLang=YAHOO.lang,CustomEvent=YAHOO.util.CustomEvent,Config=YAHOO.util.Config;/** * Constant representing the CustomEvent type for the config changed event. * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT * @private * @static * @final */Config.CONFIG_CHANGED_EVENT="configChanged";/** * Constant representing the boolean type string * @property YAHOO.util.Config.BOOLEAN_TYPE * @private * @static * @final */Config.BOOLEAN_TYPE="boolean";Config.prototype={/** * Object reference to the owner of this Config Object * @property owner * @type Object */owner:null,/** * Boolean flag that specifies whether a queue is currently * being executed * @property queueInProgress * @type Boolean */queueInProgress:false,/** * Maintains the local collection of configuration property objects and * their specified values * @property config * @private * @type Object */config:null,/** * Maintains the local collection of configuration property objects as * they were initially applied. * This object is used when resetting a property. * @property initialConfig * @private * @type Object */initialConfig:null,/** * Maintains the local, normalized CustomEvent queue * @property eventQueue * @private * @type Object */eventQueue:null,/** * Custom Event, notifying subscribers when Config properties are set * (setProperty is called without the silent flag * @event configChangedEvent */configChangedEvent:null,/** * Initializes the configuration Object and all of its local members. * @method init * @param {Object} owner The owner Object to which this Config * Object belongs */init:function(owner){this.owner=owner;this.configChangedEvent=this.createEvent(Config.CONFIG_CHANGED_EVENT);this.configChangedEvent.signature=CustomEvent.LIST;this.queueInProgress=false;this.config={};this.initialConfig={};this.eventQueue=[];},/** * Validates that the value passed in is a Boolean. * @method checkBoolean * @param {Object} val The value to validate * @return {Boolean} true, if the value is valid */checkBoolean:function(val){return(typeofval==Config.BOOLEAN_TYPE);},/** * Validates that the value passed in is a number. * @method checkNumber * @param {Object} val The value to validate * @return {Boolean} true, if the value is valid */checkNumber:function(val){return(!isNaN(val));},/** * Fires a configuration property event using the specified value. * @method fireEvent * @private * @param {String} key The configuration property's name * @param {value} Object The value of the correct type for the property */fireEvent:function(key,value){YAHOO.log("Firing Config event: "+key+"="+value,"info");varproperty=this.config[key];if(property&&property.event){property.event.fire(value);}},/** * Adds a property to the Config Object's private config hash. * @method addProperty * @param {String} key The configuration property's name * @param {Object} propertyObject The Object containing all of this * property's arguments */addProperty:function(key,propertyObject){key=key.toLowerCase();YAHOO.log("Added property: "+key,"info");this.config[key]=propertyObject;propertyObject.event=this.createEvent(key,{scope:this.owner});propertyObject.event.signature=CustomEvent.LIST;propertyObject.key=key;if(propertyObject.handler){propertyObject.event.subscribe(propertyObject.handler,this.owner);}this.setProperty(key,propertyObject.value,true);if(!propertyObject.suppressEvent){this.queueProperty(key,propertyObject.value);}},/** * Returns a key-value configuration map of the values currently set in * the Config Object. * @method getConfig * @return {Object} The current config, represented in a key-value map */getConfig:function(){varcfg={},prop,property;for(propinthis.config){property=this.config[prop];if(property&&property.event){cfg[prop]=property.value;}}returncfg;},/** * Returns the value of specified property. * @method getProperty * @param {String} key The name of the property * @return {Object} The value of the specified property */getProperty:function(key){varproperty=this.config[key.toLowerCase()];if(property&&property.event){returnproperty.value;}else{returnundefined;}},/** * Resets the specified property's value to its initial value. * @method resetProperty * @param {String} key The name of the property * @return {Boolean} True is the property was reset, false if not */resetProperty:function(key){key=key.toLowerCase();varproperty=this.config[key];if(property&&property.event){if(this.initialConfig[key]&&!Lang.isUndefined(this.initialConfig[key])){this.setProperty(key,this.initialConfig[key]);returntrue;}}else{returnfalse;}},/** * Sets the value of a property. If the silent property is passed as * true, the property's event will not be fired. * @method setProperty * @param {String} key The name of the property * @param {String} value The value to set the property to * @param {Boolean} silent Whether the value should be set silently, * without firing the property event. * @return {Boolean} True, if the set was successful, false if it failed. */setProperty:function(key,value,silent){varproperty;key=key.toLowerCase();YAHOO.log("setProperty: "+key+"="+value,"info");if(this.queueInProgress&&!silent){// Currently running through a queue... this.queueProperty(key,value);returntrue;}else{property=this.config[key];if(property&&property.event){if(property.validator&&!property.validator(value)){returnfalse;}else{property.value=value;if(!silent){this.fireEvent(key,value);this.configChangedEvent.fire([key,value]);}returntrue;}}else{returnfalse;}}},/** * Sets the value of a property and queues its event to execute. If the * event is already scheduled to execute, it is * moved from its current position to the end of the queue. * @method queueProperty * @param {String} key The name of the property * @param {String} value The value to set the property to * @return {Boolean} true, if the set was successful, false if * it failed. */queueProperty:function(key,value){key=key.toLowerCase();YAHOO.log("queueProperty: "+key+"="+value,"info");varproperty=this.config[key],foundDuplicate=false,iLen,queueItem,queueItemKey,queueItemValue,sLen,supercedesCheck,qLen,queueItemCheck,queueItemCheckKey,queueItemCheckValue,i,s,q;if(property&&property.event){if(!Lang.isUndefined(value)&&property.validator&&!property.validator(value)){// validatorreturnfalse;}else{if(!Lang.isUndefined(value)){property.value=value;}else{value=property.value;}foundDuplicate=false;iLen=this.eventQueue.length;for(i=0;i<iLen;i++){queueItem=this.eventQueue[i];if(queueItem){queueItemKey=queueItem[0];queueItemValue=queueItem[1];if(queueItemKey==key){/* found a dupe... push to end of queue, null current item, and break */this.eventQueue[i]=null;this.eventQueue.push([key,(!Lang.isUndefined(value)?value:queueItemValue)]);foundDuplicate=true;break;}}}// this is a refire, or a new property in the queueif(!foundDuplicate&&!Lang.isUndefined(value)){this.eventQueue.push([key,value]);}}if(property.supercedes){sLen=property.supercedes.length;for(s=0;s<sLen;s++){supercedesCheck=property.supercedes[s];qLen=this.eventQueue.length;for(q=0;q<qLen;q++){queueItemCheck=this.eventQueue[q];if(queueItemCheck){queueItemCheckKey=queueItemCheck[0];queueItemCheckValue=queueItemCheck[1];if(queueItemCheckKey==supercedesCheck.toLowerCase()){this.eventQueue.push([queueItemCheckKey,queueItemCheckValue]);this.eventQueue[q]=null;break;}}}}}YAHOO.log("Config event queue: "+this.outputEventQueue(),"info");returntrue;}else{returnfalse;}},/** * Fires the event for a property using the property's current value. * @method refireEvent * @param {String} key The name of the property */refireEvent:function(key){key=key.toLowerCase();varproperty=this.config[key];if(property&&property.event&&!Lang.isUndefined(property.value)){if(this.queueInProgress){this.queueProperty(key);}else{this.fireEvent(key,property.value);}}},/** * Applies a key-value Object literal to the configuration, replacing * any existing values, and queueing the property events. * Although the values will be set, fireQueue() must be called for their * associated events to execute. * @method applyConfig * @param {Object} userConfig The configuration Object literal * @param {Boolean} init When set to true, the initialConfig will * be set to the userConfig passed in, so that calling a reset will * reset the properties to the passed values. */applyConfig:function(userConfig,init){varsKey,oValue,oConfig;if(init){oConfig={};for(sKeyinuserConfig){if(Lang.hasOwnProperty(userConfig,sKey)){oConfig[sKey.toLowerCase()]=userConfig[sKey];}}this.initialConfig=oConfig;}for(sKeyinuserConfig){if(Lang.hasOwnProperty(userConfig,sKey)){this.queueProperty(sKey,userConfig[sKey]);}}},/** * Refires the events for all configuration properties using their * current values. * @method refresh */refresh:function(){varprop;for(propinthis.config){this.refireEvent(prop);}},/** * Fires the normalized list of queued property change events * @method fireQueue */fireQueue:function(){vari,queueItem,key,value,property;this.queueInProgress=true;for(i=0;i<this.eventQueue.length;i++){queueItem=this.eventQueue[i];if(queueItem){key=queueItem[0];value=queueItem[1];property=this.config[key];property.value=value;this.fireEvent(key,value);}}this.queueInProgress=false;this.eventQueue=[];},/** * Subscribes an external handler to the change event for any * given property. * @method subscribeToConfigEvent * @param {String} key The property name * @param {Function} handler The handler function to use subscribe to * the property's event * @param {Object} obj The Object to use for scoping the event handler * (see CustomEvent documentation) * @param {Boolean} override Optional. If true, will override "this" * within the handler to map to the scope Object passed into the method. * @return {Boolean} True, if the subscription was successful, * otherwise false. */subscribeToConfigEvent:function(key,handler,obj,override){varproperty=this.config[key.toLowerCase()];if(property&&property.event){if(!Config.alreadySubscribed(property.event,handler,obj)){property.event.subscribe(handler,obj,override);}returntrue;}else{returnfalse;}},/** * Unsubscribes an external handler from the change event for any * given property. * @method unsubscribeFromConfigEvent * @param {String} key The property name * @param {Function} handler The handler function to use subscribe to * the property's event * @param {Object} obj The Object to use for scoping the event * handler (see CustomEvent documentation) * @return {Boolean} True, if the unsubscription was successful, * otherwise false. */unsubscribeFromConfigEvent:function(key,handler,obj){varproperty=this.config[key.toLowerCase()];if(property&&property.event){returnproperty.event.unsubscribe(handler,obj);}else{returnfalse;}},/** * Returns a string representation of the Config object * @method toString * @return {String} The Config object in string format. */toString:function(){varoutput="Config";if(this.owner){output+=" ["+this.owner.toString()+"]";}returnoutput;},/** * Returns a string representation of the Config object's current * CustomEvent queue * @method outputEventQueue * @return {String} The string list of CustomEvents currently queued * for execution */outputEventQueue:function(){varoutput="",queueItem,q,nQueue=this.eventQueue.length;for(q=0;q<nQueue;q++){queueItem=this.eventQueue[q];if(queueItem){output+=queueItem[0]+"="+queueItem[1]+", ";}}returnoutput;},/** * Sets all properties to null, unsubscribes all listeners from each * property's change event and all listeners from the configChangedEvent. * @method destroy */destroy:function(){varoConfig=this.config,sProperty,oProperty;for(sPropertyinoConfig){if(Lang.hasOwnProperty(oConfig,sProperty)){oProperty=oConfig[sProperty];oProperty.event.unsubscribeAll();oProperty.event=null;}}this.configChangedEvent.unsubscribeAll();this.configChangedEvent=null;this.owner=null;this.config=null;this.initialConfig=null;this.eventQueue=null;}};/** * Checks to determine if a particular function/Object pair are already * subscribed to the specified CustomEvent * @method YAHOO.util.Config.alreadySubscribed * @static * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check * the subscriptions * @param {Function} fn The function to look for in the subscribers list * @param {Object} obj The execution scope Object for the subscription * @return {Boolean} true, if the function/Object pair is already subscribed * to the CustomEvent passed in */Config.alreadySubscribed=function(evt,fn,obj){varnSubscribers=evt.subscribers.length,subsc,i;if(nSubscribers>0){i=nSubscribers-1;do{subsc=evt.subscribers[i];if(subsc&&subsc.obj==obj&&subsc.fn==fn){returntrue;}}while(i--);}returnfalse;};YAHOO.lang.augmentProto(Config,YAHOO.util.EventProvider);}());