2
votes

I'm trying to make the tabs in tabpanel navigable using arrow keys.

As tabpanel has no key events, my guess was to create a KeyMap or a KeyNav and attach it to the panel this way: This is part of the tabpanel def, it's inside another panel:

activeTab : 0,
xtype : 'tabpanel',
id : 'tabPanel',
alias : 'widget.mainpanels',    
listeners: {
    afterrender: function(tb) {
        this.bindDetailsPanelKeys(tb);
    },
    scope: this
}, [...]

And the function bindDetailsPanelKeys:

bindDetailsPanelKeys: function(tb) {
    console.log(tb); //Checking tb is the correct object.
    var tbMap = new Ext.util.KeyMap(tb, {           
    key: Ext.EventObject.RIGHT,
    fn: function(e) {
        console.log(e);
    // Code to calculate next tab and switch it.
    }
});

console.log(tb) output is as expected, it contains the tab panel object.

But all I receive after that is: Uncaught TypeError: Cannot call method 'on' of null from line var tbMap = new Ext.util.KeyMap(tb, {

I've checked the El property of tb and it's also correct and it has the on method on it's proto as well.

Any help will be very appreciated.

EDIT: I've found the solution. I'll post it in a moment.

Agustin.

2

2 Answers

1
votes

according to documentation the Ext.util.KeyMap object expects a html element or Ext.Element object, so instead of passing tabpanel object you need to pass element of the tabpanel, so you can do something like this and check if its working or not

var tbMap = new Ext.util.KeyMap(tb.getEl(), {           
     key: Ext.EventObject.RIGHT,
     fn: function(e) {
          console.log(e);
          // Code to calculate next tab and switch it.
     }
});
0
votes

Ok, this is how I managed to get around it.

In first place I defined the tabpanel with its tabbar and as follows:

[...]
activeTab : 0,
xtype : 'tabpanel',
id : 'tabPanel',
alias : 'widget.mainpanels',
tabBar: {
    id: 'tabPanelTabBar',
    listeners: {
        afterrender: function(tb, eOpts) {
        this.bindDetailsPanelKeys(tb);
    },
    scope: this
}},[...]

For each tab item I added an attribute 'index' as I'didn't find another way to get the current tab numerical position. Here's an example:

{
    xtype : 'categoryEdit',
    title : 'Detalles Categoría',                                   
    index: 1
}

And the binding function as follows. As Saket Patel suggested I'm giving the KeyMap constructor a reference to the 'el' element of the tab-bar (notice it's TabBar's 'el', not TabPanel's 'el').

bindDetailsPanelKeys: function(tabBar) {
    var tbRightMap = new Ext.util.KeyMap(tabBar.getEl(), { //RIGHT ARROW
        key: Ext.EventObject.RIGHT,
        fn: function(e) {
            var totalItems = tabBar.items.length, //total tabs
            activeTabIndex = tabBar.tabPanel.getActiveTab().index, //current tab index
            nextTabIndex = (activeTabIndex % totalItems) + Math.ceil(activeTabIndex/totalItems) - 1; //Calculate next index    
            tabBar.tabPanel.setActiveTab(nextTabIndex);
        }
});

var tbLeftMap = new Ext.util.KeyMap(tabBar.getEl(), { //LEFT ARROW          
    key: Ext.EventObject.LEFT,
    fn: function(e) {
        var totalItems = tabBar.items.length,
        activeTabIndex = tabBar.tabPanel.getActiveTab().index;
        prevTabIndex = (activeTabIndex == 1) ? 3 : activeTabIndex - 2;
        tabBar.tabPanel.setActiveTab(prevTabIndex);
}
});

I hope somebody finds it useful.