1. #1
    Sencha - Training Team RWaters's Avatar
    Join Date
    Mar 2007
    Location
    Los Angeles, CA
    Posts
    714
    Vote Rating
    0
    RWaters is on a distinguished road

      0  

    Default Ext.ux.GridKeyNav

    Ext.ux.GridKeyNav


    Updated for Ext 3.x, was actually a very minor change. See 2.x version here: http://extjs.com/forum/showthread.php?t=66898

    Code:
    /**
     * @class Ext.ux.GridKeyNav
     * Simple plugin to implement basic keyboard navigation for Ext 2.x grids that have a
     * paging toolbar (required).  Adds: Page Down/Page Up/Right Arrow/Left Arrow/Home/End,
     * also adds functionality to the selection model to see if Down is pressed at the last record
     * of a page or Up is pressed at the first record of the page and attempts to move a page
     * in the proper direction.
     */
    Ext.ux.GridKeyNav = function() {}
    Ext.ux.GridKeyNav.prototype = {
        /**
         * @cfg {Boolean} bottomBar 
         * Look for the paging toolbar within the grids bbar, set to true to pull from tbar (defaults to true)
         */
        bottomBar: true,
        /**
         * @cfg {Ext.PagingToolbar} toolbar
         * Manually pass in a toolbar instead of pulling from bbar/tbar of the grid (in case it is rendered elsewhere)
         */
        toolbar: null,
    
        init: function(grid) {
            this.grid = grid;
            this.grid.on({
                render: this.onRender,
                destroy: this.onDestroy,
                scope: this
            });
        },
        
        onRender : function() {
            this.nav = new Ext.KeyNav(this.grid.getGridEl(),{
                left: this.pagingNav.createDelegate(this,['prev']),
                right: this.pagingNav.createDelegate(this,['next']),
                pageDown: this.pagingNav.createDelegate(this,['next']),
                pageUp: this.pagingNav.createDelegate(this, ['prev']),
                home: this.pagingNav.createDelegate(this,['first']),
                end: this.pagingNav.createDelegate(this,['last'])
            });
            
            this.pt = this.toolbar||((this.bottomBar)?this.grid.getBottomToolbar():this.grid.getTopToolbar());
            this.sm = this.grid.getSelectionModel();
            this.sm.selectNext = this.sm.selectNext.createInterceptor(this.beforeNext, this);
            this.sm.selectPrevious = this.sm.selectPrevious.createInterceptor(this.beforePrevious, this);
        },
        
        onDestroy: function() {
            this.nav.disable();
            delete this.nav;
        },
        
        pagingNav: function(page) {
            if (!this.pt[page].disabled) {
                this.pt.onClick(this.pt[page]);
                if (page === 'last') {
                    this.forceSelectLastRow();
                }
            } else {
                // Is all the data on a single page? If so let home/end work
                if (this.pt.pageSize >= this.grid.getStore().data.length) {
                    if (page == 'first') {
                        this.sm.selectFirstRow();
                    } else if (page == 'last') {
                        this.sm.selectLastRow();
                    }
                }
            }
        },
        
        beforeNext: function() {
            if (!this.sm.hasNext()) {
                this.pagingNav('next');
                return false;
            }
        },
        
        beforePrevious: function() {
            if (!this.sm.hasPrevious()) {
                this.pagingNav('prev');
                this.forceSelectLastRow();
                return false;
            }
        },
        
        forceSelectLastRow: function() {
            this.grid.getStore().on('load', function() {
                this.sm.selectLastRow();
            }, this, {single: true});
        }
    }
    Usage:
    Code:
    new Ext.grid.GridPanel({
        // store, cm, etc.
        bbar: new Ext.PagingToolbar({
            // store, pagesize etc
        }),
        plugins: [new Ext.ux.GridKeyNav()]
    });

  2. #2
    jay@moduscreate.com's Avatar
    Join Date
    Mar 2007
    Location
    Frederick MD, NYC, DC
    Posts
    16,353
    Vote Rating
    77
    jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all jay@moduscreate.com is a name known to all

      0  

    Default


    Awesome to see this ported over.

  3. #3
    Sencha User
    Join Date
    Jun 2008
    Posts
    18
    Vote Rating
    0
    raphac is on a distinguished road

      0  

    Default small changes

    small changes


    Code:
    forceSelectFirstRow: function() {
            this.grid.getStore().on('load',
            function() {
                this.sm.selectFirstRow();
            },
            this, {
                single: true
            });
        },
    
    beforeNext: function() {
            if (!this.sm.hasNext()) {
                this.pagingNav('next');
                this.forceSelectFirstRow();
                return false;
            }
        },
    
    pagingNav: function(page) {
            if (!this.pt[page].disabled) {
                this.pt.onClick(this.pt[page]);
                if (page === 'last') {
                    this.forceSelectLastRow();
                } else {
                    this.forceSelectFirstRow();
                }
            } else {
                // Is all the data on a single page? If so let home/end work
                if (this.pt.pageSize >= this.grid.getStore().data.length) {
                    if (page == 'first') {
                        this.sm.selectFirstRow();
                    } else if (page == 'last') {
                        this.sm.selectLastRow();
                    }
                }
            }
        },

  4. #4
    Sencha User
    Join Date
    Jun 2008
    Posts
    18
    Vote Rating
    0
    raphac is on a distinguished road

      0  

    Default Version with DelayedTask and enter key

    Version with DelayedTask and enter key


    Version with DelayedTask and enter key


    Code:
    /**
    * @class Ext.ux.GridKeyNav
    * Simple plugin to implement basic keyboard navigation for Ext 2.x grids that have a
    * paging toolbar (required).  Adds: Page Down/Page Up/Right Arrow/Left Arrow/Home/End,
    * also adds functionality to the selection model to see if Down is pressed at the last record
    * of a page or Up is pressed at the first record of the page and attempts to move a page
    * in the proper direction.
    */
    Ext.ux.grid.KeyNav = function() {}
    Ext.ux.grid.KeyNav.prototype = {
        /**
        * @cfg {Boolean} bottomBar 
        * Look for the paging toolbar within the grids bbar, set to true to pull from tbar (defaults to true)
        */
        bottomBar: true,
        /**
        * @cfg {Ext.PagingToolbar} toolbar
        * Manually pass in a toolbar instead of pulling from bbar/tbar of the grid (in case it is rendered elsewhere)
        */
        toolbar: null,
        /**
        * @cfg {integer} delayPagNav
        * DelayedTask
        */
        delayPagNav: 500,
        init: function(grid) {
            this.grid = grid;
            this.grid.on({
                render: this.onRender,
                destroy: this.onDestroy,
                scope: this
            });
            this.beforePagingNav = new Ext.util.DelayedTask(function(page) {
                if(page == 'enter')
                    this.enterNav();
                else
                    this.pagingNav(page);
            }, this);
        },
        onRender: function() {
            this.nav = new Ext.KeyNav(this.grid.getGridEl(), {
                'left': function(e) { this.beforePagingNav.delay(this.delayPagNav, null, null, ['prev']) },
                'right': function(e) { this.beforePagingNav.delay(this.delayPagNav, null, null, ['next']) },
                'pageDown': function(e) { this.beforePagingNav.delay(this.delayPagNav, null, null, ['next']) },
                'pageUp': function(e) { this.beforePagingNav.delay(this.delayPagNav, null, null, ['prev']) },
                'home': function(e) { this.beforePagingNav.delay(this.delayPagNav, null, null, ['first']) },
                'end': function(e) { this.beforePagingNav.delay(this.delayPagNav, null, null, ['last']) },
                'enter': function(e) { this.beforePagingNav.delay(this.delayPagNav, null, null, ['enter']) },
                scope: this
            });
    
            this.pt = this.toolbar || ((this.bottomBar) ? this.grid.getBottomToolbar() : this.grid.getTopToolbar());
            this.sm = this.grid.getSelectionModel();
            this.sm.selectNext = this.sm.selectNext.createInterceptor(this.beforeNext, this);
            this.sm.selectPrevious = this.sm.selectPrevious.createInterceptor(this.beforePrevious, this);
        },
        onDestroy: function() {
            if(this.nav) {
                this.nav.disable();
                delete this.nav;
            }
        },
        enterNav: function() {
            if(this.grid.hasListener('rowdblclick')) this.grid.fireEvent('rowdblclick', this.grid);
        },
        pagingNav: function(page) {
            if (!this.pt[page].disabled) {
                switch(page) {
                    case 'next':
                        this.pt.moveNext(); break;
                    case 'prev':
                        this.pt.movePrevious(); break;
                    case 'first':
                        this.pt.moveFirst(); break;
                    case 'last':
                        this.pt.moveLast(); break;
                }
                if (page === 'last')
                    this.forceSelectLastRow();
                else
                    this.forceSelectFirstRow();
            } else {
                // Is all the data on a single page? If so let home/end work
                if (this.pt.pageSize >= this.grid.getStore().data.length) {
                    if (page == 'first') {
                        this.sm.selectFirstRow();
                    } else if (page == 'last') {
                        this.sm.selectLastRow();
                    }
                }
            }
        },
        beforeNext: function() {
            if (!this.sm.hasNext()) {
                this.beforePagingNav.delay(this.delayPagNav, null, null, ['next']);
                this.forceSelectFirstRow();
                return false;
            }
        },
        beforePrevious: function() {
            if (!this.sm.hasPrevious()) {
                this.beforePagingNav.delay(this.delayPagNav, null, null, ['prev']);
                this.forceSelectLastRow();
                return false;
            }
        },
        forceSelectFirstRow: function() {
            this.grid.getStore().on('load',
            function() {
                this.sm.selectFirstRow();
                this.grid.getView().focusEl.focus();
            },
            this, {
                single: true
            });
        },
        forceSelectLastRow: function() {
            this.grid.getStore().on('load',
            function() {
                this.sm.selectLastRow();
                this.grid.getView().focusEl.focus();
            },
            this, {
                single: true
            });
        }
    }

  5. #5
    Ext User
    Join Date
    Oct 2007
    Posts
    5
    Vote Rating
    0
    simon1118 is on a distinguished road

      0  

    Default


    Great work, nice!