PDA

View Full Version : TabPanel events



Jangla
24 Sep 2009, 7:34 AM
Can someone help me out with some events?

If I have this set up in a tabpanel:



var tabs = new Ext.TabPanel({
renderTo : 'super-tab-panel',
minTabWidth : 115,
autoWidth : false,
enableTabScroll : true,
width : 680,
height : 530,
defaults : {autoScroll:true, split: true},
activeTab : 0,
items :
[{
id : 'filter-properties-tab',
layout : 'border',
title : 'Filter property list',
items : [filterListPanel, propertyGrid]
},{
id : 'map-properties-panel',
layout : 'border',
title : 'Filter on map',
listeners:{
activate: function(panel){
if ( !mapLoaded ) {
myMarkers = new Ext.data.JsonStore({
proxy : new Ext.data.ScriptTagProxy({
url : 'index.php?eID=tx_supersearch_pi1&mode=map',
callbackParam : 'loadMarkerCallBack'
}),
reader : new Ext.data.JsonReader({
root : 'Data',
fields : ['id', 'marker', 'lat', 'lng']
}),

});
myMarkers.load();
}
}
},
items : [
filterMapPanel,
{
title : '',
layout : 'fit',
xtype : 'gmappanel',
border : false,
id : 'property-map',
region : 'center',
height : 200,
margins : '1 1 1 1',
cmargins : '1 1 1 1',
gmapType : 'map',
mapConfOpts : ['enableScrollWheelZoom','enableDoubleClickZoom','enableDragging'],
mapControls : ['GSmallMapControl'],
setCenter: {
lat: 45.5679096098613,
lng: 0.791015625
}
}
],
},{

title : 'Availability search',
html : 'Availability search'
},{
title : 'Property list',
defaults : {autoScroll:true},
contentEl : 'property-list'
},
{
title : 'Special offers',
html : 'Special offers'
},
{
title : 'Featured properties',
html : 'Featured properties'
}]
});
tabs.doLayout();


...I would expect the listener to fire once the tab is rendered on screen, regardless of whether it was the active tab or not. In this example, this would result in the gmappanel being populated while the user was looking at the first tab.

In reality though, the gmappanel isn't populated until the tab is activated, thus making the event useless - I may as well use the actived event.

Anyone able to help? As hinted at, the ideal solution for me is to have the map render and the markers all added while the user is still looking at the first tab.

hendricd
24 Sep 2009, 7:48 AM
@Jangla --
To render all tabs at once, use the deferredRender cfg option:



var tabs = new Ext.TabPanel({
renderTo : 'super-tab-panel',
minTabWidth : 115,
autoWidth : false,
enableTabScroll : true,
width : 680,
height : 530,
deferredRender : false, //render all at once
defaults : {autoScroll:true, split: true},
activeTab : 0,
items :
[{
id : 'filter-properties-tab',
layout : 'border',
title : 'Filter property list',
items : [filterListPanel, propertyGrid]
},{
id : 'map-properties-panel',
layout : 'border',
title : 'Filter on map',
listeners:{
activateafterrender: function(panel){ //only do this once ?
if ( !mapLoaded ) {
myMarkers = new Ext.data.JsonStore({
proxy : new Ext.data.ScriptTagProxy({
url : 'index.php?eID=tx_supersearch_pi1&mode=map',
callbackParam : 'loadMarkerCallBack'
}),
reader : new Ext.data.JsonReader({
root : 'Data',
fields : ['id', 'marker', 'lat', 'lng']
}),

});
myMarkers.load();
}
}
},
items : [
filterMapPanel,
{
title : '',
layout : 'fit',
xtype : 'gmappanel',
border : false,
id : 'property-map',
region : 'center',
height : 200,
margins : '1 1 1 1',
cmargins : '1 1 1 1',
gmapType : 'map',
mapConfOpts : ['enableScrollWheelZoom','enableDoubleClickZoom','enableDragging'],
mapControls : ['GSmallMapControl'],
setCenter: {
lat: 45.5679096098613,
lng: 0.791015625
}
}
],
},{

title : 'Availability search',
html : 'Availability search'
},{
title : 'Property list',
defaults : {autoScroll:true},
contentEl : 'property-list'
},
{
title : 'Special offers',
html : 'Special offers'
},
{
title : 'Featured properties',
html : 'Featured properties'
}]
});
tabs.doLayoutshow();

Jangla
24 Sep 2009, 8:04 AM
Awesome!

Plays merry havoc with the gmappanel - it has an issue with auto zooming to get all markers visible (it sooms out to global level!) but I can step through that and see if it's surmountable - at least you've helped me get the first stage out the way :)

At the moment it's probably fine to have the map load on activate but I'm a firm believer in scalable solutions and if this map ends up with 10 times as many markers, it would be really slow to load so it's arguable that loading on the fly in the background is preferable!

Thanks hendricd

Jangla
25 Sep 2009, 5:54 AM
Hmmm, getting rather frustrated with these events on tabPanels! activate fires after rendering (so not after it's activated by the user), as does tabchange, making it almost impossible to use any of them for user interaction.

Guess I'll have to wait until eveything is loaded and then add a listener and remove it again later :(

hendricd
25 Sep 2009, 5:56 AM
What exactly are trying to accomplish each time the active tab changes?

Jangla
25 Sep 2009, 6:14 AM
The idea is that on page load, the tab panel is rendered and the map populated with markers.
This is for two reasons:
1. I can't get a loading mask to work on the map so users won't be aware that something is happening.
2: if the number of markers greatly increases, it makes sense to start loading them immediately so they can be ready (or at least most of the way there) if the user chooses to look at the map.

Your help with the initial post got over the loading of markers on page load perfectly.

Once the markers are loaded (regardless of whether the map tab has been selected or not), the map should automatically zoom to the correct level and location to include all markers in the viewport so if and when the user views the map, it's immediately ready to go.

The issue now is that the gmap refuses to auto zoom to the correct level when the map isn't physically viewable on the user's screen. This is largely Google's fault but they claim that telling the map the size of it's parent container when you call new GMap2 will address this problem - it doesn't.

I therefore thought I could get over this by waiting to fire the auto zoom code until the first time the map tab is activated - that way it's visible on the user's screen and *should* be able to set the correct zoom level.

hendricd
25 Sep 2009, 6:33 AM
The issue now is that the gmap refuses to auto zoom to the correct level when the map isn't physically viewable on the user's screen. This is largely Google's fault but they claim that telling the map the size of it's parent container when you call new GMap2 will address this problem - it doesn't.


This is likely due to fact that inactive tabs are hidden using hideMode:'display' (by default : display:none). You can try changing the default hideMode to 'offsets', but that too may cause DOM reflow problems when made visible again.

'offsets' might preserve the size of the Container for later map resizing when the Panel is rendered.

An alternate solution is to use the uxvismode plugin, available here (http://uxdocs.theactivegroup.com/repo/trunk/Ext/ux/plugin/uxvismode.js).


var vismode = new Ext.ux.plugin.VisibilityMode();Adding this to your tabPanel config:



plugins : vismode,
defaults : {autoScroll:true, split: true, hideMode : 'nosize', plugins : vismode},
Then the Map objects may not 'go-to-sleep'. ;)

Jangla
28 Sep 2009, 2:25 AM
Visibility plugin doesn't seem to have any beneficial effect in this case :(

hendricd
28 Sep 2009, 3:18 AM
@Jangla -- based on this thread and the other one, it sounds like you're not quite timing the map extent calculation at quite the right time.

Try using the afterlayout event with the {single:true} option instead.

Beyond that, post your current tabPanel layout strategy for review.

mschwartz
28 Sep 2009, 5:46 AM
3.0.0
Beware the add event is fired for a tab panel whenever you add anything to any tab in the panel. It really should fire only when a tab is added.

mschwartz
10 Nov 2009, 8:50 AM
I'm seeing problems with the visibility plugin.

I have a tab panel defined something like this:


var panel = new Ext.TabPanel({
id: 'workspace-tabs',
plugins : [ vismode, new Ext.ux.TabCloseMenu() ],
defaults : {autoScroll:true, split: true, hideMode : 'nosize', plugins : vismode},


With one default tab instantiated.

I dynamically open two tabs (on button clicks), each with html:'' in the config. On render, the tabs do an Ajax call to get an array of items to be rendered as HTML in the tab. Something like:



success: function() { // Ext.Ajax success method
var html = '<div style="padding: 15px"><table>';
for (var item=0; item<items; item++) {
html += '<tr>' + item.details + '</tr>';
}
html += '</table></div>';
tab.getEl().update(html);
}


When I open the first tab, the HTML is created via the ajax method. It looks great. I examine the HTML and it passes lint (e.g. proper tags, close tags for each open tag, etc.).

When I open the second tab, the HTML for the first tab is shown on top of (or behind) the HTML generated for the second tab.

If I switch to the first tab again, the HTML for the second tab is now rendered on top of (or behind) the HTML generated for the first tab.

I examine the HTML with firebug and it's the visibility plugin messing things up. It's setting the tab's div style to x-hide-nosize, but the HTML within that tab's div is not being hidden, even though it inherits .x-hide-nosize.

Any clue how to get around this?

hendricd
10 Nov 2009, 9:00 AM
@mschwartz --
The rendering area for a Panel (your tab) is:


tab.body.update(html);You're destroying the guts of the tab using getEl().update(). /:)

mschwartz
10 Nov 2009, 9:01 AM
Fixed it, thanks so much!