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

Thread: ExtJS Adapter for History.js

  1. #1

    Default ExtJS Adapter for History.js

    I wrote a history.js adapter for Ext (version 4.1, but should work for 4.0), and I thought I would share it with the world:

    Code:
    /**
     * History.js ExtJS Adapter
     * @author Sean Adkinson <[email protected]>
     * @copyright 2012 Sean Adkinson <[email protected]>
     * @license New BSD License <http://creativecommons.org/licenses/BSD/>
     */
    
    // Closure
    (function(window,undefined){
        "use strict";
    
        // Localise Globals
        var
            History = window.History = window.History||{};
    
        window.JSON = {
            stringify: Ext.JSON.encode,
            parse: Ext.JSON.decode
        };
        
        // Check Existence
        if ( typeof History.Adapter !== 'undefined' ) {
            throw new Error('History.js Adapter has already been loaded...');
        }
    
        // Add the Adapter
        History.Adapter = {
            observables: {},
            
            /**
             * History.Adapter.bind(el,event,callback)
             * @param {Element|string} el
             * @param {string} event - custom and standard events
             * @param {function} callback
             * @param {Object} scope
             * @return {void}
             */
            bind: function(element,eventName,callback,scope){
                Ext.EventManager.addListener(element, eventName, callback, scope);
                
                //bind an observable to the element that will let us "trigger" events on it
                var id = Ext.id(element, 'history-');
                var observable = this.observables[id];
                if (!observable) {
                    observable = Ext.create('Ext.util.Observable');
                    this.observables[id] = observable;
                }
                observable.on(eventName, callback, scope);
            },
    
            /**
             * History.Adapter.trigger(el,event)
             * @param {Element|string} el
             * @param {string} event - custom and standard events
             * @param {Object=} extra - a object of extra event data (optional)
             * @return {void}
             */
            trigger: function(element,eventName,extra){
                var id = Ext.id(element, 'history-');
                var observable = this.observables[id];
                if (observable) {
                    observable.fireEvent(eventName, extra);
                }
            },
    
            /**
             * History.Adapter.extractEventData(key,event,extra)
             * @param {string} key - key for the event data to extract
             * @param {string} event - custom and standard events
             * @param {Object=} extra - a object of extra event data (optional)
             * @return {mixed}
             */
            extractEventData: function(key,event,extra){
                var result = (event && event.browserEvent && event.browserEvent[key]) || (extra && extra[key]) || undefined;
                return result;
            },
    
            /**
             * History.Adapter.onDomLoad(callback)
             * @param {function} callback
             * @return {void}
             */
            onDomLoad: function(callback) {
                Ext.onReady(callback);
            }
        };
    
        // Try and Initialise History
        if ( typeof History.init !== 'undefined' ) {
            History.init();
        }
    
    })(window);
    Last edited by BigSeanDawg; 25 Jul 2012 at 3:15 PM. Reason: Added scope per Ronaldo's suggestion

  2. #2
    Sencha Premium User mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    40,450

    Default

    Moved to the extensions/plugins forum
    Mitchell Simoens @LikelyMitch
    Modus Create, Senior Fullstack Engineer
    ________________
    Modus Create is based on the model of an open source team. We’re a remote, global team of experts in our field. To find out more about the work we do, head over to our website.

    Check out my GitHub:
    https://github.com/mitchellsimoens

  3. #3
    Sencha Premium Member Ronaldo's Avatar
    Join Date
    Jul 2007
    Location
    Enschede, The Netherlands
    Posts
    299

    Default Added scope

    Sweet! We were just investigating history.js.

    I do have a minor improvement; it's nice if you can pass an optional scope so that the callback method
    is called in it's own scope.

    Code:
            bind: function(element,eventName,callback,scope){
                Ext.EventManager.addListener(element, eventName, callback, scope);
                
    //bind an observable to the element that will let us "trigger" events on it
                var id = Ext.id(element, 'history-');
                var observable = this.observables[id];
                if (!observable) {
                    observable = Ext.create('Ext.util.Observable');
                    this.observables[id] = observable;
                }
                observable.on(eventName, callback, scope);
            },
    Ronald van Raaphorst aka Ronaldo
    I'm a freelance software developer in Java, PHP, and ExtJs.


    Skyperonald_twensoc
    Mail[email protected]

  4. #4

    Default

    EDIT: Updated the original post with your suggestion Ronaldo. Thanks!

  5. #5
    Touch Premium Member
    Join Date
    Aug 2011
    Posts
    96

    Default A small example perhaps?

    Any chance on how to use this with Ext JS MVC app?
    A small example perhaps...


    Also, you may want to send a pull request to author to include this in:
    https://github.com/balupton/history.js/tree/master/vendor



  6. #6
    Sencha User bclinton's Avatar
    Join Date
    Nov 2007
    Posts
    305

    Default An example

    I came upon this adapter while looking for a way to manage my application's routing and history, and like abcoa I also could have used an MVC example. But I think I was able to work it out and created a simple example of its use in an MVC app. There may be better ways to do this and I am open to suggestions.

    The example code is here: https://github.com/BillClinton/histo...dapter-example
    And there is a demo of this code here: http://appunto.net/examples/history-example/?clients

    The good news is that this adapter is now comes as part of History.js. You will find the ExtJs version in the history.js/scripts/bundled directory after you download history.js.

    After including the extjs.history.js in your html file (or perhaps adding it to your Sencha command app.classpath) You can initialize it in your application launch like this:
    Code:
            var History = window.History;
    
    
            // Try and Initialise History
            if ( typeof History.init !== 'undefined' ) {
                console.log('Initializing History...');
                History.init();
            }
    you then bind it to the window's statechange event like this:
    Code:
            var History = window.History;
    
    
            History.Adapter.bind(window, 'statechange', this.chooseView, this);
    (I did this in my Viewport's afterrender handler, in a "Menu" controller.


    then write the handler that will handle the event
    Code:
    chooseView: function() {
    
    
            var History = window.History,
                State   = History.getState(),
                route   = State.title;
    
    
            if (route == "something") 
            {
                //do stuff
            }
            else if (route == "something_else") 
            {
                // do something else
            } 
            else
            {
                // unrecognized route, do default action
            }
    }

    To set the page url and trigger your 'statechange' handler, just call the the pushState function:
    Code:
            var History = window.History;
            History.pushState({data:"any kind of data object"}, "Settings", "?settings");
    or use one of History's other functions like back() or forward() to traverse your application history

    The ability to pass a json object as the first parameter of the pushState function makes things very flexible, but one thing that is conspicuously absent is the ability to route requests that are not yet in the user's history. For example, if you do something like this
    Code:
            var History = window.History,
                my_id;
                
            my_id = rec.id // some value, perhaps passed by a button click or grid slection
    
    
            History.pushState({client_id:my_id}, "client-view", "?client="+my_id");
    You can retrieve the id from the data object in the statechange handler (History.data.client_id), and since this state will be saved in the user's history, subsequent visits to this page (?client=x) will still contain this data object. But what if you want the user to be able to call a URL with parameters directly? Perhaps you want them to be able to click a link in an email like http://my-domain.com/myapp/user/view?client=467 . In this case, you have not set up this request in the browsers history with a call to History.pushState that encapsulates the client_id parameter in a data object.

    It seems your best best if you need this kind of functionality is to write your statechange handler so it directs requests based on url parameters rather than assuming the request came from an internal call to History.pushState. If you want your application to respond to manually inputted URLs, you can't count on that .pushstate() data object being there. I left some comments on this and a very simplified solution in the comments above the chooseView function in my example's Menu controller.

    But I'd refer people looking for a more polished, flexible approach to Bruno Tavares' ExtJS Router for ideas: https://github.com/brunotavares/Ext.ux.Router . You should be able to incorporate his routing techniques with the History.js ExtJs adapter and come up with something that will be both elegant and functional.

  7. #7
    Sencha Premium User mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    40,450

    Default

    I will be speaking about history support in Ext JS tomorrow at SenchaCon. Have new features to make this very simple to handle in an MVC application.
    Mitchell Simoens @LikelyMitch
    Modus Create, Senior Fullstack Engineer
    ________________
    Modus Create is based on the model of an open source team. We’re a remote, global team of experts in our field. To find out more about the work we do, head over to our website.

    Check out my GitHub:
    https://github.com/mitchellsimoens

  8. #8
    Sencha User bclinton's Avatar
    Join Date
    Nov 2007
    Posts
    305

    Default

    Great! I'm not at SenchaCon, but I look forward to hearing about it.

    I hope you will address backwards compatibility with non HTML5 browsers and inconsistencies between the history implementations of the various browsers. These issues are why I felt the need to turn to the history.js library and I'd love to know if there are ways to alleviate these concerns without a 3rd party library.

  9. #9
    Sencha Premium User mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    40,450

    Default

    Quote Originally Posted by bclinton View Post
    Great! I'm not at SenchaCon, but I look forward to hearing about it.

    I hope you will address backwards compatibility with non HTML5 browsers and inconsistencies between the history implementations of the various browsers. These issues are why I felt the need to turn to the history.js library and I'd love to know if there are ways to alleviate these concerns without a 3rd party library.
    What I've created is a Router to make setting up routes in a controller easy and uses the Ext.util.History as the actual history mechanism which of course works even in IE6 so it will work for all supported Ext JS 4 browsers.
    Mitchell Simoens @LikelyMitch
    Modus Create, Senior Fullstack Engineer
    ________________
    Modus Create is based on the model of an open source team. We’re a remote, global team of experts in our field. To find out more about the work we do, head over to our website.

    Check out my GitHub:
    https://github.com/mitchellsimoens

  10. #10
    Sencha User bclinton's Avatar
    Join Date
    Nov 2007
    Posts
    305

    Default

    Hey, any more news on this? Is there video of your presentation or demonstration code available somewhere?

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

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