PDA

View Full Version : Ext.ux.TabScrollerMenu bugfixes



Lukman
16 Jul 2009, 7:04 AM
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:


/*!
* 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);
}
}
});

mmanners
20 Aug 2009, 9:02 AM
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

jay@moduscreate.com
21 Aug 2009, 4:38 AM
Thanks,
I'll look into integrating this.

andrevio
2 Jul 2012, 1:46 PM
It seems that this bug is still there in 4.0.7 and 4.1