PDA

View Full Version : [FIXED-389][3.1] GroupTabPanel Group/Tab change..



robindel
17 Dec 2009, 5:25 AM
Ext version tested:


Ext 3.1 rev 5770-119



Adapter used:


ext




Browser versions tested against:


IE8
FF3.5 (firebug 1.4.5 installed)



Operating System:


WinXP Pro



Description:
It seems that the GroupTabPanel's behaviour has been modified by the changes in TabPanel.
The bug appears when switching between groups.
You can't come back to the last visited item of a group.:-?
You can switch between items of any given groups freely, but you can't go back to a given group by selecting the item that was active when you left the group.

Hope the explanation was clear, but you can play around on the example page http://www.extjs.com/deploy/dev/examples/grouptabs/grouptabs.html to understand it better..

I'll play around with Firebug and try to see where it comes from. Will come back with more info as soon as I have some.

Edit: First level debugging:
When clicking on the previously active item of a group, no call to setActiveGroup is made. But why:-/

Edit2:

Awwright... Found it!
In grouptab.js, the method setActiveTab does this test:

if( this.activeTab != item && this.fireEvent('beforetabchange', this, item, this.activeTab) !== false)

When you change group, the group's activeTab remains what it was before, therefore the test fails if you try to activate this tab again..

Fix:
in GroupTabPanel.js, method setActiveGroup:


if(this.activeGroup != group && this.fireEvent('beforegroupchange', this, group, this.activeGroup) !== false){
if(this.activeGroup){
this.activeGroup.activeTab=null;
var oldEl = this.getGroupEl(this.activeGroup);
if(oldEl){
Ext.fly(oldEl).removeClass('x-grouptabs-strip-active');
}
}




rob'

mystix
17 Dec 2009, 11:59 AM
quick check -- did you rename your thread to [FIXED], or did someone else do it?

aw1zard2
17 Dec 2009, 12:07 PM
I think we are reporting the same thing I just havent had time to troubleshoot anything cause i've been in meetings all day.

:)

mystix
17 Dec 2009, 12:09 PM
marked this thread [DUP] in light of other report:
http://www.extjs.com/forum/showthread.php?t=88005

robindel
17 Dec 2009, 12:48 PM
@mystix: nope, did not rename.. But I am interested in knowing if the fix I proposed is "right" (fix'd by setting the value bak to init value isn't always the right thing to do).

@aw1zard2: yes we are. Only I'm currently developping an app that uses GroupTabPanels (for a reason I don't want to know but that might come from the 'iGoogle'y look and feel of the thing)

@all: by the way, what is the status of the ux'es? Are they "examples" as aw1zard2 implies in his post title (as in "provided without support, use at you own risk") or are they some kind of "advanced widgets" (as in "created by extending existing stuff but not worthy the widget status")?

rob'

aw1zard2
17 Dec 2009, 12:58 PM
I have a working beta that uses it as well as custom mobile web components for phones and touchscreens. I was just testing out the examples that our beta product is using and found a few things that don't work the same way.

LOL

:)

Yes the Grouptabs is considered a UX but the fix should be in place since it is listed on the main examples and sent out with the zip download.

:D

josh803316
17 Dec 2009, 1:46 PM
I tested the posted fix out and am still getting errors. Not sure if that was the final fix but I thought I would test it out since I need it to work :)

tip.triggerElement is undefined
http://localhost/lib/ext/examples/ux/GroupTab.js
Line 122

josh803316
17 Dec 2009, 1:49 PM
Scratch that last error: looks like it was a cache issue with the fix.....I'm testing it out and so far the fix works great

rlegend
18 Dec 2009, 12:23 PM
If fixed this problem with the following change in GroupTab.js in the setActiveTab method

setActiveTab : function(item){
item = this.getComponent(item);
if(!item){
return false;
}
if(!this.rendered){
this.activeTab = item;
return true;
}
if(this.fireEvent('beforetabchange', this, item, this.activeTab) !== false && this.activeTab != item){
if(this.activeTab && this.activeTab != this.mainItem){
var oldEl = this.getTabEl(this.activeTab);
if(oldEl){
Ext.fly(oldEl).removeClass('x-grouptabs-strip-active');
}
}
var el = this.getTabEl(item);
Ext.fly(el).addClass('x-grouptabs-strip-active');
this.activeTab = item;
this.stack.add(item);

this.layout.setActiveItem(item);
if(this.layoutOnTabChange && item.doLayout){
item.doLayout();
}
if(this.scrolling){
this.scrollToTab(item, this.animScroll);
}

this.fireEvent('tabchange', this, item);
return true;
}
return false;
},
I basically swapped the order of the arguments in the if statement. I stumbled upon this when I was doing a console.log of the fireEvent output before the if statement and the tab switching suddenly started working.

robindel
18 Dec 2009, 12:38 PM
I must admit this is quite elegant.. I think this works (will confirm over the weekend) and will fix the damn thing..
Thanks..

Nam
20 Dec 2009, 10:21 PM
I noticed this as well, and your post helped me fix the problem, but I have found another problem with the new grouptabpanel as well...

If I add a tab using the following process...


Ext.getCmp('GroupPanel').add({
expanded: true,
hidden: true,
name: 'SiteGroup',
deferredRender: true,
mainItem: 0,
items: [{
title: 'Sites',
iconCls: 'icon-cog',
tabTip: 'This will allow you to configure your protected sites.',
style: 'padding: 10px;'
}]
});

I get the following error in firebug...

this.itemTpl is undefined
anonymous(Object initialConfig=Object expanded=true hidden=true, 3)ext-all-debug.js (line 26173)
anonymous(Object initialConfig=Object expanded=true hidden=true)ext-all-debug.js (line 26236)
anonymous(Object expanded=true hidden=true name=SiteGroup)ext-all-debug.js (line 11373)
anonymous(Object data=Object baseParams=Object removed=[0], [Object id=55 data=Object json=Object store=Object 0=Object], Object params=Object)cp (line 617)
anonymous()ext-all-debug.js (line 1577)
anonymous()ext-all-debug.js (line 1324)
anonymous(Object success=true records=[1] totalRecords=1, Object params=Object, true)ext-all-debug.js (line 20332)
anonymous("read", Object method=POST request=Object reader=Object, Object)ext-all-debug.js (line 21475)
anonymous(Object method=POST request=Object reader=Object, true, Object)ext-all-debug.js (line 21439)
anonymous(Object)ext-all-debug.js (line 6295)
anonymous(XMLHttpRequest readyState=0 status=200 statusText=OK, "success")ext-jque...dapter.js (line 7)
complete()jquery.js (line 2790)
anonymous(Object name=isTimeout value=0)jquery.js (line 2740)
[Break on this error] this.itemTpl.insertBefore(before, p) :


I have been trying to figure out a fix, but so far, no luck. Can anyone who is more experienced with this provide some insight?

Thanks,

rlegend
21 Dec 2009, 9:22 AM
Hey Nam,

We should start a new thread about 'unable to add/remove' items for the Group Tab Panel.

I've cobbled together a version of GroupTab.js that appears to solve the issue though I'm sure it's not 100% correct. From what I can tell the add method in the SuperClass(in this case Ext.Container) isn't calling onAdd with the arguments that GroupTab is expecting. I've added modified versions of the Add and doRemove methods to GroupTab.js and it appears to be working ok in my project. I'm sure doRemove can use some work because I had to resort to some hacks for it to actually remove the dom element from the tab panel.

Hope this is helpful.

Ron


/*!
* Ext JS Library 3.1.0
* Copyright(c) 2006-2009 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
*/
Ext.ux.GroupTab = Ext.extend(Ext.Container, {
mainItem: 0,

expanded: true,

deferredRender: true,

activeTab: null,

idDelimiter: '__',

headerAsText: false,

frame: false,

hideBorders: true,

initComponent: function(config){
Ext.apply(this, config);
this.frame = false;

Ext.ux.GroupTab.superclass.initComponent.call(this);

this.addEvents('activate', 'deactivate', 'changemainitem', 'beforetabchange', 'tabchange');

this.setLayout(new Ext.layout.CardLayout({
deferredRender: this.deferredRender
}));

if (!this.stack) {
this.stack = Ext.TabPanel.AccessStack();
}

this.initItems();

this.on('beforerender', function(){
this.groupEl = this.ownerCt.getGroupEl(this);
}, this);

//there was a bug with double calls to onAdd so I commented this out.
// this.on('add', this.onAdd, this, {
// target: this
// });
this.on('remove', this.onRemove, this, {
target: this
});

if (this.mainItem !== undefined) {
var item = (typeof this.mainItem == 'object') ? this.mainItem : this.items.get(this.mainItem);
delete this.mainItem;
this.setMainItem(item);
}
},

/**
* Sets the specified tab as the active tab. This method fires the {@link #beforetabchange} event which
* can return false to cancel the tab change.
* @param {String/Panel} tab The id or tab Panel to activate
*/
setActiveTab : function(item){
item = this.getComponent(item);
if(!item){
return false;
}
if(!this.rendered){
this.activeTab = item;
return true;
}

//fix for the odd tab changing behavior
if(this.fireEvent('beforetabchange', this, item, this.activeTab) !== false && this.activeTab != item){
if(this.activeTab && this.activeTab != this.mainItem){
var oldEl = this.getTabEl(this.activeTab);
if(oldEl){
Ext.fly(oldEl).removeClass('x-grouptabs-strip-active');
}
}
var el = this.getTabEl(item);
Ext.fly(el).addClass('x-grouptabs-strip-active');
this.activeTab = item;
this.stack.add(item);

this.layout.setActiveItem(item);
if(this.layoutOnTabChange && item.doLayout){
item.doLayout();
}
if(this.scrolling){
this.scrollToTab(item, this.animScroll);
}

this.fireEvent('tabchange', this, item);
return true;
}
return false;
},

getTabEl: function(item){
if (item == this.mainItem) {
return this.groupEl;
}
return Ext.TabPanel.prototype.getTabEl.call(this, item);
},

onRender: function(ct, position){
Ext.ux.GroupTab.superclass.onRender.call(this, ct, position);

this.strip = Ext.fly(this.groupEl).createChild({
tag: 'ul',
cls: 'x-grouptabs-sub'
});

this.tooltip = new Ext.ToolTip({
target: this.groupEl,
delegate: 'a.x-grouptabs-text',
trackMouse: true,
renderTo: document.body,
listeners: {
beforeshow: function(tip) {
var item = (tip.triggerElement.parentNode === this.mainItem.tabEl)
? this.mainItem
: this.findById(tip.triggerElement.parentNode.id.split(this.idDelimiter)[1]);

if(!item.tabTip) {
return false;
}
tip.body.dom.innerHTML = item.tabTip;
},
scope: this
}
});

if (!this.itemTpl) {
var tt = new Ext.Template('<li class="{cls}" id="{id}">', '<a onclick="return false;" class="x-grouptabs-text {iconCls}">{text}</a>', '</li>');
tt.disableFormats = true;
tt.compile();
Ext.ux.GroupTab.prototype.itemTpl = tt;
}

this.items.each(this.initTab, this);
},

afterRender: function(){
Ext.ux.GroupTab.superclass.afterRender.call(this);

if (this.activeTab !== undefined) {
var item = (typeof this.activeTab == 'object') ? this.activeTab : this.items.get(this.activeTab);
delete this.activeTab;
this.setActiveTab(item);
}
},

// private
initTab: function(item, index){
var before = this.strip.dom.childNodes[index];
var p = Ext.TabPanel.prototype.getTemplateArgs.call(this, item);

if (item === this.mainItem) {
item.tabEl = this.groupEl;
p.cls += ' x-grouptabs-main-item';
}

var el = before ? this.itemTpl.insertBefore(before, p) : this.itemTpl.append(this.strip, p);

item.tabEl = item.tabEl || el;

item.on('disable', this.onItemDisabled, this);
item.on('enable', this.onItemEnabled, this);
item.on('titlechange', this.onItemTitleChanged, this);
item.on('iconchange', this.onItemIconChanged, this);
item.on('beforeshow', this.onBeforeShowItem, this);
},

setMainItem: function(item){
item = this.getComponent(item);
if (!item || this.fireEvent('changemainitem', this, item, this.mainItem) === false) {
return;
}

this.mainItem = item;
},

getMainItem: function(){
return this.mainItem || null;
},

// private
onBeforeShowItem: function(item){
if (item != this.activeTab) {
this.setActiveTab(item);
return false;
}
},

// private
onAdd: function(gt, item, index) {
if (this.rendered) {
this.initTab.call(this, item, index);
}
},


// private
onRemove: function(tp, item){
Ext.destroy(Ext.get(this.getTabEl(item)));
this.stack.remove(item);
item.un('disable', this.onItemDisabled, this);
item.un('enable', this.onItemEnabled, this);
item.un('titlechange', this.onItemTitleChanged, this);
item.un('iconchange', this.onItemIconChanged, this);
item.un('beforeshow', this.onBeforeShowItem, this);
if (item == this.activeTab) {
var next = this.stack.next();
if (next) {
this.setActiveTab(next);
}
else if (this.items.getCount() > 0) {
this.setActiveTab(0);
}
else {
this.activeTab = null;
}
}
},

// private
onBeforeAdd: function(item){
var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
if (existing) {
this.setActiveTab(item);
return false;
}
Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
var es = item.elements;
item.elements = es ? es.replace(',header', '') : es;
item.border = (item.border === true);
},

// private
onItemDisabled: Ext.TabPanel.prototype.onItemDisabled,
onItemEnabled: Ext.TabPanel.prototype.onItemEnabled,

// private
onItemTitleChanged: function(item){
var el = this.getTabEl(item);
if (el) {
Ext.fly(el).child('a.x-grouptabs-text', true).innerHTML = item.title;
}
},

//private
onItemIconChanged: function(item, iconCls, oldCls){
var el = this.getTabEl(item);
if (el) {
Ext.fly(el).child('a.x-grouptabs-text').replaceClass(oldCls, iconCls);
}
},

beforeDestroy: function(){
Ext.TabPanel.prototype.beforeDestroy.call(this);
this.tooltip.destroy();
},

//add method taken from Ext.Container, modified to call onAdd with the correct arguments
add: function(comp) {
this.initItems();
var args = arguments.length > 1;
if (args || Ext.isArray(comp)) {
var result = [];
Ext.each(args ? arguments: comp,
function(c) {
result.push(this.add(c));
},
this);
return result;
}
var c = this.lookupComponent(this.applyDefaults(comp));
var index = this.items.length;
if (this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false) {
this.items.add(c);

c.onAdded(this, index);
this.onAdd(this, c, index);
// this.fireEvent('add', this, c, index);
}
return c;
},


//hacked version of doRemove from Ext.Container, I'm sure this isn't right but it 'appears' to be working
doRemove: function(c, autoDestroy) {
if (this.layout && this.rendered) {
this.layout.onRemove(c);
}
this.items.remove(c);
c.onRemoved();
this.onRemove(this,c);
if (autoDestroy === true || (autoDestroy !== false && this.autoDestroy)) {
c.destroy();
Ext.get(c.tabEl).remove();
}
}

});

Ext.reg('grouptab', Ext.ux.GroupTab);

hendricd
21 Dec 2009, 12:36 PM
To confirm, OP's issue was resolved by REV 5797.

Changing to FIXED.

Please report your new issues on a new thread.