Page 1 of 4 123 ... LastLast
Results 1 to 10 of 34

Thread: Ext.Direct based State Provider

  1. #1
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,664
    Vote Rating
    403
      0  

    Default Ext.Direct based State Provider

    Hi all.

    Based on my HttpProvider, I've just finished DirectProvider. The logic is same but this one uses Ext.Direct to interact with server.

    PHP Code:
    // vim: ts=4:sw=4:nu:fdc=2:nospell
    /*global Ext, console */
    /**
     * @class Ext.ux.state.DirectProvider
     * @extends Ext.state.Provider
     *
     * Buffering state provider that sends and receives state information to/from server
     * using Ext.Direct infrastructure
     *
     * @author    Ing. Jozef Saklo
     * @copyright (c) 2008-2009, Ing. Jozef Saklo
     * @version   2.0
     * @date      18. September 2009
     * @revision  $Id: Ext.ux.state.DirectProvider.js 23 2009-09-18 15:41:12Z jozo $
     * @depends   Ext.ux.util
     *
     * @license Ext.ux.state.DirectProvider is licensed under the terms of
     * the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
     * that the code/component(s) do NOT become part of another Open Source or Commercially
     * licensed development library or toolkit without explicit permission.
     * 
     * <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
     * target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
     *
     * @forum     24970
     *
     * @donate
     * <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
     * <input type="hidden" name="cmd" value="_s-xclick">
     * <input type="hidden" name="hosted_button_id" value="3430419">
     * <input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-butcc-donate.gif" 
     * border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
     * <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
     * </form>
     */

    Ext.ns('Ext.ux.state');

    /**
     * Creates new DirectProvider
     * @constructor
     * @param {Object} config Configuration object
     */
    // {{{
    Ext.ux.state.DirectProvider = function(config) {

        
    this.addEvents(
            
    /**
             * @event readsuccess
             * Fires after state has been successfully received from server and restored
             * @param {DirectProvider} this
             */
             
    'readsuccess'
            
    /**
             * @event readfailure
             * Fires in the case of an error when attempting to read state from server
             * @param {DirectProvider} this
             */
            
    ,'readfailure'
            
    /**
             * @event savesuccess
             * Fires after the state has been successfully saved to server
             * @param {DirectProvider} this
             */
            
    ,'savesuccess'
            
    /**
             * @event savefailure
             * Fires in the case of an error when attempting to save state to the server
             * @param {DirectProvider} this
             */
            
    ,'savefailure'
        
    );

        
    // call parent 
        
    Ext.ux.state.DirectProvider.superclass.constructor.call(this);

        
    Ext.apply(thisconfig, {
            
    // defaults
             
    delay:750 // buffer changes for 750 ms
            
    ,dirty:false
            
    ,started:false
            
    ,autoStart:true
            
    ,autoRead:true
            
    ,readFn:Ext.emptyFn
            
    ,saveFn:Ext.emptyFn
            
    ,user:'user'
            
    ,id:1
            
    ,session:'session'
            
    ,logFailure:false
            
    ,logSuccess:false
            
    ,queue:[]
            ,
    paramNames:{
                 
    id:'id'
                
    ,name:'name'
                
    ,value:'value'
                
    ,user:'user'
                
    ,session:'session'
                
    ,data:'data'
            
    }
        }); 
    // eo apply

        
    if(this.autoRead) {
            
    this.readState();
        }

        
    this.dt = new Ext.util.DelayedTask(this.saveStatethis);
        if(
    this.autoStart) {
            
    this.start();
        }
    }; 
    // eo constructor
    // }}}

    Ext.extend(Ext.ux.state.DirectProviderExt.state.Provider, {

        
    // localizable texts
         
    saveSuccessText:'Save Success'
        
    ,saveFailureText:'Save Failure'
        
    ,readSuccessText:'Read Success'
        
    ,readFailureText:'Read Failure'
        
    ,dataErrorText:'Data Error'

        
    // {{{
        /**
         * Clears the state variable
         * @param {String} name Name of the variable to clear
         */
        
    ,clear:function(name) {
            
    this.set(nameundefined);
        } 
    // eo function clear
        // }}}
        // {{{
        /**
         * Initializes state from the passed state object or array.
         * This method can be called early during page load having the state Array/Object
         * retrieved from database by server.
         * @param {Array/Object} state State to initialize state manager with
         */
        
    ,initState:function(state) {
            if(
    state instanceof Array) {
                
    Ext.each(state, function(item) {
                    
    this.state[item.name] = this.decodeValue(item[this.paramNames.value]);
                }, 
    this);
            }
            else {
                
    this.state state state : {};
            }
        } 
    // eo function initState
        // }}}
        // {{{
        /**
         * private, logs errors or successes
         */
        
    ,log:function() {
            if(
    console) {
                
    console.log.apply(consolearguments);
            }
        } 
    // eo log
        // }}}
        // {{{
        /**
         * private, queues the state change if state has changed
         */
        
    ,queueChange:function(namevalue) {
            var 
    = {};
            var 
    i;
            var 
    found false;

            
    // see http://extjs.com/forum/showthread.php?p=344233
            
    var lastValue this.state[name];
            for(
    0this.queue.lengthi++) {
                if(
    this.queue[i].name === name) {
                    
    lastValue this.decodeValue(this.queue[i].value);
                }
            }
            var 
    changed undefined === lastValue || lastValue !== value;

            if(
    changed) {
                
    o[this.paramNames.name] = name;
                
    o[this.paramNames.value] = this.encodeValue(value);
                for(
    0this.queue.lengthi++) {
                    if(
    this.queue[i].name === o.name) {
                        
    this.queue[i] = o;
                        
    found true;
                    }
                }
                if(
    false === found) {
                    
    this.queue.push(o);
                }
                
    this.dirty true;
            }
            if(
    this.started) {
                
    this.start();
            }
            return 
    changed;
        } 
    // eo function bufferChange
        // }}}
        // {{{
        /**
         * Ext direct call callback
         * @private
         */
        
    ,readCallback:function(responsee) {
            
    // handle success
            
    if(true === e.status) {
                if(!
    Ext.isArray(response) && true === this.logFailure) {
                    
    this.log(this.dataErrorTextresponsee);
                    return;
                }
                
    Ext.each(response, function(item) {
                    
    this.state[item[this.paramNames.name]] = this.decodeValue(item[this.paramNames.value]);
                }, 
    this);
                
    this.queue = [];
                
    this.dirty false;
                if(
    true === this.logSuccess) {
                    
    this.log(this.readSuccessTextresponsee);
                }
                
    this.fireEvent('readsuccess'this);
            }
            
    // handle failure
            
    else {
                if(
    true === this.logFailure) {
                    
    this.log(this.readFailureTextresponsee);
                }
                
    this.fireEvent('readfailure'this);
            }
        } 
    // eo function readCallback
        // }}}
        // {{{
        /**
         * Reads saved state from server by sending asynchronous Ajax request and processing the response
         */
        
    ,readState:function() {
            var 
    = {
                 
    paramNames:this.paramNames
            
    }
            
    o[this.paramNames.id] = this.id;
            
    o[this.paramNames.user] = this.user;
            
    o[this.paramNames.session] = this.session;

            
    this.readFn(othis.readCallbackthis);
        } 
    // eo function readState
        // }}}
        // {{{
        /**
         * Direct call callback function
         * @private
         */
        
    ,saveCallback:function(responsee) {
            
    // handle success
            
    if(true === e.status) {

                
    // get queue clone that has been sent to server as data
                
    var queue e.getTransaction().args[0][this.paramNames.data];

                
    // iterate through the sent queue and set local state
                
    Ext.each(queue, function(item) {
                    if(!
    item) {
                        return;
                    }
                    var 
    name item[this.paramNames.name];
                    var 
    value this.decodeValue(item[this.paramNames.value]);

                    if(
    undefined === value || null === value) {
                        
    Ext.ux.state.DirectProvider.superclass.clear.call(thisname);
                    }
                    else {
                        
    // parent sets value and fires event
                        
    Ext.ux.state.DirectProvider.superclass.set.call(thisnamevalue);
                    }
                }, 
    this);

                
    // nothing to do if we've not got dirty during the server roundtrip
                
    if(false === this.dirty) {
                    
    this.queue = [];
                }
                else {
                    var 
    ijfound;
                    for(
    0queue.lengthi++) {
                        
    found false;
                        for(
    0this.queue.lengthj++) {
                            if(
    queue[i].name === this.queue[j].name) {
                                
    found true;
                                break;
                            }
                        }
                        
    // remove equal items, i.e. items already saved
                        
    if(true === found && this.encodeValue(queue[i].value) === this.encodeValue(this.queue[j].value)) {
                            
    this.queue.remove(this.queue[j]);
                        }
                    }
                }
                if(
    true === this.logSuccess) {
                    
    this.log(this.saveSuccessTextresponsee);
                }
                
    this.fireEvent('savesuccess'this);
            }

            
    // handle failure
            
    else {
                if(
    true === this.logFailure) {
                    
    this.log(this.saveFailureTextresponsee);
                }
                
    this.dirty true;
                
    this.fireEvent('savefailure'this);
            }
        } 
    // eo function saveCallback
        // }}}
        // {{{
        /**
         * private, submits state to server by asynchronous Ajax request
         */
        
    ,saveState:function() {
            if(!
    this.dirty) {
                
    this.dt.delay(this.delay);
                return;
            }
            
    this.dt.cancel();

            var 
    queueClone Ext.ux.util.clone(this.queue);
            var 
    = {
                 
    paramNames:this.paramNames
            
    }
            
    o[this.paramNames.id] = this.id;
            
    o[this.paramNames.user] = this.user;
            
    o[this.paramNames.session] = this.session;
            
    o[this.paramNames.data] = queueClone;

            
    // be optimistic
            
    this.dirty false;

            
    // call direct function
            
    this.saveFn(othis.saveCallbackthis);

        } 
    // eo function saveState
        // }}}
        // {{{
        /**
         * Sets the passed state variable name to the passed value and queues the change
         * @param {String} name Name of the state variable
         * @param {Mixed} value Value of the state variable
         */
        
    ,set:function(namevalue) {
            if(!
    name) {
                return;
            }

            
    this.queueChange(namevalue);

        } 
    // eo function set
        // }}}
        // {{{
        /**
         * Starts submitting state changes to server
         */
        
    ,start:function() {
            
    this.dt.delay(this.delay);
            
    this.started true;
        } 
    // eo function start
        // }}}
        // {{{
        /**
         * Stops submitting state changes
         */
        
    ,stop:function() {
            
    this.dt.cancel();
            
    this.started false;
        } 
    // eo function stop
        // }}}

    }); // eo extend

    // eof 
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid MultiSearch Plugin, Grid MultiSort Plugin, Configuring ViewModel Hierarchy


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

    Default

    can you provide a simple direct php class to handle this?

    Bye, Dumbledore

  3. #3
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,664
    Vote Rating
    403
      0  

    Default

    The server side I use is proprietary so I cannot publish the code. However, it shouldn't be that difficult to code it as you only need two functions: saveState and readState (or your own names). If you will deliver the full state on page load and initialize the provider with that state (autoRead:false and initState(....) at the beginning of the page) then you only need saveState remotable method. This is what is sent to server:
    Code:
    {"action":"State","method":"saveState","data":[{"paramNames":{"id":"id","name":"name","value":"value","user":"user","session":"session","data":"data"},"id":"1","user":"jozo@default","session":"Perseus","data":[{"name":"testwidget","value":"o%3Awidth%3Dn%253A200%5Eheight%3Dn%253A150%5Ex%3Dn%253A395%5Ey%3Dn%253A171"}]}],"type":"rpc","tid":2}
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid MultiSearch Plugin, Grid MultiSort Plugin, Configuring ViewModel Hierarchy


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

    Default

    ok, i figure out how to to that. Two questions:

    1. Why you dont implement a simple get function to get only one state?
    2. Why do my listener not work?

    Code:
            // State-Handler
            Ext.state.Manager.setProvider(new Ext.ux.state.DirectProvider({
                user    : 'user',
                readFn  : Ext.app.State.read,
                saveFn  : Ext.app.State.save,
                autoRead: false,
                listeners : {
                    readsuccess : function(r){
                        console.log("readsuccess");
                        console.log(r);
                    },
                    readfailure : function(r){
                        console.log("readfailure");
                        console.log(r);
                    }
                }
            }));

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

    Default

    ok, listener dont work. But this works fine:

    Code:
            // State-Handler
            var stateProvider = new Ext.ux.state.DirectProvider({
                user    : 'user',
                session : this.title,
                readFn  : Ext.app.State.read,
                saveFn  : Ext.app.State.save,
                autoRead: false
            })
            stateProvider.on('readsuccess', function(prov){
                console.log(prov.state);
            })

  6. #6
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,664
    Vote Rating
    403
      0  

    Default

    You have also options: logSuccess:true, logFailure:true.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid MultiSearch Plugin, Grid MultiSort Plugin, Configuring ViewModel Hierarchy


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

    Default

    i need again your help...

    i have a singlepage application. All is rendered at startup and then the login appears. After login i make a ...stateProvider.readState();

    But how do i set at this time all states to all (always rendered) components?

    [update]

    when i switched back to Cookie-Provider all runs fine... Whats wrong?

    When i run follwing:
    Code:
    Ext.state.Manager.getProvider().initState([{"name":"app_rightnavigation","value":"o%3Acollapsed%3Db%253A0"}]);
    My Panel with the stateId "app_rightnavigation" must expanded? Also at runtime?

    Bye, Dumbledore

  8. #8
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,664
    Vote Rating
    403
      0  

    Default

    Generally, the state provider must be initialized at the beginning of the application as state is read and applied when classes are instantiated. Cookie provider has saved state automatically available as it is stored by client. For HttpProvider you need to deliver this state from the server - ideally at the initial page load.

    See http://cellactions.extjs.eu/ for example on how it can be done. The content of the page is not interesting - mind only state save/restore parts. Take a look also at the page source to see the app flow.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid MultiSearch Plugin, Grid MultiSort Plugin, Configuring ViewModel Hierarchy


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

    Default

    now it worked for me, thanks for your help.

    It will be nice if there were a destroy state (destroyFn) handler in future versions. In this case it will be easier to remove no needed entries.

    Bye...

  10. #10
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,664
    Vote Rating
    403
      0  

    Default

    You can call clear method to remove an individual state. There is no clearAll method currently.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid MultiSearch Plugin, Grid MultiSort Plugin, Configuring ViewModel Hierarchy


Page 1 of 4 123 ... 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
  •