Page 1 of 2 12 LastLast
Results 1 to 10 of 16

Thread: Ext.ux.state.provider.OmniProvider w/ Direct

  1. #1
    Sencha User willf1976's Avatar
    Join Date
    May 2009
    Location
    carpinteria, ca
    Posts
    84
    Vote Rating
    0
      0  

    Talking Ext.ux.state.provider.OmniProvider w/ Direct

    Hi all


    I have made a new provider for state management that offers a much more robust feature set than anything I was able to find out there already.


    Key Features:
    Allows states to be saved with names so you can allow users to save and load presets for how they want their components to be configured.


    Allows states to be saved, loaded and copied between: cookies, ajax and ExtDirect (allows for remotely or locally saved states, or for any sort of hybrid of the above you would prefer to use).


    Allows batch saving and loading of states and direct control over when a state is saved or applied opening up more flexibility in how you interact with your state.
    I have attached some sample files to this for you to look over and see how the class works:
    omniProviderAjaxAndCookieHybred.html this file demonstrates saving and loading named states via ajax while the currently displayed state is saved locally in a cookie


    omniProviderAllDirect.html this file demonstrates using ExtDirect as your state provider

    To learn how to use the class please look over the documentation in the class please read over the comments relating to events, public properties, and public functions.

    Let me know any bugs you find or additional features you would like to see.

    Note: I have tested all the features in this class except for the "components" array that can be passed as an argument to certain functions. I haven't had need of this feature in any of my code yet. If you try out this feature and find any bugs please let me know.

    Below is the code for class:


    HTML Code:
    /*
    author: Will Ferrer
    date: 08/03/09
    history:
      07/27/09 -- posted to ExtJS forums
      08/03/09 -- fixed a minor typo in the code documentation, changed accidental references to Ext.state.CookieProvider to Ext.ux.state.provider.OmniProvider
    */
    /**
     * @class Ext.ux.state.provider.OmniProvider
     * @extends Ext.state.Provider
     * A class that greatly extends the capabilities of  Ext.state.Provider to allow it to handle multiple named states, multiple types of state sources and a great many other enhancements to the class.
     * @constructor
     * @param {Object} config The config object
     * @xtype ux-state-provider-omniprovider
     */
    
    Ext.namespace("Ext.ux.state.provider");
    
    Ext.ux.state.provider.OmniProvider = function(config){
    //event 'statechange' is already included in Ext.state.Provider and will fire on: 'set' and 'clear'
    	Ext.apply(this, config);
    	Ext.ux.state.provider.OmniProvider.superclass.constructor.call(this);
    	this.addEvents(
    		/**
    		 * @event beforereadstate
    		 * Fires right before the readState function is run
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} stateGroupId
    		 * @param {Boolean} triggerApplyAll
    		 * @param {String} sourceType
    		 * @param {Array} components
    		 * @param {Object} extra
    		 */
    		'beforereadstate',
    		/**
    		 * @event beforeupdatestate
    		 * Fires right before the updateState function is run
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {Object} state
    		 * @param {String} stateGroupId
    		 * @param {String} sourceType
    		 * @param {Object} extra
    		 */
    		'beforeupdatestate',
    		/**
    		 * @event beforedestroystate
    		 * Fires right before the destroyState function is run
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {Array} stateNames
    		 * @param {String} stateGroupId
    		 * @param {String} sourceType
    		 * @param {Object} extra
    		 */
    		'beforedestroystate',
    		/**
    		 * @event beforecopystate
    		 * Fires right before the copyState function is run
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} fromSourceType
    		 * @param {String} toSourceType
    		 * @param {String} stateGroupId
    		 * @param {String} newStateGroupId
    		 */
    		'beforecopystate',
    		/**
    		 * @event beforeapplyall
    		 * Fires right before the applyAll function is run
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} stateGroupId
    		 * @param {Array} components
    		 */
    		'beforeapplyall',
    		/**
    		 * @event beforesaveall
    		 * Fires right before the saveAll function is run
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} stateGroupId
    		 * @param {Array} components
    		 */
    		'beforesaveall',
    		/**
    		 * @event readstatesuccess
    		 * Fires when a state has been read into the provider.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} sourceType
    		 * @param {String} stateGroupId
    		 * @param {Boolean} triggerApplyAll
    		 * @param {Array} components
    		 * @param {Object} extra
    		 */
    		'readstatesuccess',
    		/**
    		 * @event updatestatesuccess
    		 * Fires when a state has been updated.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} sourceType
    		 * @param {Object} state
    		 * @param {String} stateGroupId
    		 * @param {Object} extra
    		 */
    		'updatestatesuccess',
    		/**
    		 * @event destroystatesuccess
    		 * Fires when a state has been destroyed.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} sourceType
    		 * @param {Object} stateNames
    		 * @param {String} stateGroupId
    		 * @param {Object} extra
    		 */
    		'destroystatesuccess',
    		/**
    		 * @event copystatereadsuccess
    		 * Fires when a state has been read into the provider and is about to be coppied.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {Object} copyStateSettings
    		 */
    		'copystatereadsuccess',
    		/**
    		 * @event copystateupdatesuccess
    		 * Fires when the copy state process completes.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {Object} copyStateSettings
    		 */
    		'copystateupdatesuccess',
    		/**
    		 * @event applyallsuccess
    		 * Fires when applyAll function has completed.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} stateGroupId
    		 * @param {Array} components
    		 */
    		'applyallsuccess',
    		/**
    		 * @event saveallsuccess
    		 * Fires when saveAll function has completed.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} stateGroupId
    		 * @param {Array} components
    		 */
    		'saveallsuccess',
    		/**
    		 * @event readstatefailure
    		 * Fires when readState has failed.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} sourceType
    		 * @param {Object} e
    		 * @param {Object} Response
    		 * @param {String} stateGroupId
    		 * @param {Boolean} triggerApplyAll
    		 * @param {Array} components
    		 * @param {Object} extra
    		 */
    		'readstatefailure',
    		/**
    		 * @event updatestatefailure
    		 * Fires when updateState has failed.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} sourceType
    		 * @param {Object} e
    		 * @param {Object} Response
    		 * @param {String} stateGroupId
    		 * @param {Object} extra
    		 */
    		'updatestatefailure',
    		/**
    		 * @event destroystatefailure
    		 * Fires when destroyState has failed.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {String} sourceType
    		 * @param {Object} e
    		 * @param {Object} Response
    		 * @param {Array} stateNames
    		 * @param {String} stateGroupId
    		 * @param {Object} extra
    		 */
    		'destroystatefailure',
    		/**
    		 * @event copystatereadfailure
    		 * Fires when copyState has failed during it's read operation.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {Object} copyStateSettings
    		 */
    		'copystatereadfailure',
    		/**
    		 * @event copystateupdatefailure
    		 * Fires when copyState has failed during it's update operation.
    		 * @param {Ext.ux.state.provider.OmniProvider} this
    		 * @param {Object} copyStateSettings
    		 */
    		'copystateupdatefailure'
    	);
    	
    //These listeners are used to allow the copyState function to complete it's opperation:	
    	this.on('readstatesuccess', function () {
    		var extra = arguments[arguments.length-1];
    		var copyStateSettings = (extra && extra.copyStateSettings)?extra.copyStateSettings:null;
    		if (copyStateSettings) {
    			this.fireEvent("copystatereadsuccess", this, copyStateSettings);
    			var updateStateGroupId = (copyStateSettings.newStateGroupId)?copyStateSettings.newStateGroupId:this.stateGroupId;
    			this.updateState(this.tempState, updateStateGroupId, copyStateSettings.toSourceType, extra);
    			this.tempState = {};
    		}
    	}, this);
    
    	this.on('readstatefailure', function () {
    		var extra = arguments[arguments.length-1];
    		var copyStateSettings = (extra && extra.copyStateSettings)?extra.copyStateSettings:null;
    		if (copyStateSettings) {
    			this.fireEvent("copystatereadfailure", this, copyStateSettings);
    			this.tempState = {};
    		}
    	}, this);
    	
    	this.on('updatestatesuccess', function () {
    		var extra = arguments[arguments.length-1];
    		var copyStateSettings = (extra && extra.copyStateSettings)?extra.copyStateSettings:null;
    		if (copyStateSettings) {
    			this.fireEvent("copystateupdatesuccess", this, copyStateSettings);
    			this.tempState = {};
    		}
    	}, this);
    	
    	this.on('updatestatefailure', function () {
    		var extra = arguments[arguments.length-1];
    		var copyStateSettings = (extra && extra.copyStateSettings)?extra.copyStateSettings:null;
    		if (copyStateSettings) {
    			this.fireEvent("copystateupdatefailure", this, copyStateSettings);
    			this.tempState = {};
    		}
    	}, this);
    	
    	if (this.autoReadStateOnConstruct) {
    		this.readState();
    	}
    
    };
    Ext.extend(Ext.ux.state.provider.OmniProvider, Ext.state.Provider, {
    //Public Properties:
    	/**
        * @cfg {Boolean} debug
        * whether or not to use console.log to log failed connection attemps and other errors (defaults to true).
    	* 
    	*/
    	debug : true,
    	/**
        * @cfg {String} sourceType
        * the source used for states -- may be 'cookie' (uses modified version of Ext.state.CookieProvider code), 'ajax' (uses ajax request with data formated as json), 'direct' (uses api for ExtDirect) (defaults to 'cookie').
    	* 
    	*/
    	sourceType : 'cookie',
    	/**
        * @cfg {Boolean} protectState
        * protect the currently loaded state so that other functions that attempt to directly alter or delete it are defeated -- I added this feature because several components will try to modify or delete elements of the state and in some circumstances this can cause problems  (defaults to false).
    	* 
    	*/
    	protectState : false,
    	/**
        * @cfg {Mixed} stateGroupId
        * allows you to save configurations of multiple components in a 'set'. This will allow for multiple state configurations to saved and retrieved as part of a group (defaults to null).
    	* 
    	*/
    	stateGroupId : null,
    	/**
        * @cfg {Boolean} autoSaveState
        * may be set to false in order to prevent components from saving their own state configurations -- set this to false when you want a state to be saved manually or by another function (defaults to true).
    	* 
    	*/
    	autoSaveState : true,
    	/**
        * @cfg {Boolean} autoGiveStateOnGet
        * may be set to false in order to prevent components from applying their own state configurations -- set this to false when you want a state to be applied manually or by another function (defaults to true).
    	* 
    	*/
    	autoGiveStateOnGet : true,
    	/**
        * @cfg {Boolean} autoReadStateOnGet
        * whether or not to repload the state each time a get request comes in from a component -- seldom used feature (defaults to false).
    	* 
    	*/
    	autoReadStateOnGet : false,
    	/**
        * @cfg {Boolean} autoReadStateOnConstruct
        * whether or not to read the state into memory when provider is constructed (defaults to true).
    	* 
    	*/
    	autoReadStateOnConstruct : true,
    	/**
        * @cfg {Object} cookieConfig
        * configurations used when saving and retrieving states from a cookie -- does not generaly need to be modified but may be used to overide the settings in defaultCookieConfig. Used when sourceType is set to 'cookie' (defaults to {}).
    	* 
    	*/
    	cookieConfig : {},
    	/**
        * @cfg {Object} api
        * An object containing referances to the functions to use when making ExtDirect calls to read, update and destroy the state (generally created using Ext.Direct.addProvider). The functions must connect to remote functions that do the following:
    	* read($stateGroupId, $triggerApplyAll, $components, $extra) -- remote function must return: {success : [boolean], result : [state_object]}
    	* update($state, $stateGroupId, $extra) -- remote function must return: {success : [boolean], result : [message]}
    	* destroy($stateNames, $stateGroupId, $extra) -- remote function must return: {success : [boolean], result : [message]}
    	*/
    	api : {
    		read : null,
    		update : null,
    		destroy : null
    	},
    	/**
        * @cfg {Object} ajaxConfig
        * configuration for ajax calls to read, update and destroy the state. Generally you will only need to define the 'url' properties but other things may be set on this configuration as well. omniProvider will make the following calls to your ajax script:
    	* action='read'&components=[json_encoded_array_of_components]&stateGroupId=[stateGroupId] -- remote function must return json encoded: {success : [boolean], result : [state_object]}
    	* action='update'&stateGroupId=[stateGroupId]&state=[json_encoded_state_object] -- remote function must return json encoded: {success : [boolean], result : [message]}
    	* action='destroy'&stateGroupId=[stateGroupId]&stateNames=[json_encoded_array_of_state_names] -- remote function must return json encoded: {success : [boolean], result : [message]}
    	*/
    	ajaxConfig : {
    		url: null
    	},
    // Private Properties:
    	/**
        * @private internal config {Object} specialCaseGetState
        * flag used when all components are instructed to restore their state via the applyAll function.
    	* 
    	*/
    	specialCaseGetState : false,
    	/**
        * @private internal config {Object} specialCaseSetState
        * flag used when all components are instructed to save their state via the saveAll function.
    	* 
    	*/
    	specialCaseSetState : false,
    	/**
        * @private internal config {Object} tempSaveState
        * used when a batch save takes place (via the saveAll function) to record all the state info to save.
    	* 
    	*/
    	tempSaveState : {},
    	/**
        * @private internal config {Object} tempClearStateNames
        * used when a batch save takes place to record all the state info to clear.
    	* 
    	*/
    	tempClearStateNames : [],
    	/**
        * @private internal config {Object} tempState
        * used when a copyState function is called to read the contents of a state into a property of the class with out overwriting the state property.
    	* 
    	*/
    	tempState : {},
    	/**
        * @private internal config {Object} state
        * State when object is instantiated, is over written when readState functions are called
    	* 
    	*/
    	state : {},
    	/**
        * @private internal config {Object} defaultStateGroupId
        * used to store what the stateGroupId is before performning batch operations.
    	* 
    	*/
    	defaultStateGroupId : '',
    	/**
        * @private internal config {Object} defaultCookieConfig
        * default config for cookieConfig -- over ridden by any values passed in with cookieConfig.
    	* 
    	*/
    	defaultCookieConfig : {
    		path : "/",
       		expires : new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days
    		domain : null,
    		secure : false
    	},
    	/**
        * @private internal config {Object} errorMessages
        * error messages that will be logged through the log function if debug is set to true.
    	* 
    	*/
    	errorMessages : {
    		ajaxCouldNoteDecodeJson : 'omniProviderError-Ajax: could not decode remote json data:',
    		ajaxImproperlyFormatedReturn : 'omniProviderError-Ajax: response from server improperly formated -- should be {success:[true_or_false], result:{[error_message_or_state_information]}}:',
    		ajaxServerReportedAnError : 'omniProviderError-Ajax: the server reported an error',
    		ajaxServerDidNotRespond : 'omniProviderError-Ajax: Did not receive a response from the server',
    		
    		directRead : 'omniProviderError-Direct: error with readStateDirect return data',
    		directUpdated : 'omniProviderError-Direct: error with updateStateDirect return data',
    		directDestroy : 'omniProviderError-Direct: error with destroyStateDirect return data'
    	},
    //Public Functions:
    	/** Public Function: readState
    	 * reads state into memory from either the sourceType defined for the class or from the sourceType passed to the function. This function routes to other functions depending on the sourceType
    	 * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different names. Defaults to this.this.stateGroupId.
    	 * @param {Boolean} triggerApplyAll (Optional) If set to true the applyAll function will be called after the readState function completes. Defaults to false.
    	 * @param {Mixed} sourceType (Optional) May be set to: 'cookie', 'ajax' or 'direct'. Overides the sourceType set for the class to all the function to read in the state from a different source. Defaults to null.
    	 * @param {Array} components (Optional) An array of component ids that may optionaly be passed in to cause just the states relating to these components to be loaded. Defaults to this.sourceType.
    	 * @param {Object} extra (Optional) Values that will be passed along with the requests to read the state -- this is used largely by the copyState functions. Defaults to null.
    	 * @return {Object} the state that was read by the function
    	 */
    	readState : function (stateGroupId, triggerApplyAll, sourceType, components, extra) {
    		var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
    		var triggerApplyAll = (typeof(triggerApplyAll)!='undefined')?triggerApplyAll:false;
    		var components = (typeof(components)!='undefined')?components:null;
    		var components = (typeof(components)=='string')?[components]:components;
    		var sourceType = (typeof(sourceType)!='undefined')?sourceType:this.sourceType;
    		var extra = (typeof(extra)!='undefined')?extra:null;
    		var stateHolder = (extra && extra.stateHolder)?extra.stateHolder:'state';
    		
    		this.fireEvent("beforereadstate", this, stateGroupId, triggerApplyAll, sourceType, components, extra);
    		
    		switch (sourceType) {
    			case 'cookie':
    				this.readCookies(stateGroupId, triggerApplyAll, components, extra);
    			break;
    			case 'ajax':
    				this.readAjax(stateGroupId, triggerApplyAll, components, extra);
    			break;
    			case 'direct':
    				this.readDirect(stateGroupId, triggerApplyAll, components, extra);
    			break;
    		}
    		
    		return this[stateHolder];
    	},
    	/** Public Function: updateState
    	 * saves the state passed to the function to the source of sourceType either set for the class or passed to the function. This function routes to other functions depending on the sourceType
    	 * @param {Object} state (Required) A state object to save
    	 * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different name. Defaults to this.stateGroupId.
    	 * @param {String} sourceType (Optional) May be set to: 'cookie', 'ajax' or 'direct'. Overides the sourceType set for the class to all the function to read in the state from a different source. Defaults to this.sourceType.
    	 * @param {Mixed} extra (Optional) Values that will be passed along with the requests to read the state -- this is used largely by the copyState functions. Defaults to null.
    	 * @return {Boolean} returns true
    	 */
    	updateState : function (state, stateGroupId, sourceType, extra) {
    		var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
    		var sourceType = (typeof(sourceType)!='undefined')?sourceType:this.sourceType;
    		var extra = (typeof(extra)!='undefined')?extra:null;
    		
    		this.fireEvent("beforeupdatestate", this, state, stateGroupId, sourceType, extra);
    		switch (sourceType) {
    			case 'cookie':
    				this.updateCookies(state, stateGroupId, extra);
    			break;
    			case 'ajax':
    				this.updateAjax(state, stateGroupId, extra);
    			break;
    			case 'direct':
    				this.updateDirect(state, stateGroupId, extra);
    			break;
    		}
    		return true;
    	},
    	/** Public Function: destroyState
    	 * destroys the states whose names are passed in stateNames from sourceType either set for the class or passed to the function. This function routes to other functions depending on the sourceType
    	 * @param {Array} stateNames (Required) An array of stateNames to destroy
    	 * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different name. Defaults to this.stateGroupId
    	 * @param {String} sourceType (Optional) May be set to: 'cookie', 'ajax' or 'direct'. Overides the sourceType set for the class to all the function to read in the state from a different source. Defaults to this.sourceType
    	 * @param {Mixed} extra (Optional) Values that will be passed along with the requests to read the state -- this is used largely by the copyState functions. Defaults to null.
    	 * @return {Boolean} returns true
    	 */
    	destroyState : function (stateNames, stateGroupId, sourceType, extra) {
    		var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
    		var sourceType = (typeof(sourceType)!='undefined')?sourceType:this.sourceType;
    		var extra = (typeof(extra)!='undefined')?extra:null;
    		var stateNames = (typeof(stateNames)!='string')?stateNames:[stateNames];
    		this.fireEvent("beforedestroystate", this, stateNames, stateGroupId, sourceType, extra);
    		
    		switch (sourceType) {
    			case 'cookie':
    				this.destroyCookies(stateNames, stateGroupId, extra);
    			break;
    			case 'ajax':
    				this.destroyAjax(stateNames, stateGroupId, extra);
    			break;
    			case 'direct':
    				this.destroyDirect(stateNames, stateGroupId, extra);
    			break;
    		}
    		return true;
    	},
    	/** Public Function: copyState
    	 * starts the process to read in a state from a source and then update it to another source.
    	 * @param {String} fromSourceType (Required) May be set to: 'cookie', 'ajax' or 'direct'. source from which to read.
    	 * @param {String} toSourceType (Required) May be set to: 'cookie', 'ajax' or 'direct'. sourceType to copy the state to.
    	 * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different name. Defaults to this.stateGroupId
    	 * @param {String} newStateGroupId (Optional) The new stateGroupId to copy the state you have read to. Defaults to this.stateGroupId
    	 * @return {Boolean} returns true
    	 */
    	copyState : function (fromSourceType, toSourceType, stateGroupId, newStateGroupId) {
    		var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
    		var newStateGroupId = (typeof(newStateGroupId)!='undefined')?newStateGroupId:this.stateGroupId;
    		
    		this.fireEvent("beforecopystate", this, fromSourceType, toSourceType, stateGroupId, newStateGroupId);
    		
    		var extra = {
    			copyStateSettings : 
    				{
    					stateGroupId : stateGroupId,
    					fromSourceType : fromSourceType,
    					newStateGroupId : newStateGroupId,
    					toSourceType : toSourceType
    				},
    			stateHolder : 'tempState'
    		};
    		this.readState(stateGroupId, false, fromSourceType, null, extra);
    		return true;
    	},
    	/** Public Function: applyAll
    	 * runs a batch process to call the initState function on stateful components
    	 * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different name. Defaults to this.stateGroupId;
    	 * @param {Mixed} components An array of component ids that may optionaly be passed in to cause just these components to run their initState function. Defaults to null.
    	 * @return {Boolean} returns true
    	 */
    	applyAll : function (stateGroupId, components) {
    		var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
    		var components = (typeof(components)!='undefined')?components:null;
    		var components = (typeof(components)=='string')?[components]:components;
    		
    		this.fireEvent("beforeapplyall", this, stateGroupId, components);
    		this.batch(stateGroupId, components,'specialCaseGetState', 'initState');
    		this.fireEvent("applyallsuccess", this, stateGroupId, components);
    		return true;
    	},
    	/** Public Function: saveAll
    	 * runs a batch process to call the saveState function on stateful components
    	 * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different name. Defaults to this.stateGroupId.
    	 * @param {Mixed} components (Optional) An array of component ids that may optionaly be passed in to cause just these components to run their saveState function. Defaults to null.
    	 * @return {Boolean} returns true
    	 */
    	saveAll : function (stateGroupId, components) {
    		var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
    		var components = (typeof(components)!='undefined')?components:null;
    		var components = (typeof(components)=='string')?[components]:components;
    		this.fireEvent("beforesaveall", this, stateGroupId, components);
    		this.batch(stateGroupId, components, 'specialCaseSetState', 'saveState');
    		
    		this.updateState(this.tempSaveState);
    		this.destroyState(this.tempClearStateNames);
    		
    		this.tempSaveState = {};
    		this.tempClearStateNames = [];
    		this.fireEvent("saveallsuccess", this, stateGroupId, components);
    		return true;
    	},
    	/** Public Function: get
    	 * modified standard get function called by the Ext.state.Manager when an component requests to read it's loaded state
    	 * @param {String} name (Required) The key name.
    	 * @param {Mixed} defaultValue (Optional) The default value to return if the key lookup does not match. Defaults to undefined.
    	 * @return {Mixed} The state data or null.
    	 */
    	get : function (name, defaultValue) {
    		if (this.autoReadStateOnGet) {
    			this.readState(this.stateGroupId, false, this.sourceType, [name]);
    		}
    		if (this.autoGiveStateOnGet || this.specialCaseGetState) {
    			if (this.protectState) {
    				var returnData = {};
    				var stateObj = typeof this.state[name] == "undefined" ?
    				defaultValue : this.state[name];
    				Ext.apply(returnData, stateObj);
    				return returnData;
    			} else {
    				return typeof this.state[name] == "undefined" ?
    				defaultValue : this.state[name];
    			}
    		} else {
    			return null;	
    		}
    	},
    	/** Public Function: set
    	 * modified standard set function called by the Ext.state.Manager when an component requests to set it's state
    	 * @param {String} name (Required) The key name.
         * @param {Mixed} value (Required) The state data.
    	 * @return {Boolean} returns true or false
    	 */
    	set : function (name, value) {
    		if (this.autoSaveState || this.specialCaseSetState) {
    			if(typeof value == "undefined" || value === null){
    				this.clear(name);
    				return;
    			}
    			if (this.specialCaseSetState) {
    				this.tempSaveState[name] = value;
    			} else {
    				var tempState = [];
    				tempState[name] = value;
    				this.updateState(tempState);
    				Ext.ux.state.provider.OmniProvider.superclass.set.call(this, name, value);
    			}
    			return true;
    		} else {
    			return false;
    		}
    		
    	},
    	/** Public Function: clear
    	 * modified standard clear function called by the Ext.state.Manager when an component requests to clear its
    	 * @param {String} name (Required) The key name.
    	 * @return {Boolean} true
    	 */
    	clear : function (name) {
    		if (this.specialCaseSetState) {
    			this.tempClearStateNames.push(name);
    		} else {
    			this.destroyState([name]);
    			Ext.ux.state.provider.OmniProvider.superclass.clear.call(this, name);
    		}
    		return true;
    	},
    //Private Functions:
    	// private
        readCookies : function(stateGroupId, triggerApplyAll, components, extra){
    		var stateHolder = (extra && extra.stateHolder)?extra.stateHolder:'state';
            var cookies = {};
            var c = document.cookie + ";";
            var re = /\s?(.*?)=(.*?);/g;
            var matches;
    		var regExString = "^ys\-" + stateGroupId + "\-";
    		var extraRegEx = (stateGroupId) ? new RegExp(regExString) : null;
    		
            while((matches = re.exec(c)) != null){
                var name = matches[1];
                var value = matches[2];
    			var nameFirst3 = name.substring(0,3);
    			var trimmedName = name.replace(extraRegEx, '');
    			var decodedValue = this.decodeValue(value);
                if(name && nameFirst3 == "ys-" && (!extraRegEx || extraRegEx.test(name)) && (!components || this.inArray(components, name))){
                    cookies[trimmedName] = decodedValue;
                }
            }
           	this[stateHolder] = cookies;
    		
    		this.fireEvent("readstatesuccess", this, 'cookie', stateGroupId, triggerApplyAll, components, extra);
    		if (triggerApplyAll) {
    			this.applyAll(stateGroupId, components);
    		}
        },
    	// private
    	updateCookies : function(state, stateGroupId, extra){
    		for (var obj in state) {
    			var curName = obj;
    			var curValue = state[obj];
    			this.updateCookie(stateGroupId, curName, curValue);
    		}
    		this.fireEvent("updatestatesuccess", this, 'cookie', state, stateGroupId, extra);
        },
        // private
        updateCookie : function(stateGroupId, name, value){
    		curCookieConfig = this.cookieConfig;
    		Ext.applyIf(curCookieConfig, this.defaultCookieConfig);
    		var nameExtra = (stateGroupId) ? stateGroupId + "-" : '';
    		var cookieName = "ys-"+ nameExtra + name;
    		var cookieValue = this.encodeValue(value) +
               ((curCookieConfig.expires == null) ? "" : ("; expires=" + curCookieConfig.expires.toGMTString())) +
               ((curCookieConfig.path == null) ? "" : ("; path=" + curCookieConfig.path)) +
               ((curCookieConfig.domain == null) ? "" : ("; domain=" + curCookieConfig.domain)) +
               ((curCookieConfig.secure == true) ? "; secure" : "");
    		   
            document.cookie = cookieName + "=" + cookieValue;
        },
    	// private
        destroyCookies : function(stateNames, stateGroupId, extra){
    		for (var n=0; n< stateNames.length; n++) {
    			var curName = stateNames[n];
    			this.destroyCookie(stateGroupId, curName);
    		}
    		this.fireEvent("destroystatesuccess", this, 'cookie', stateNames, stateGroupId, extra);
        },
        // private
        destroyCookie : function(stateGroupId, name){
    		curCookieConfig = this.cookieConfig;
    		Ext.applyIf(curCookieConfig, this.defaultCookieConfig);
    		var nameExtra = (stateGroupId) ? stateGroupId + "-" : '';
            document.cookie = "ys-" + nameExtra + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
               ((curCookieConfig.path == null) ? "" : ("; path=" + curCookieConfig.path)) +
               ((curCookieConfig.domain == null) ? "" : ("; domain=" + curCookieConfig.domain)) +
               ((curCookieConfig.secure == true) ? "; secure" : "");
        },
    	//private
    	readAjax : function (stateGroupId, triggerApplyAll, components, extra) {
    		var curAjax = this.ajaxConfig;
    		var componentsEncoded = (components)?Ext.encode(components):null;
    		curAjax.params  = {
    			action:'read',
    			components:componentsEncoded,
    			stateGroupId:stateGroupId
    		};
    		curAjax.triggerApplyAll = triggerApplyAll;
    		curAjax.extra = extra;
    		curAjax.components = components;
    		curAjax.stateGroupId = stateGroupId;
    		curAjax.success = this.onAjaxReadSuccess;
    		curAjax.failure = this.onAjaxReadFailure;
    		curAjax.scope = this;
    
    		Ext.Ajax.request(curAjax);
    	},
    	//private
    	onAjaxReadSuccess : function (response, options) {
    		var response = this.parseJSONReturn(response);
    		
    		var stateGroupId = options.stateGroupId;
    		var triggerApplyAll = options.triggerApplyAll;
    		var components = options.components;
    		var extra = options.extra;
    		
    		var success = response.success;
    		var stateHolder = (extra && extra.stateHolder)?extra.stateHolder:'state';
    
    		if (success) {
    			for (obj in response.result) {
    				response.result[obj] = Ext.decode(response.result[obj]);
    			}
    
    			this[stateHolder] = response.result;
    			this.fireEvent("readstatesuccess", this, 'ajax', stateGroupId, triggerApplyAll, components, extra);
    			if (triggerApplyAll) {
    				this.applyAll(stateGroupId, components);
    			}
    		} else {
    			this.fireEvent("readstatefailure", this, 'ajax', null, response, stateGroupId, triggerApplyAll, components, extra);
    			this.log(this.errorMessages.ajaxServerReportedAnError, 'onAjaxReadSuccess', this, 'ajax', response, stateGroupId, triggerApplyAll, components, extra);
    		}
    	},
    	//private
    	onAjaxReadFailure : function (e, options) {
    		var stateGroupId = options.stateGroupId;
    		var triggerApplyAll = options.triggerApplyAll;
    		var components = options.components;
    		var extra = options.extra;
    		this.fireEvent("readstatefailure", this, 'ajax', e, null, stateGroupId, triggerApplyAll, components, extra);
    		this.log(this.errorMessages.ajaxServerDidNotRespond, 'ajax', e, null, stateGroupId, triggerApplyAll, components, extra);
    	},
    	//private
    	updateAjax : function (state, stateGroupId, extra) {
    		var curAjax = this.ajaxConfig;
    	//The 'remove' function on the state obj screwed up the Ext.encode function so we make an object that doesn't have it:
    		var stateToEncode = {};
    		for (obj in state) {
    			if (obj != 'remove') {
    				stateToEncode[obj] = state[obj];
    			}
    		}
    		stateEncoded = Ext.encode(stateToEncode);
    
    		curAjax.params = {
    			action:'update',
    			state:stateEncoded,
    			stateGroupId:stateGroupId
    		};
    		curAjax.state = state;
    		curAjax.stateGroupId = stateGroupId;
    		curAjax.extra = extra;
    		curAjax.success = this.onAjaxUpdateSuccess;
    		curAjax.failure = this.onAjaxUpdateFailure;
    		curAjax.scope = this;
    		Ext.Ajax.request(curAjax);
    	},
    	//private
    	onAjaxUpdateSuccess : function (response, options) {
    		response = this.parseJSONReturn(response);
    		var success = response.success;
    		var state = options.state;
    		var stateGroupId = options.stateGroupId;
    		var extra = options.extra
    		
    		if (success) {
    			this.fireEvent("updatestatesuccess", this, 'ajax', state, stateGroupId, extra);	
    		} else {
    			this.fireEvent("updatestatefailure", this, 'ajax', null, response, state, stateGroupId, extra);
    			this.log(this.errorMessages.ajaxServerReportedAnError, 'onAjaxUpdateSuccess', this, 'ajax', null, response, state, stateGroupId, extra);
    		}
    	},
    	//private
    	onAjaxUpdateFailure : function (e, options) {
    		var state = options.state;
    		var stateGroupId = options.stateGroupId;
    		var extra = options.extra
    		this.fireEvent("updatestatefailure", this, 'ajax', e, null, state, stateGroupId, extra);
    		this.log(this.errorMessages.ajaxServerDidNotRespond, this, 'ajax', e, null, state, stateGroupId, extra);
    	},
    	//private
    	destroyAjax : function (stateNames, stateGroupId, extra) {
    		var curAjax = this.ajaxConfig;
    		var stateNamesEncoded = (stateNames)?Ext.encode(stateNames):null;
    		curAjax.params = {
    			action:'destroy',
    			stateNames:stateNamesEncoded,
    			stateGroupId:stateGroupId
    		};
    		curAjax.stateNames = stateNames;
    		curAjax.stateGroupId = stateGroupId;
    		curAjax.extra = extra;
    		curAjax.success = this.onAjaxDestroySuccess;
    		curAjax.failure = this.onAjaxDestroyFailure;
    		curAjax.scope = this;
    		Ext.Ajax.request(curAjax);
    	},
    	//private
    	onAjaxDestroySuccess : function (response, options) {
    		response = this.parseJSONReturn(response);
    		var stateNames = options.stateNames;
    		var stateGroupId = options.stateGroupId;
    		var extra = options.extra
    		
    		var success = response.success;
    		if (success) {
    			this.fireEvent("destroystatesuccess", this, 'ajax', stateNames, stateGroupId, extra);	
    		} else {
    			this.fireEvent("destroystatefailure", this, 'ajax', null, response, stateNames, stateGroupId, extra);
    			this.log(this.errorMessages.ajaxServerDidNotRespond, this, 'ajax', response, stateNames, stateGroupId, extra);
    		}
    	},
    	//private
    	onAjaxDestroyFailure : function (e, options) {
    		var stateNames = options.stateNames;
    		var stateGroupId = options.stateGroupId;
    		var extra = options.extra
    		
    		this.fireEvent("destroystatefailure", this, 'ajax', e, null, stateNames, stateGroupId, extra);
    		this.log(this.errorMessages.ajaxServerDidNotRespond, this, 'ajax', e, stateNames, stateGroupId, extra);
    	},
    	//private
    	readDirect : function (stateGroupId, triggerApplyAll, components, extra) {
    		this.api.read(stateGroupId, triggerApplyAll, components, extra, this.onDirectReadSuccess, this);
    	},
    	//private
    	onDirectReadSuccess : function(response, e){
    		var transaction = e.getTransaction();
    		var stateGroupId = transaction.args[0];
    		var triggerApplyAll = transaction.args[1];
    		var components = transaction.args[2];
    		var extra = transaction.args[3];
    		var stateHolder = (extra && extra.stateHolder)?extra.stateHolder:'state';
    		var success = response.success;
    		if (success) {
    			this[stateHolder] = response.result;
    			this.fireEvent("readstatesuccess", this, 'direct', stateGroupId, triggerApplyAll, components, extra);
    			if (triggerApplyAll) {
    				this.applyAll(stateGroupId, components);
    			}
    		} else {
    			this.fireEvent("readstatefailure", this, 'direct', e, response, stateGroupId, triggerApplyAll, components, extra);
    			this.log(this.errorMessages.directRead, 'onDirectReadSuccess', this, 'direct', e, stateGroupId, triggerApplyAll, components, extra);
    		}
    	},
    	//private
    	updateDirect : function (state, stateGroupId, extra) {
    		var stateToSend = {};
    		for (obj in state) {
    			if (obj != 'remove') {
    				stateToSend[obj] = state[obj];
    			}
    		}
    		this.api.update(stateToSend, stateGroupId, extra, this.onDirectUpdateSuccess, this);
    	},
    	//private
    	onDirectUpdateSuccess : function(response, e){
    		var transaction = e.getTransaction();
    		var state = transaction.args[0];
    		var stateGroupId = transaction.args[1];
    		var extra = transaction.args[2];
    		var success = response.success;
    
    		if (success) {
    			this.fireEvent("updatestatesuccess", this, 'direct', state, stateGroupId, extra);	
    		} else {
    			this.fireEvent("updatestatefailure", this, 'direct', e, response, state, stateGroupId, extra);
    			this.log(this.errorMessages.directUpdate, 'onDirectUpdateSuccess', this, 'direct', e, response, state, stateGroupId, extra);
    		}
    		
    	},
    	//private
    	destroyDirect : function (stateNames, stateGroupId, extra) {
    		this.api.destroy(stateNames, stateGroupId, extra, this.onDirectDestroySuccess, this);
    	},
    	//private
    	onDirectDestroySuccess : function(response, e){
    		var transaction = e.getTransaction();
    		var stateNames = transaction.args[0];
    		var stateGroupId = transaction.args[1];
    		var extra = transaction.args[2];
    		var success = response.success;
    		if (success) {
    			this.fireEvent("destroystatesuccess", this, 'direct', stateNames, stateGroupId, extra);
    		} else {
    			this.fireEvent("destroystatefailure", this, 'direct', e, response, stateNames, stateGroupId, extra);
    			this.log(this.errorMessages.directDestroy, 'onAjaxDestroySuccess', this, 'direct', e, stateNames, stateGroupId, extra);
    		}
    	},
    	//private
    	parseJSONReturn : function (response) {
    		try {
    			var result = Ext.decode(response.responseText);
    		} catch(e) {
    			this.log(this.errorMessages.ajaxCouldNoteDecodeJson, e, response, options, this);
    			return false;
    		}
    		if (typeof(result.success) == 'undefined' || typeof(result.result)== 'undefined') {
    			this.log(this.errorMessages.ajaxImproperlyFormatedReturn, response, options, this);
    			return false;
    		}
    		return result;
    	},
    	//private
    	batch : function (stateGroupId, components, flag, callFunction) {
    		this.defaultStateGroupId = this.stateGroupId;
    		this.stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
    		
    		this[flag] = true;
    		
    		var curComponents = (components)?components:Ext.ComponentMgr.all.items;
    
    		for (var n=0; n<curComponents.length; n++) {
    			var curComp = curComponents[n];
    			curComp = (typeof(curComp)=='string')?Ext.getCmp(curComp):curComp;
    			if (typeof(curComp.stateful !== false)) {
    				curComp[callFunction]();
    			}
    		}
    		
    		this[flag] = false;
    		this.stateGroupId = this.defaultStateGroupId;
    	},
    	//private
    	log : function() {
    		if (this.debug){ 
    			if(console) {
    				console.log.apply(console, arguments);
    			}
    		}
    	},
    	//private
    	inArray : function (array, value, caseSensitive) {
    		var i;
    		for (i=0; i < array.length; i++) {
    			// use === to check for Matches. ie., identical (===),
    			if(caseSensitive){ //performs match even the string is case sensitive
    				if (array[i].toLowerCase() == value.toLowerCase()) {
    					return true;
    				}
    			}else{
    				if (array[i] == value) {
    					return true;
    				}
    			}
    		}
    		return false;
    	}
    });
    Ext.reg('ux-state-provider-omniprovider', Ext.ux.state.provider.OmniProvider);
    Attached Files Attached Files

  2. #2
    Ext JS Premium Member
    Join Date
    Oct 2008
    Posts
    18
    Vote Rating
    1
      0  

    Default Thanks

    I just downloaded your extension and will start playing with it soon. If it works as expected, you will save me a whole lot of time.
    Thanks in advance. I will let you know what I find.

  3. #3
    Ext User
    Join Date
    Mar 2009
    Posts
    18
    Vote Rating
    0
      0  

    Default

    This seems great !

    I'll need this in a couple of weeks. I'll give you feedback as soon as I test it !

    Regards

  4. #4
    Sencha User willf1976's Avatar
    Join Date
    May 2009
    Location
    carpinteria, ca
    Posts
    84
    Vote Rating
    0
      0  

    Default Minor Update

    Hi All

    Many thanks to those Georgioa and lechenique for checking out the code. Looking forward to hearing what you guys find .

    I made a very minor revision today -- this literally does not change the functionality of the code at all but I fixed a few typos I found and figured I might as well post the updated version of the code:

    HTML Code:
    /*
    author: Will Ferrer
    date: 08/03/09
    history:
      07/27/09 -- posted to ExtJS forums
      08/03/09 -- fixed a minor typo in the code documentation, changed accidental references to Ext.state.CookieProvider to Ext.ux.state.provider.OmniProvider
    */
    /**
     * @class Ext.ux.state.provider.OmniProvider
     * @extends Ext.state.Provider
     * A class that greatly extends the capabilities of  Ext.state.Provider to allow it to handle multiple named states, multiple types of state sources and a great many other enhancements to the class.
     * @constructor
     * @param {Object} config The config object
     * @xtype ux-state-provider-omniprovider
     */
    
    Ext.namespace("Ext.ux.state.provider");
    
    Ext.ux.state.provider.OmniProvider = function(config){
    //event 'statechange' is already included in Ext.state.Provider and will fire on: 'set' and 'clear'
        Ext.apply(this, config);
        Ext.ux.state.provider.OmniProvider.superclass.constructor.call(this);
        this.addEvents(
            /**
             * @event beforereadstate
             * Fires right before the readState function is run
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} stateGroupId
             * @param {Boolean} triggerApplyAll
             * @param {String} sourceType
             * @param {Array} components
             * @param {Object} extra
             */
            'beforereadstate',
            /**
             * @event beforeupdatestate
             * Fires right before the updateState function is run
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {Object} state
             * @param {String} stateGroupId
             * @param {String} sourceType
             * @param {Object} extra
             */
            'beforeupdatestate',
            /**
             * @event beforedestroystate
             * Fires right before the destroyState function is run
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {Array} stateNames
             * @param {String} stateGroupId
             * @param {String} sourceType
             * @param {Object} extra
             */
            'beforedestroystate',
            /**
             * @event beforecopystate
             * Fires right before the copyState function is run
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} fromSourceType
             * @param {String} toSourceType
             * @param {String} stateGroupId
             * @param {String} newStateGroupId
             */
            'beforecopystate',
            /**
             * @event beforeapplyall
             * Fires right before the applyAll function is run
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} stateGroupId
             * @param {Array} components
             */
            'beforeapplyall',
            /**
             * @event beforesaveall
             * Fires right before the saveAll function is run
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} stateGroupId
             * @param {Array} components
             */
            'beforesaveall',
            
            /**
             * @event readstatesuccess
             * Fires when a state has been read into the provider.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} sourceType
             * @param {String} stateGroupId
             * @param {Boolean} triggerApplyAll
             * @param {Array} components
             * @param {Object} extra
             */
            'readstatesuccess',
            /**
             * @event updatestatesuccess
             * Fires when a state has been updated.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} sourceType
             * @param {Object} state
             * @param {String} stateGroupId
             * @param {Object} extra
             */
            'updatestatesuccess',
            /**
             * @event destroystatesuccess
             * Fires when a state has been destroyed.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} sourceType
             * @param {Object} stateNames
             * @param {String} stateGroupId
             * @param {Object} extra
             */
            'destroystatesuccess',
            /**
             * @event copystatereadsuccess
             * Fires when a state has been read into the provider and is about to be coppied.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {Object} copyStateSettings
             */
            'copystatereadsuccess',
            /**
             * @event copystateupdatesuccess
             * Fires when the copy state process completes.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {Object} copyStateSettings
             */
            'copystateupdatesuccess',
            /**
             * @event applyallsuccess
             * Fires when applyAll function has completed.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} stateGroupId
             * @param {Array} components
             */
            'applyallsuccess',
            /**
             * @event saveallsuccess
             * Fires when saveAll function has completed.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} stateGroupId
             * @param {Array} components
             */
            'saveallsuccess',
            /**
             * @event readstatefailure
             * Fires when readState has failed.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} sourceType
             * @param {Object} e
             * @param {Object} Response
             * @param {String} stateGroupId
             * @param {Boolean} triggerApplyAll
             * @param {Array} components
             * @param {Object} extra
             */
            'readstatefailure',
            /**
             * @event updatestatefailure
             * Fires when updateState has failed.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} sourceType
             * @param {Object} e
             * @param {Object} Response
             * @param {String} stateGroupId
             * @param {Object} extra
             */
            'updatestatefailure',
            /**
             * @event destroystatefailure
             * Fires when destroyState has failed.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {String} sourceType
             * @param {Object} e
             * @param {Object} Response
             * @param {Array} stateNames
             * @param {String} stateGroupId
             * @param {Object} extra
             */
            'destroystatefailure',
            /**
             * @event copystatereadfailure
             * Fires when copyState has failed during it's read operation.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {Object} copyStateSettings
             */
            'copystatereadfailure',
            /**
             * @event copystateupdatefailure
             * Fires when copyState has failed during it's update operation.
             * @param {Ext.ux.state.provider.OmniProvider} this
             * @param {Object} copyStateSettings
             */
            'copystateupdatefailure'
        );
        
    //These listeners are used to allow the copyState function to complete it's opperation:    
        this.on('readstatesuccess', function () {
            var extra = arguments[arguments.length-1];
            var copyStateSettings = (extra && extra.copyStateSettings)?extra.copyStateSettings:null;
            if (copyStateSettings) {
                this.fireEvent("copystatereadsuccess", this, copyStateSettings);
                var updateStateGroupId = (copyStateSettings.newStateGroupId)?copyStateSettings.newStateGroupId:this.stateGroupId;
                this.updateState(this.tempState, updateStateGroupId, copyStateSettings.toSourceType, extra);
                this.tempState = {};
            }
        }, this);
    
        this.on('readstatefailure', function () {
            var extra = arguments[arguments.length-1];
            var copyStateSettings = (extra && extra.copyStateSettings)?extra.copyStateSettings:null;
            if (copyStateSettings) {
                this.fireEvent("copystatereadfailure", this, copyStateSettings);
                this.tempState = {};
            }
        }, this);
        
        this.on('updatestatesuccess', function () {
            var extra = arguments[arguments.length-1];
            var copyStateSettings = (extra && extra.copyStateSettings)?extra.copyStateSettings:null;
            if (copyStateSettings) {
                this.fireEvent("copystateupdatesuccess", this, copyStateSettings);
                this.tempState = {};
            }
        }, this);
        
        this.on('updatestatefailure', function () {
            var extra = arguments[arguments.length-1];
            var copyStateSettings = (extra && extra.copyStateSettings)?extra.copyStateSettings:null;
            if (copyStateSettings) {
                this.fireEvent("copystateupdatefailure", this, copyStateSettings);
                this.tempState = {};
            }
        }, this);
        
        if (this.autoReadStateOnConstruct) {
            this.readState();
        }
    
    };
    Ext.extend(Ext.ux.state.provider.OmniProvider, Ext.state.Provider, {
    //Public Properties:
        /**
        * @cfg {Boolean} debug
        * whether or not to use console.log to log failed connection attemps and other errors (defaults to true).
        * 
        */
        debug : true,
        /**
        * @cfg {String} sourceType
        * the source used for states -- may be 'cookie' (uses modified version of Ext.state.CookieProvider code), 'ajax' (uses ajax request with data formated as json), 'direct' (uses api for ExtDirect) (defaults to 'cookie').
        * 
        */
        sourceType : 'cookie',
        /**
        * @cfg {Boolean} protectState
        * protect the currently loaded state so that other functions that attempt to directly alter or delete it are defeated -- I added this feature because several components will try to modify or delete elements of the state and in some circumstances this can cause problems  (defaults to false).
        * 
        */
        protectState : false,
        /**
        * @cfg {Mixed} stateGroupId
        * allows you to save configurations of multiple components in a 'set'. This will allow for multiple state configurations to saved and retrieved as part of a group (defaults to null).
        * 
        */
        stateGroupId : null,
        /**
        * @cfg {Boolean} autoSaveState
        * may be set to false in order to prevent components from saving their own state configurations -- set this to false when you want a state to be saved manually or by another function (defaults to true).
        * 
        */
        autoSaveState : true,
        /**
        * @cfg {Boolean} autoGiveStateOnGet
        * may be set to false in order to prevent components from applying their own state configurations -- set this to false when you want a state to be applied manually or by another function (defaults to true).
        * 
        */
        autoGiveStateOnGet : true,
        /**
        * @cfg {Boolean} autoReadStateOnGet
        * whether or not to repload the state each time a get request comes in from a component -- seldom used feature (defaults to false).
        * 
        */
        autoReadStateOnGet : false,
        /**
        * @cfg {Boolean} autoReadStateOnConstruct
        * whether or not to read the state into memory when provider is constructed (defaults to true).
        * 
        */
        autoReadStateOnConstruct : true,
        /**
        * @cfg {Object} cookieConfig
        * configurations used when saving and retrieving states from a cookie -- does not generaly need to be modified but may be used to overide the settings in defaultCookieConfig. Used when sourceType is set to 'cookie' (defaults to {}).
        * 
        */
        cookieConfig : {},
        /**
        * @cfg {Object} api
        * An object containing referances to the functions to use when making ExtDirect calls to read, update and destroy the state (generally created using Ext.Direct.addProvider). The functions must connect to remote functions that do the following:
        * read($stateGroupId, $triggerApplyAll, $components, $extra) -- remote function must return: {success : [boolean], result : [state_object]}
        * update($state, $stateGroupId, $extra) -- remote function must return: {success : [boolean], result : [message]}
        * destroy($stateNames, $stateGroupId, $extra) -- remote function must return: {success : [boolean], result : [message]}
        */
        api : {
            read : null,
            update : null,
            destroy : null
        },
        /**
        * @cfg {Object} ajaxConfig
        * configuration for ajax calls to read, update and destroy the state. Generally you will only need to define the 'url' properties but other things may be set on this configuration as well. omniProvider will make the following calls to your ajax script:
        * action='read'&components=[json_encoded_array_of_components]&stateGroupId=[stateGroupId] -- remote function must return json encoded: {success : [boolean], result : [state_object]}
        * action='update'&stateGroupId=[stateGroupId]&state=[json_encoded_state_object] -- remote function must return json encoded: {success : [boolean], result : [message]}
        * action='destroy'&stateGroupId=[stateGroupId]&stateNames=[json_encoded_array_of_state_names] -- remote function must return json encoded: {success : [boolean], result : [message]}
        */
        ajaxConfig : {
            url: null
        },
    // Private Properties:
        /**
        * @private internal config {Object} specialCaseGetState
        * flag used when all components are instructed to restore their state via the applyAll function.
        * 
        */
        specialCaseGetState : false,
        /**
        * @private internal config {Object} specialCaseSetState
        * flag used when all components are instructed to save their state via the saveAll function.
        * 
        */
        specialCaseSetState : false,
        /**
        * @private internal config {Object} tempSaveState
        * used when a batch save takes place (via the saveAll function) to record all the state info to save.
        * 
        */
        tempSaveState : {},
        /**
        * @private internal config {Object} tempClearStateNames
        * used when a batch save takes place to record all the state info to clear.
        * 
        */
        tempClearStateNames : [],
        /**
        * @private internal config {Object} tempState
        * used when a copyState function is called to read the contents of a state into a property of the class with out overwriting the state property.
        * 
        */
        tempState : {},
        /**
        * @private internal config {Object} state
        * State when object is instantiated, is over written when readState functions are called
        * 
        */
        state : {},
        /**
        * @private internal config {Object} defaultStateGroupId
        * used to store what the stateGroupId is before performning batch operations.
        * 
        */
        defaultStateGroupId : '',
        /**
        * @private internal config {Object} defaultCookieConfig
        * default config for cookieConfig -- over ridden by any values passed in with cookieConfig.
        * 
        */
        defaultCookieConfig : {
            path : "/",
               expires : new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days
            domain : null,
            secure : false
        },
        /**
        * @private internal config {Object} errorMessages
        * error messages that will be logged through the log function if debug is set to true.
        * 
        */
        errorMessages : {
            ajaxCouldNoteDecodeJson : 'omniProviderError-Ajax: could not decode remote json data:',
            ajaxImproperlyFormatedReturn : 'omniProviderError-Ajax: response from server improperly formated -- should be {success:[true_or_false], result:{[error_message_or_state_information]}}:',
            ajaxServerReportedAnError : 'omniProviderError-Ajax: the server reported an error',
            ajaxServerDidNotRespond : 'omniProviderError-Ajax: Did not receive a response from the server',
            
            directRead : 'omniProviderError-Direct: error with readStateDirect return data',
            directUpdated : 'omniProviderError-Direct: error with updateStateDirect return data',
            directDestroy : 'omniProviderError-Direct: error with destroyStateDirect return data'
        },
    //Public Functions:
        /** Public Function: readState
         * reads state into memory from either the sourceType defined for the class or from the sourceType passed to the function. This function routes to other functions depending on the sourceType
         * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different names. Defaults to this.this.stateGroupId.
         * @param {Boolean} triggerApplyAll (Optional) If set to true the applyAll function will be called after the readState function completes. Defaults to false.
         * @param {Mixed} sourceType (Optional) May be set to: 'cookie', 'ajax' or 'direct'. Overides the sourceType set for the class to all the function to read in the state from a different source. Defaults to null.
         * @param {Array} components (Optional) An array of component ids that may optionaly be passed in to cause just the states relating to these components to be loaded. Defaults to this.sourceType.
         * @param {Object} extra (Optional) Values that will be passed along with the requests to read the state -- this is used largely by the copyState functions. Defaults to null.
         * @return {Object} the state that was read by the function
         */
        readState : function (stateGroupId, triggerApplyAll, sourceType, components, extra) {
            var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
            var triggerApplyAll = (typeof(triggerApplyAll)!='undefined')?triggerApplyAll:false;
            var components = (typeof(components)!='undefined')?components:null;
            var components = (typeof(components)=='string')?[components]:components;
            var sourceType = (typeof(sourceType)!='undefined')?sourceType:this.sourceType;
            var extra = (typeof(extra)!='undefined')?extra:null;
            var stateHolder = (extra && extra.stateHolder)?extra.stateHolder:'state';
            
            this.fireEvent("beforereadstate", this, stateGroupId, triggerApplyAll, sourceType, components, extra);
            
            switch (sourceType) {
                case 'cookie':
                    this.readCookies(stateGroupId, triggerApplyAll, components, extra);
                break;
                case 'ajax':
                    this.readAjax(stateGroupId, triggerApplyAll, components, extra);
                break;
                case 'direct':
                    this.readDirect(stateGroupId, triggerApplyAll, components, extra);
                break;
            }
            
            return this[stateHolder];
        },
        /** Public Function: updateState
         * saves the state passed to the function to the source of sourceType either set for the class or passed to the function. This function routes to other functions depending on the sourceType
         * @param {Object} state (Required) A state object to save
         * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different name. Defaults to this.stateGroupId.
         * @param {String} sourceType (Optional) May be set to: 'cookie', 'ajax' or 'direct'. Overides the sourceType set for the class to all the function to read in the state from a different source. Defaults to this.sourceType.
         * @param {Mixed} extra (Optional) Values that will be passed along with the requests to read the state -- this is used largely by the copyState functions. Defaults to null.
         * @return {Boolean} returns true
         */
        updateState : function (state, stateGroupId, sourceType, extra) {
            var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
            var sourceType = (typeof(sourceType)!='undefined')?sourceType:this.sourceType;
            var extra = (typeof(extra)!='undefined')?extra:null;
            
            this.fireEvent("beforeupdatestate", this, state, stateGroupId, sourceType, extra);
            switch (sourceType) {
                case 'cookie':
                    this.updateCookies(state, stateGroupId, extra);
                break;
                case 'ajax':
                    this.updateAjax(state, stateGroupId, extra);
                break;
                case 'direct':
                    this.updateDirect(state, stateGroupId, extra);
                break;
            }
            return true;
        },
        /** Public Function: destroyState
         * destroys the states whose names are passed in stateNames from sourceType either set for the class or passed to the function. This function routes to other functions depending on the sourceType
         * @param {Array} stateNames (Required) An array of stateNames to destroy
         * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different name. Defaults to this.stateGroupId
         * @param {String} sourceType (Optional) May be set to: 'cookie', 'ajax' or 'direct'. Overides the sourceType set for the class to all the function to read in the state from a different source. Defaults to this.sourceType
         * @param {Mixed} extra (Optional) Values that will be passed along with the requests to read the state -- this is used largely by the copyState functions. Defaults to null.
         * @return {Boolean} returns true
         */
        destroyState : function (stateNames, stateGroupId, sourceType, extra) {
            var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
            var sourceType = (typeof(sourceType)!='undefined')?sourceType:this.sourceType;
            var extra = (typeof(extra)!='undefined')?extra:null;
            var stateNames = (typeof(stateNames)!='string')?stateNames:[stateNames];
            this.fireEvent("beforedestroystate", this, stateNames, stateGroupId, sourceType, extra);
            
            switch (sourceType) {
                case 'cookie':
                    this.destroyCookies(stateNames, stateGroupId, extra);
                break;
                case 'ajax':
                    this.destroyAjax(stateNames, stateGroupId, extra);
                break;
                case 'direct':
                    this.destroyDirect(stateNames, stateGroupId, extra);
                break;
            }
            return true;
        },
        /** Public Function: copyState
         * starts the process to read in a state from a source and then update it to another source.
         * @param {String} fromSourceType (Required) May be set to: 'cookie', 'ajax' or 'direct'. source from which to read.
         * @param {String} toSourceType (Required) May be set to: 'cookie', 'ajax' or 'direct'. sourceType to copy the state to.
         * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different name. Defaults to this.stateGroupId
         * @param {String} newStateGroupId (Optional) The new stateGroupId to copy the state you have read to. Defaults to this.stateGroupId
         * @return {Boolean} returns true
         */
        copyState : function (fromSourceType, toSourceType, stateGroupId, newStateGroupId) {
            var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
            var newStateGroupId = (typeof(newStateGroupId)!='undefined')?newStateGroupId:this.stateGroupId;
            
            this.fireEvent("beforecopystate", this, fromSourceType, toSourceType, stateGroupId, newStateGroupId);
            
            var extra = {
                copyStateSettings : 
                    {
                        stateGroupId : stateGroupId,
                        fromSourceType : fromSourceType,
                        newStateGroupId : newStateGroupId,
                        toSourceType : toSourceType
                    },
                stateHolder : 'tempState'
            };
            this.readState(stateGroupId, false, fromSourceType, null, extra);
            return true;
        },
        /** Public Function: applyAll
         * runs a batch process to call the initState function on stateful components
         * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different name. Defaults to this.stateGroupId;
         * @param {Mixed} components An array of component ids that may optionaly be passed in to cause just these components to run their initState function. Defaults to null.
         * @return {Boolean} returns true
         */
        applyAll : function (stateGroupId, components) {
            var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
            var components = (typeof(components)!='undefined')?components:null;
            var components = (typeof(components)=='string')?[components]:components;
            
            this.fireEvent("beforeapplyall", this, stateGroupId, components);
            this.batch(stateGroupId, components,'specialCaseGetState', 'initState');
            this.fireEvent("applyallsuccess", this, stateGroupId, components);
            return true;
        },
        /** Public Function: saveAll
         * runs a batch process to call the saveState function on stateful components
         * @param {String} stateGroupId (Optional) A stateGroupId to over ride the stateGroupId set for the class -- using different stateGroupId allows you to save and load states using different name. Defaults to this.stateGroupId.
         * @param {Mixed} components (Optional) An array of component ids that may optionaly be passed in to cause just these components to run their saveState function. Defaults to null.
         * @return {Boolean} returns true
         */
        saveAll : function (stateGroupId, components) {
            var stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
            var components = (typeof(components)!='undefined')?components:null;
            var components = (typeof(components)=='string')?[components]:components;
            this.fireEvent("beforesaveall", this, stateGroupId, components);
            this.batch(stateGroupId, components, 'specialCaseSetState', 'saveState');
            
            this.updateState(this.tempSaveState);
            this.destroyState(this.tempClearStateNames);
            
            this.tempSaveState = {};
            this.tempClearStateNames = [];
            this.fireEvent("saveallsuccess", this, stateGroupId, components);
            return true;
        },
        /** Public Function: get
         * modified standard get function called by the Ext.state.Manager when an component requests to read it's loaded state
         * @param {String} name (Required) The key name.
         * @param {Mixed} defaultValue (Optional) The default value to return if the key lookup does not match. Defaults to undefined.
         * @return {Mixed} The state data or null.
         */
        get : function (name, defaultValue) {
            if (this.autoReadStateOnGet) {
                this.readState(this.stateGroupId, false, this.sourceType, [name]);
            }
            if (this.autoGiveStateOnGet || this.specialCaseGetState) {
                if (this.protectState) {
                    var returnData = {};
                    var stateObj = typeof this.state[name] == "undefined" ?
                    defaultValue : this.state[name];
                    Ext.apply(returnData, stateObj);
                    return returnData;
                } else {
                    return typeof this.state[name] == "undefined" ?
                    defaultValue : this.state[name];
                }
            } else {
                return null;    
            }
        },
        /** Public Function: set
         * modified standard set function called by the Ext.state.Manager when an component requests to set it's state
         * @param {String} name (Required) The key name.
         * @param {Mixed} value (Required) The state data.
         * @return {Boolean} returns true or false
         */
        set : function (name, value) {
            if (this.autoSaveState || this.specialCaseSetState) {
                if(typeof value == "undefined" || value === null){
                    this.clear(name);
                    return;
                }
                if (this.specialCaseSetState) {
                    this.tempSaveState[name] = value;
                } else {
                    var tempState = [];
                    tempState[name] = value;
                    this.updateState(tempState);
                    Ext.ux.state.provider.OmniProvider.superclass.set.call(this, name, value);
                }
                return true;
            } else {
                return false;
            }
            
        },
        /** Public Function: clear
         * modified standard clear function called by the Ext.state.Manager when an component requests to clear its
         * @param {String} name (Required) The key name.
         * @return {Boolean} true
         */
        clear : function (name) {
            if (this.specialCaseSetState) {
                this.tempClearStateNames.push(name);
            } else {
                this.destroyState([name]);
                Ext.ux.state.provider.OmniProvider.superclass.clear.call(this, name);
            }
            return true;
        },
    //Private Functions:
        // private
        readCookies : function(stateGroupId, triggerApplyAll, components, extra){
            var stateHolder = (extra && extra.stateHolder)?extra.stateHolder:'state';
            var cookies = {};
            var c = document.cookie + ";";
            var re = /\s?(.*?)=(.*?);/g;
            var matches;
            var regExString = "^ys\-" + stateGroupId + "\-";
            var extraRegEx = (stateGroupId) ? new RegExp(regExString) : null;
            
            while((matches = re.exec(c)) != null){
                var name = matches[1];
                var value = matches[2];
                var nameFirst3 = name.substring(0,3);
                var trimmedName = name.replace(extraRegEx, '');
                var decodedValue = this.decodeValue(value);
                if(name && nameFirst3 == "ys-" && (!extraRegEx || extraRegEx.test(name)) && (!components || this.inArray(components, name))){
                    cookies[trimmedName] = decodedValue;
                }
            }
               this[stateHolder] = cookies;
            
            this.fireEvent("readstatesuccess", this, 'cookie', stateGroupId, triggerApplyAll, components, extra);
            if (triggerApplyAll) {
                this.applyAll(stateGroupId, components);
            }
        },
        // private
        updateCookies : function(state, stateGroupId, extra){
            for (var obj in state) {
                var curName = obj;
                var curValue = state[obj];
                this.updateCookie(stateGroupId, curName, curValue);
            }
            this.fireEvent("updatestatesuccess", this, 'cookie', state, stateGroupId, extra);
        },
        // private
        updateCookie : function(stateGroupId, name, value){
            curCookieConfig = this.cookieConfig;
            Ext.applyIf(curCookieConfig, this.defaultCookieConfig);
            var nameExtra = (stateGroupId) ? stateGroupId + "-" : '';
            var cookieName = "ys-"+ nameExtra + name;
            var cookieValue = this.encodeValue(value) +
               ((curCookieConfig.expires == null) ? "" : ("; expires=" + curCookieConfig.expires.toGMTString())) +
               ((curCookieConfig.path == null) ? "" : ("; path=" + curCookieConfig.path)) +
               ((curCookieConfig.domain == null) ? "" : ("; domain=" + curCookieConfig.domain)) +
               ((curCookieConfig.secure == true) ? "; secure" : "");
               
            document.cookie = cookieName + "=" + cookieValue;
        },
        // private
        destroyCookies : function(stateNames, stateGroupId, extra){
            for (var n=0; n< stateNames.length; n++) {
                var curName = stateNames[n];
                this.destroyCookie(stateGroupId, curName);
            }
            this.fireEvent("destroystatesuccess", this, 'cookie', stateNames, stateGroupId, extra);
        },
        // private
        destroyCookie : function(stateGroupId, name){
            curCookieConfig = this.cookieConfig;
            Ext.applyIf(curCookieConfig, this.defaultCookieConfig);
            var nameExtra = (stateGroupId) ? stateGroupId + "-" : '';
            document.cookie = "ys-" + nameExtra + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
               ((curCookieConfig.path == null) ? "" : ("; path=" + curCookieConfig.path)) +
               ((curCookieConfig.domain == null) ? "" : ("; domain=" + curCookieConfig.domain)) +
               ((curCookieConfig.secure == true) ? "; secure" : "");
        },
        //private
        readAjax : function (stateGroupId, triggerApplyAll, components, extra) {
            var curAjax = this.ajaxConfig;
            var componentsEncoded = (components)?Ext.encode(components):null;
            curAjax.params  = {
                action:'read',
                components:componentsEncoded,
                stateGroupId:stateGroupId,
            };
            curAjax.triggerApplyAll = triggerApplyAll;
            curAjax.extra = extra;
            curAjax.components = components;
            curAjax.stateGroupId = stateGroupId;
            curAjax.success = this.onAjaxReadSuccess;
            curAjax.failure = this.onAjaxReadFailure;
            curAjax.scope = this;
    
            Ext.Ajax.request(curAjax);
        },
        //private
        onAjaxReadSuccess : function (response, options) {
            var response = this.parseJSONReturn(response);
            
            var stateGroupId = options.stateGroupId;
            var triggerApplyAll = options.triggerApplyAll;
            var components = options.components;
            var extra = options.extra;
            
            var success = response.success;
            var stateHolder = (extra && extra.stateHolder)?extra.stateHolder:'state';
    
            if (success) {
                for (obj in response.result) {
                    response.result[obj] = Ext.decode(response.result[obj]);
                }
    
                this[stateHolder] = response.result;
                this.fireEvent("readstatesuccess", this, 'ajax', stateGroupId, triggerApplyAll, components, extra);
                if (triggerApplyAll) {
                    this.applyAll(stateGroupId, components);
                }
            } else {
                this.fireEvent("readstatefailure", this, 'ajax', null, response, stateGroupId, triggerApplyAll, components, extra);
                this.log(this.errorMessages.ajaxServerReportedAnError, 'onAjaxReadSuccess', this, 'ajax', response, stateGroupId, triggerApplyAll, components, extra);
            }
        },
        //private
        onAjaxReadFailure : function (e, options) {
            var stateGroupId = options.stateGroupId;
            var triggerApplyAll = options.triggerApplyAll;
            var components = options.components;
            var extra = options.extra;
            this.fireEvent("readstatefailure", this, 'ajax', e, null, stateGroupId, triggerApplyAll, components, extra);
            this.log(this.errorMessages.ajaxServerDidNotRespond, 'ajax', e, null, stateGroupId, triggerApplyAll, components, extra);
        },
        //private
        updateAjax : function (state, stateGroupId, extra) {
            var curAjax = this.ajaxConfig;
        //The 'remove' function on the state obj screwed up the Ext.encode function so we make an object that doesn't have it:
            var stateToEncode = {};
            for (obj in state) {
                if (obj != 'remove') {
                    stateToEncode[obj] = state[obj];
                }
            }
            stateEncoded = Ext.encode(stateToEncode);
    
            curAjax.params = {
                action:'update',
                state:stateEncoded,
                stateGroupId:stateGroupId
            };
            curAjax.state = state;
            curAjax.stateGroupId = stateGroupId;
            curAjax.extra = extra;
            curAjax.success = this.onAjaxUpdateSuccess;
            curAjax.failure = this.onAjaxUpdateFailure;
            curAjax.scope = this;
            Ext.Ajax.request(curAjax);
        },
        //private
        onAjaxUpdateSuccess : function (response, options) {
            response = this.parseJSONReturn(response);
            var success = response.success;
            var state = options.state;
            var stateGroupId = options.stateGroupId;
            var extra = options.extra
            
            if (success) {
                this.fireEvent("updatestatesuccess", this, 'ajax', state, stateGroupId, extra);    
            } else {
                this.fireEvent("updatestatefailure", this, 'ajax', null, response, state, stateGroupId, extra);
                this.log(this.errorMessages.ajaxServerReportedAnError, 'onAjaxUpdateSuccess', this, 'ajax', null, response, state, stateGroupId, extra);
            }
        },
        //private
        onAjaxUpdateFailure : function (e, options) {
            var state = options.state;
            var stateGroupId = options.stateGroupId;
            var extra = options.extra
            this.fireEvent("updatestatefailure", this, 'ajax', e, null, state, stateGroupId, extra);
            this.log(this.errorMessages.ajaxServerDidNotRespond, this, 'ajax', e, null, state, stateGroupId, extra);
        },
        //private
        destroyAjax : function (stateNames, stateGroupId, extra) {
            var curAjax = this.ajaxConfig;
            var stateNamesEncoded = (stateNames)?Ext.encode(stateNames):null;
            curAjax.params = {
                action:'destroy',
                stateNames:stateNamesEncoded,
                stateGroupId:stateGroupId
            };
            curAjax.stateNames = stateNames;
            curAjax.stateGroupId = stateGroupId;
            curAjax.extra = extra;
            curAjax.success = this.onAjaxDestroySuccess;
            curAjax.failure = this.onAjaxDestroyFailure;
            curAjax.scope = this;
            Ext.Ajax.request(curAjax);
        },
        //private
        onAjaxDestroySuccess : function (response, options) {
            response = this.parseJSONReturn(response);
            var stateNames = options.stateNames;
            var stateGroupId = options.stateGroupId;
            var extra = options.extra
            
            var success = response.success;
            if (success) {
                this.fireEvent("destroystatesuccess", this, 'ajax', stateNames, stateGroupId, extra);    
            } else {
                this.fireEvent("destroystatefailure", this, 'ajax', null, response, stateNames, stateGroupId, extra);
                this.log(this.errorMessages.ajaxServerDidNotRespond, this, 'ajax', response, stateNames, stateGroupId, extra);
            }
        },
        //private
        onAjaxDestroyFailure : function (e, options) {
            var stateNames = options.stateNames;
            var stateGroupId = options.stateGroupId;
            var extra = options.extra
            
            this.fireEvent("destroystatefailure", this, 'ajax', e, null, stateNames, stateGroupId, extra);
            this.log(this.errorMessages.ajaxServerDidNotRespond, this, 'ajax', e, stateNames, stateGroupId, extra);
        },
        //private
        readDirect : function (stateGroupId, triggerApplyAll, components, extra) {
            this.api.read(stateGroupId, triggerApplyAll, components, extra, this.onDirectReadSuccess, this);
        },
        //private
        onDirectReadSuccess : function(response, e){
            var transaction = e.getTransaction();
            var stateGroupId = transaction.args[0];
            var triggerApplyAll = transaction.args[1];
            var components = transaction.args[2];
            var extra = transaction.args[3];
            var stateHolder = (extra && extra.stateHolder)?extra.stateHolder:'state';
            var success = response.success;
            if (success) {
                this[stateHolder] = response.result;
                this.fireEvent("readstatesuccess", this, 'direct', stateGroupId, triggerApplyAll, components, extra);
                if (triggerApplyAll) {
                    this.applyAll(stateGroupId, components);
                }
            } else {
                this.fireEvent("readstatefailure", this, 'direct', e, response, stateGroupId, triggerApplyAll, components, extra);
                this.log(this.errorMessages.directRead, 'onDirectReadSuccess', this, 'direct', e, stateGroupId, triggerApplyAll, components, extra);
            }
        },
        //private
        updateDirect : function (state, stateGroupId, extra) {
            var stateToSend = {};
            for (obj in state) {
                if (obj != 'remove') {
                    stateToSend[obj] = state[obj];
                }
            }
            this.api.update(stateToSend, stateGroupId, extra, this.onDirectUpdateSuccess, this);
        },
        //private
        onDirectUpdateSuccess : function(response, e){
            var transaction = e.getTransaction();
            var state = transaction.args[0];
            var stateGroupId = transaction.args[1];
            var extra = transaction.args[2];
            var success = response.success;
    
            if (success) {
                this.fireEvent("updatestatesuccess", this, 'direct', state, stateGroupId, extra);    
            } else {
                this.fireEvent("updatestatefailure", this, 'direct', e, response, state, stateGroupId, extra);
                this.log(this.errorMessages.directUpdate, 'onDirectUpdateSuccess', this, 'direct', e, response, state, stateGroupId, extra);
            }
            
        },
        //private
        destroyDirect : function (stateNames, stateGroupId, extra) {
            this.api.destroy(stateNames, stateGroupId, extra, this.onDirectDestroySuccess, this);
        },
        //private
        onDirectDestroySuccess : function(response, e){
            var transaction = e.getTransaction();
            var stateNames = transaction.args[0];
            var stateGroupId = transaction.args[1];
            var extra = transaction.args[2];
            var success = response.success;
            if (success) {
                this.fireEvent("destroystatesuccess", this, 'direct', stateNames, stateGroupId, extra);
            } else {
                this.fireEvent("destroystatefailure", this, 'direct', e, response, stateNames, stateGroupId, extra);
                this.log(this.errorMessages.directDestroy, 'onAjaxDestroySuccess', this, 'direct', e, stateNames, stateGroupId, extra);
            }
        },
        //private
        parseJSONReturn : function (response) {
            try {
                var result = Ext.decode(response.responseText);
            } catch(e) {
                this.log(this.errorMessages.ajaxCouldNoteDecodeJson, e, response, options, this);
                return false;
            }
            if (typeof(result.success) == 'undefined' || typeof(result.result)== 'undefined') {
                this.log(this.errorMessages.ajaxImproperlyFormatedReturn, response, options, this);
                return false;
            }
            return result;
        },
        //private
        batch : function (stateGroupId, components, flag, callFunction) {
            this.defaultStateGroupId = this.stateGroupId;
            this.stateGroupId = (typeof(stateGroupId)!='undefined')?stateGroupId:this.stateGroupId;
            
            this[flag] = true;
            
            var curComponents = (components)?components:Ext.ComponentMgr.all.items;
    
            for (var n=0; n<curComponents.length; n++) {
                var curComp = curComponents[n];
                curComp = (typeof(curComp)=='string')?Ext.getCmp(curComp):curComp;
                if (typeof(curComp.stateful !== false)) {
                    curComp[callFunction]();
                }
            }
            
            this[flag] = false;
            this.stateGroupId = this.defaultStateGroupId;
        },
        //private
        log : function() {
            if (this.debug){ 
                if(console) {
                    console.log.apply(console, arguments);
                }
            }
        },
        //private
        inArray : function (array, value, caseSensitive) {
            var i;
            for (i=0; i < array.length; i++) {
                // use === to check for Matches. ie., identical (===),
                if(caseSensitive){ //performs match even the string is case sensitive
                    if (array[i].toLowerCase() == value.toLowerCase()) {
                        return true;
                    }
                }else{
                    if (array[i] == value) {
                        return true;
                    }
                }
            }
            return false;
        }
    });
    Ext.reg('ux-state-provider-omniprovider', Ext.ux.state.provider.OmniProvider);

  5. #5
    Sencha User thesilentman's Avatar
    Join Date
    Apr 2007
    Location
    Athens, Greece
    Posts
    232
    Vote Rating
    2
      0  

    Default Works nicely, just what I was going to do next.... ;)

    Hello Will,

    your extension works nicely. I am using it with my own backend though.
    I had started experimenting with the stateproviders when I stumbled upon your post.


    So, for me only one little question remains...
    what license is it under?

    I liked it, so I wanted to include it in a commercial app I am building.

    Greets,
    Frank

  6. #6
    Sencha User willf1976's Avatar
    Join Date
    May 2009
    Location
    carpinteria, ca
    Posts
    84
    Vote Rating
    0
      0  

    Post

    Hi Frank

    I am glad you like the omniProvider. I actually I am not using that back end either -- just something I through together to make a demo.

    I am putting the omniProvider under the GNU license LGPL version 3 -- http://www.gnu.org/copyleft/lesser.html

    Basically you can use omniProvider as a component of what ever you want to sell so long as you are not selling the omniProvider itself. Also if you are distributing omniProvider you must leave the GPL intact.

    Hope you had a good weekend.

    Best Regards

    Will Ferrer

  7. #7
    Ext JS Premium Member
    Join Date
    Mar 2007
    Location
    Germany
    Posts
    731
    Vote Rating
    37
      0  

    Default

    there ist a small typo:

    Code:
        readAjax : function (stateGroupId, triggerApplyAll, components, extra) {
            var curAjax = this.ajaxConfig;
            var componentsEncoded = (components)?Ext.encode(components):null;
            curAjax.params  = {
                action:'read',
                components:componentsEncoded,
                stateGroupId:stateGroupId,   <----
            };
    This comma is not good for the Internet-Explorer :-)

  8. #8
    Sencha User willf1976's Avatar
    Join Date
    May 2009
    Location
    carpinteria, ca
    Posts
    84
    Vote Rating
    0
      0  

    Default

    Hi Dumbledore

    I had made an additional post with an updated version that fixed that -- to avoid confusion I deleted the updated post and updated the original post instead.

    Thanks for the catch.

    Best regards

    Will Ferrer

    Quote Originally Posted by Dumbledore View Post
    there ist a small typo:

    Code:
        readAjax : function (stateGroupId, triggerApplyAll, components, extra) {
            var curAjax = this.ajaxConfig;
            var componentsEncoded = (components)?Ext.encode(components):null;
            curAjax.params  = {
                action:'read',
                components:componentsEncoded,
                stateGroupId:stateGroupId,   <----
            };
    This comma is not good for the Internet-Explorer :-)

  9. #9
    Sencha User proceno72's Avatar
    Join Date
    Mar 2008
    Location
    Italy
    Posts
    2
    Vote Rating
    0
      0  

    Default destroyState ajax sourceType

    When I use destroyState function on 'ajax' sourceType (trying delete txt file on server), found error 'Options is not defined' on line 891 of your 'Ext.ux.state.provider.OmniProvider.js' (private definition of parseJSONReturn).
    Function call on my page is like this:
    omniProvider.destroyState('id_grid', omniProvider.stateGroupId,'ajax');

    Using Extjs version 3.2.0

  10. #10
    Sencha User willf1976's Avatar
    Join Date
    May 2009
    Location
    carpinteria, ca
    Posts
    84
    Vote Rating
    0
      0  

    Default

    Hi Proceno

    I have been very preoccupied with a deadline and haven't had a chance to look into this yet. I will try to see if I can figure it out next chance I get though. If you happen to look through the code and figure it out first please let me know and I will post your updated version of the code back into this thread.

    Thanks for the catch.

    Best Regards

    Will Ferrer

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •