1. #1
    Ext User Lukman's Avatar
    Join Date
    Jun 2009
    Location
    Malaysia
    Posts
    138
    Vote Rating
    0
    Lukman is on a distinguished road

      0  

    Default Ext.ux.TabScrollerMenu bugfixes

    Ext.ux.TabScrollerMenu bugfixes


    Playing around with Tab Scroller Menu sample (examples/tabs/tab-scroller-menu.html) I noticed two bugs (or I would rather call them peculiarities):

    1. Setting pageSize = 1 creates tab scroller menu with "Items 1-1", "Items 2-2" all the way to "Items 23-23" with each of them containing submenu with 1 item. It makes more sense if the scroller menu has no submenus; the menu items for the tabs should be on the first menu level.

    2. If or when number of tabs < pageSize, the menu doesn't work.

    It turns out that for peculiarity 1, there is no special algorithm to cater the case when pageSize = 1. I can accept that. But for peculiarity 2, it is definitely a bug since there is a condition that checks if number of tabs > pageSize, BUT the code in the "else" part (i.e. when number of tabs <= pageSize) does not work as if it has not been tested at all before including it into the package.

    So here is my fixed ux js file (examples/ux/TabScrollerMenu.js). It fixes both peculiarities by creating a single-level scroller menu instead of the weird "Items X-Y" submenus if pageSize <= 1 or when the number of tabs is less than pageSize. Changed code is in bold:

    Code:
    /*!
     * Ext JS Library 3.0.0
     * Copyright(c) 2006-2009 Ext JS, LLC
     * licensing@extjs.com
     * http://www.extjs.com/license
     */
    
    
    Ext.ux.TabScrollerMenu =  Ext.extend(Object, {
        pageSize       : 10,
        maxText        : 15,
        menuPrefixText : 'Items',
        constructor    : function(config) {
            config = config || {};
            Ext.apply(this, config);
        },
        init : function(tabPanel) {
            Ext.apply(tabPanel, this.tabPanelMethods);
            
            tabPanel.tabScrollerMenu = this;
            var thisRef = this;
            
            tabPanel.on({
                render : {
                    scope  : tabPanel,
                    single : true,
                    fn     : function() { 
                        var newFn = tabPanel.createScrollers.createSequence(thisRef.createPanelsMenu, this);
                        tabPanel.createScrollers = newFn;
                    }
                }
            });
        },
        // private && sequeneced
        createPanelsMenu : function() {
            var h = this.stripWrap.dom.offsetHeight;
            
            //move the right menu item to the left 18px
            var rtScrBtn = this.header.dom.firstChild;
            Ext.fly(rtScrBtn).applyStyles({
                right : '18px'
            });
            
            var stripWrap = Ext.get(this.strip.dom.parentNode);
            stripWrap.applyStyles({
                 'margin-right' : '36px'
            });
            
            // Add the new righthand menu
            var scrollMenu = this.header.insertFirst({
                cls:'x-tab-tabmenu-right'
            });
            scrollMenu.setHeight(h);
            scrollMenu.addClassOnOver('x-tab-tabmenu-over');
            scrollMenu.on('click', this.showTabsMenu, this);    
            
            this.scrollLeft.show = this.scrollLeft.show.createSequence(function() {
                scrollMenu.show();                                                                          
            });
            
            this.scrollLeft.hide = this.scrollLeft.hide.createSequence(function() {
                scrollMenu.hide();                                
            });
            
        },
        // public
        getPageSize : function() {
            return this.pageSize;
        },
        // public
        setPageSize : function(pageSize) {
            this.pageSize = pageSize;
        },
        // public
        getMaxText : function() {
            return this.maxText;
        },
        // public
        setMaxText : function(t) {
            this.maxText = t;
        },
        getMenuPrefixText : function() {
            return this.menuPrefixText;
        },
        setMenuPrefixText : function(t) {
            this.menuPrefixText = t;
        },
        // private && applied to the tab panel itself.
        tabPanelMethods : {
            // all execute within the scope of the tab panel
            // private    
            showTabsMenu : function(e) {        
                if (! this.tabsMenu) {
                    this.tabsMenu =  new Ext.menu.Menu();
                    this.on('beforedestroy', this.tabsMenu.destroy, this.tabsMenu);
                }
                
                this.tabsMenu.removeAll();
                
                this.generateTabMenuItems();
                
                var target = Ext.get(e.getTarget());
                var xy     = target.getXY();
                
                //Y param + 24 pixels
                xy[1] += 24;
                
                this.tabsMenu.showAt(xy);
            },
            // private    
            generateTabMenuItems : function() {
                var curActive  = this.getActiveTab();
                var totalItems = this.items.getCount();
                var pageSize   = this.tabScrollerMenu.getPageSize();
                
                
                if (pageSize > 1 && totalItems > pageSize)  {
                    var numSubMenus = Math.floor(totalItems / pageSize);
                    var remainder   = totalItems % pageSize;
                    
                    // Loop through all of the items and create submenus in chunks of 10
                    for (var i = 0 ; i < numSubMenus; i++) {
                        var curPage = (i + 1) * pageSize;
                        var menuItems = [];
                        
                        
                        for (var x = 0; x < pageSize; x++) {                
                            index = x + curPage - pageSize;
                            var item = this.items.get(index);
                            menuItems.push(this.autoGenMenuItem(item));
                        }
                        
                        this.tabsMenu.add({
                            text : this.tabScrollerMenu.getMenuPrefixText() + ' '  + (curPage - pageSize + 1) + ' - ' + curPage,
                            menu : menuItems
                        });
                        
                    }
                    // remaining items
                    if (remainder > 0) {
                        var start = numSubMenus * pageSize;
                        menuItems = [];
                        for (var i = start ; i < totalItems; i ++ ) {                    
                            var item = this.items.get(i);
                            menuItems.push(this.autoGenMenuItem(item));
                        }
                        
                        
                        this.tabsMenu.add({
                            text : this.tabScrollerMenu.menuPrefixText  + ' ' + (start + 1) + ' - ' + (start + menuItems.length),
                            menu : menuItems
                        });
                        
    
                    }
                }
                else {
                    this.items.each(function(item) {
                        this.tabsMenu.add(this.autoGenMenuItem(item));
                    }, this);
                }    
            },
            // private
            autoGenMenuItem : function(item) {
                var maxText = this.tabScrollerMenu.getMaxText();
                var text    = Ext.util.Format.ellipsis(item.title, maxText);
                
                return {
                    text      : text,
                    handler   : this.showTabFromMenu,
                    scope     : this,
                    disabled  : item.disabled,
                    tabToShow : item,
                    iconCls   : item.iconCls
                }
            
            },
            // private
            showTabFromMenu : function(menuItem) {
                this.setActiveTab(menuItem.tabToShow);
            }    
        }    
    });

  2. #2
    Ext JS Premium Member
    Join Date
    May 2009
    Posts
    2
    Vote Rating
    0
    mmanners is on a distinguished road

      0  

    Smile Thanks for the changed code

    Thanks for the changed code


    I just ran into the same problem with the tab-scroller. I found your code, replaced the file, and now things work as expected.

    Thanks for posting

  3. #3
    jay@moduscreate.com's Avatar
    Join Date
    Mar 2007
    Location
    Frederick MD, NYC, DC
    Posts
    16,360
    Vote Rating
    81
    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


    Thanks,
    I'll look into integrating this.

  4. #4
    Sencha User
    Join Date
    Dec 2011
    Posts
    20
    Vote Rating
    4
    andrevio is on a distinguished road

      0  

    Default


    It seems that this bug is still there in 4.0.7 and 4.1