Hybrid View

  1. #1
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,162
    Vote Rating
    322
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default Buffering Http State Provider

    Buffering Http State Provider


    Hi all,

    I've just finished coding and first tests of HttpProvider (Ext.ux.HttpProvider) that saves state data on a server not in cookies. It buffers changes for a configurable time and then saves them to a server with Ajax request. There is no client/server traffic if there are no changes.

    Give it a try, however, testing this extension is not for beginners.

    PHP Code:
    // vim: ts=4:sw=4:nu:fdc=2:nospell
    /*global Ext, console */
    /**
     * @class Ext.ux.state.HttpProvider
     * @extends Ext.state.Provider
     *
     * Buffering state provider that sends and receives state information to/from server
     *
     * @author    Ing. Jozef Sakáloš
     * @copyright (c) 2008, Ing. Jozef Sakáloš
     * @version   1.2
     * @revision  $Id: Ext.ux.state.HttpProvider.js 728 2009-06-16 16:31:16Z jozo $
     * @depends   Ext.ux.util
     *
     * @license Ext.ux.state.HttpProvider 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
     * @demo      http://cellactions.extjs.eu
     *
     * @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 HttpProvider
     * @constructor
     * @param {Object} config Configuration object
     */
    // {{{
    Ext.ux.state.HttpProvider = function(config) {

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

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

        
    Ext.apply(thisconfig, {
            
    // defaults
             
    delay:750 // buffer changes for 750 ms
            
    ,dirty:false
            
    ,started:false
            
    ,autoStart:true
            
    ,autoRead:true
            
    ,user:'user'
            
    ,id:1
            
    ,session:'session'
            
    ,logFailure:false
            
    ,logSuccess:false
            
    ,queue:[]
            ,
    url:'.'
            
    ,readUrl:undefined
            
    ,saveUrl:undefined
            
    ,method:'post'
            
    ,saveBaseParams:{}
            ,
    readBaseParams:{}
            ,
    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.submitStatethis);
        if(
    this.autoStart) {
            
    this.start();
        }
    }; 
    // eo constructor
    // }}}

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

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

        
    // {{{
        /**
         * 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
        // }}}
        // {{{
        /**
         * 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
        // }}}
        // {{{
        /**
         * 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
        // }}}
        // {{{
        /**
         * private, submits state to server by asynchronous Ajax request
         */
        
    ,submitState:function() {
            if(!
    this.dirty) {
                
    this.dt.delay(this.delay);
                return;
            }
            
    this.dt.cancel();

            var 
    = {
                 
    url:this.saveUrl || this.url
                
    ,method:this.method
                
    ,scope:this
                
    ,success:this.onSaveSuccess
                
    ,failure:this.onSaveFailure
                
    ,queue:Ext.ux.util.clone(this.queue)
                ,
    params:{}
            };

            var 
    params Ext.apply({}, this.saveBaseParams);
            
    params[this.paramNames.id] = this.id;
            
    params[this.paramNames.user] = this.user;
            
    params[this.paramNames.session] = this.session;
            
    params[this.paramNames.data] = Ext.encode(o.queue);

            
    Ext.apply(o.paramsparams);

            
    // be optimistic
            
    this.dirty false;

            
    Ext.Ajax.request(o);
        } 
    // eo function submitState
        // }}}
        // {{{
        /**
         * Clears the state variable
         * @param {String} name Name of the variable to clear
         */
        
    ,clear:function(name) {
            
    this.set(nameundefined);
        } 
    // eo function clear
        // }}}
        // {{{
        /**
         * private, save success callback
         */
        
    ,onSaveSuccess:function(responseoptions) {
            var 
    = {};
            try {
    Ext.decode(response.responseText);}
            catch(
    e) {
                if(
    true === this.logFailure) {
                    
    this.log(this.saveFailureTexteresponse);
                }
                
    this.dirty true;
                return;
            }
            if(
    true !== o.success) {
                if(
    true === this.logFailure) {
                    
    this.log(this.saveFailureTextoresponse);
                }
                
    this.dirty true;
            }
            else {
                
    Ext.each(options.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.HttpProvider.superclass.clear.call(thisname);
                    }
                    else {
                        
    // parent sets value and fires event
                        
    Ext.ux.state.HttpProvider.superclass.set.call(thisnamevalue);
                    }
                }, 
    this);
                if(
    false === this.dirty) {
                    
    this.queue = [];
                }
                else {
                    var 
    ijfound;
                    for(
    0options.queue.lengthi++) {
                        
    found false;
                        for(
    0this.queue.lengthj++) {
                            if(
    options.queue[i].name === this.queue[j].name) {
                                
    found true;
                                break;
                            }
                        }
                        if(
    true === found && this.encodeValue(options.queue[i].value) === this.encodeValue(this.queue[j].value)) {
                            
    this.queue.remove(this.queue[j]);
                        }
                    }
                }
                if(
    true === this.logSuccess) {
                    
    this.log(this.saveSuccessTextoresponse);
                }
                
    this.fireEvent('savesuccess'this);
            }
        } 
    // eo function onSaveSuccess
        // }}}
        // {{{
        /**
         * private, save failure callback
         */
        
    ,onSaveFailure:function(responseoptions) {
            if(
    true === this.logFailure) {
                
    this.log(this.saveFailureTextresponse);
            }
            
    this.dirty true;
            
    this.fireEvent('savefailure'this);
        } 
    // eo function onSaveFailure
        // }}}
        // {{{
        /**
         * private, read state callback
         */
        
    ,onReadFailure:function(responseoptions) {
            if(
    true === this.logFailure) {
                
    this.log(this.readFailureTextresponse);
            }
            
    this.fireEvent('readfailure'this);

        } 
    // eo function onReadFailure
        // }}}
        // {{{
        /**
         * private, read success callback
         */
        
    ,onReadSuccess:function(responseoptions) {
            var 
    = {}, data;
            try {
    Ext.decode(response.responseText);}
            catch(
    e) {
                if(
    true === this.logFailure) {
                    
    this.log(this.readFailureTexteresponse);
                }
                return;
            }
            if(
    true !== o.success) {
                if(
    true === this.logFailure) {
                    
    this.log(this.readFailureTextoresponse);
                }
            }
            else {
                
    data o[this.paramNames.data];
                if(!(
    data instanceof Array) && true === this.logFailure) {
                    
    this.log(this.dataErrorTextdataresponse);
                    return;
                }
                
    Ext.each(data, 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.readSuccessTextdataresponse);
                }
                
    this.fireEvent('readsuccess'this);
            }
        } 
    // eo function onReadSuccess
        // }}}
        // {{{
        /**
         * Reads saved state from server by sending asynchronous Ajax request and processing the response
         */
        
    ,readState:function() {
            var 
    = {
                 
    url:this.readUrl || this.url
                
    ,method:this.method
                
    ,scope:this
                
    ,success:this.onReadSuccess
                
    ,failure:this.onReadFailure
                
    ,params:{}
            };

            var 
    params Ext.apply({}, this.readBaseParams);
            
    params[this.paramNames.id] = this.id;
            
    params[this.paramNames.user] = this.user;
            
    params[this.paramNames.session] = this.session;

            
    Ext.apply(o.paramsparams);
            
    Ext.Ajax.request(o);
        } 
    // eo function readState
        // }}}
        // {{{
        /**
         * private, logs errors or successes
         */
        
    ,log:function() {
            if(
    console) {
                
    console.log.apply(consolearguments);
            }
        } 
    // eo log
        // }}}

    }); // eo extend

    // eof 
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Blessing and Curse of refs, Grid MultiSearch Plugin


  2. #2
    Sencha User galdaka's Avatar
    Join Date
    Mar 2007
    Location
    Spain
    Posts
    1,166
    Vote Rating
    -1
    galdaka is an unknown quantity at this point

      0  

    Default


    Sound interesting!!

    Will be a demo in future?

    Thanks in advance,

  3. #3
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,162
    Vote Rating
    322
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    Well, this is not very easy to "show" or "demonstrate" as it has no UI to be shown and everything runs in background. Anyway, should there be a big demand for a demo, I'd think of some and create.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Blessing and Curse of refs, Grid MultiSearch Plugin


  4. #4
    Ext JS Premium Member
    Join Date
    Nov 2007
    Location
    Munich
    Posts
    30
    Vote Rating
    0
    sigaref is on a distinguished road

      0  

    Default


    Thank you for this code.

    I managed to store the state from a grid in a DB, and to read the state back into this.state when loading the page.

    But how can I set the grid state now with the settings from this.state? I have set the grid's stateId and stateful to true. Do I have to specify some kind of callback or call a special grid function?

    Thanks in advance!

  5. #5
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,162
    Vote Rating
    322
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    I'd say that grid.initState() should be enough but if that changes column widths or another visual parts you may need to refresh view, doLayout or similar.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Blessing and Curse of refs, Grid MultiSearch Plugin


  6. #6
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,162
    Vote Rating
    322
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    One more remark: Provider request state from server upon construction. If you try to set grid state before it was received from server you see no effect as state is still empty.

    I've also faced this problem so I updated HttpProvider code a bit and I send the initial state with initial page load. The rendered html of main page contains:

    HTML Code:
    <script type="text/javascript">
    Ext.state.Manager.setProvider(new Ext.ux.HttpProvider({
         url:'/request.php?#state'
        ,user:'jozo@default'
        ,session:'Perseus.Stat'
        ,id:'1'
        ,readBaseParams:{cmd:'readState'}
        ,saveBaseParams:{cmd:'saveState'}
        ,autoRead:false
    //    ,logFailure:true
    //    ,logSuccess:true
    }));
    Ext.state.Manager.getProvider().initState([{"name":"client-mod-client-grid","value":"..."},{"name":"client-mod-win","value":"..."}]);
    </script>
    Of course, to create the initial state you need to iterate through your db server-side and to construct the above argument with states array for the provider.

    Don't forget to grab the updated code from the first post.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Blessing and Curse of refs, Grid MultiSearch Plugin


  7. #7
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,162
    Vote Rating
    322
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    Quote Originally Posted by galdaka View Post
    Sound interesting!!

    Will be a demo in future?

    Thanks in advance,
    There is no demo dedicated to HttpProvider but http://rowactions.extjs.eu uses HttpProvider to keep state of window and grid.
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Blessing and Curse of refs, Grid MultiSearch Plugin


  8. #8
    Ext User
    Join Date
    Mar 2008
    Posts
    41
    Vote Rating
    0
    jonx is on a distinguished road

      0  

    Thumbs up


    Quote Originally Posted by jsakalos View Post
    There is demo dedicated to HttpProvider but http://rowactions.extjs.eu uses HttpProvider to keep state of window and grid.
    Hello jsakalos
    thank you for providing a demo. I have still not finished adapting it to my code as I'm using asp.net and I'm trying to persist the state of the portal sample. I made some progresses but this still needs work

    Thanks again...

  9. #9
    Sencha User jack.slocum's Avatar
    Join Date
    Mar 2007
    Location
    Tampa, FL
    Posts
    6,955
    Vote Rating
    16
    jack.slocum will become famous soon enough

      0  

    Default


    Hey guys, as mentioned in my previous post on this thread, you really should take a look at the hybrid provider in the examples/state folder of the distribution.

    Saki, in response to your previous concern, only the state modification taking place is set in a cookie not the entire state (unlike CookieProvider). Because of that, there is no issue with the size of cookies getting too large.

    I really would like to encourage you to take a look as it is definitely a preferred way to tackle this issue and will result in a much better user experience (reduced HTTP requests), no data loss (if they leave the page immediately their state is still safe, unlike HTTP which aborts on leave) and less/simplified code. I've used the approach in many applications with great success.
    Jack Slocum
    Ext JS Founder
    Original author of Ext JS 1, 2 & 3.
    Twitter: @jackslocum
    jack@extjs.com

  10. #10
    Ext User
    Join Date
    Mar 2008
    Posts
    41
    Vote Rating
    0
    jonx is on a distinguished road

      0  

    Default


    Hello Jack,
    I agree with you that in most cases the hybrid provider or even the cookie provider is a better choice (by the fact it's easier to setup and use) but just in my current project I can't use cookies at all. Meaning Saki's HttpProvider is the only way to go for me right now...

film izle

hd film izle

film sitesi

takipci kazanma sitesi

takipci kazanma sitesi

güzel olan herşey

takipci alma sitesi

komik eğlenceli videolar