View Full Version : Error on closing tab destroying app
ojintoad
02-01-2007, 04:08 PM
When I close tabbed content panels I get an error that redirects the entire page to the root url targeted at #.
The application works by having an outer BorderLayout with a north and center region. The center region is populated with content panels, each content panel a new IFrame which has its own Border Layout. These IFrames are called TabPages.
Currently there are around 13 possible TabPages, but I have coded a priority queue which will close the least recently accessed TabPage when more than 5 are attempted to be open.
Each content panel added to the center region is configured with close on tab.
When the priority queue mechanism removes the panels, for some reason they close without error.
When the close tab button removes a panel, some javascript error is thrown (?) or some other unknown activity occurs which redirects the entire url to #, or a blank target.
I have stepped through the code and I know that it happens after the Yahoo Event's Window Unload system has finished unloading ALL of it's events (so I don't think it is in there). The debugger fails to expose any events and just calmly sits there acknowledging that all window objects have been destroyed somehow. The same code (Yahoo Event's Window Unload) does not execute when the priority queue closes the panel with LayoutRegion.remove(panel). If a window has been closed with LayoutRegion.remove(panel) and then I use the click, it seems like double the amout of Event Window Unloads are done.
1) Why is it when I close the panel programatically rather than through the tab interface that this occurs? I don't have preserve panel set to true, but it seems like the IFrame isn't getting destroyed at the right time.
2) Has anyone else experienced errors like this before? I feel like I've dealt with this when working with the YUIMenu object.
*Edits:
To clarify it redirects the outer page, not just the inner IFrame, not that either is preferable behavior.
So while writing this and got to the part where I mentioned the whole closeOnTab thing, I thought 'Maybe if I turn off the whole closeOnTab thing and have it close from the title bar, it will work'. And I'll darned, but it did work.
But It'd be nice to know why the alternative fails. I'm wondering if it is because the tab has focus and it removes the item which has focus (though that doesn't make much sense).
BernardChhun
02-02-2007, 07:10 AM
do you have a link to show us your problem?
ojintoad
02-02-2007, 08:43 AM
Intranet App. No dice... :?
BernardChhun
02-02-2007, 08:59 AM
Intranet App. No dice... :?
post parts of your code here then...we'll try to figure it out :wink:
ojintoad
02-02-2007, 02:05 PM
I just discovered while stepping through code to figure out other issues that they Tab Elements are drawn using an anchor Tag. Inspecting the A Tag granted me the redirection URL that keeps getting hit defined for the anchor tag's href, that is, href = "http://properurl/#".
So, this is my theory. When I click on a tab to close, an error gets thrown and not caught somewhere. That error interrupts the Tab code. If it wasn't interrupted, the Tab Code would probably cancel the default event for the A Tag or prevent it from being executed. But in this case, the Tab code gets exited early and the default event, following the href, is executed. This redirects my screen to the location http://properurl/#.
I realize I have seen this problem before with IE6, in the Yahoo Menu Widget or maybe the Tree Widget, because it uses A tags by default so that people can have the tree nodes act as links. I wish A Tags were used less because of this bug.
Time to go inspect the Tab code for a cancelEvent of some type...
Here is the code for the loading of the pages, though I don't see it as being much help. The panels are loaded individually by the user using a select box with a button next to it. The Page object is just a helper object for the application. This version does NOT have the panels with the closeOnTab set to true.
I'll probably ask this in another thread, but does anyone know when the ounload event is fired for iFrames. (on src change? on tag destruction? hrm)
Page.initialize = function()
{
var lo = new YAHOO.ext.BorderLayout(document.body,
{
north:
{
initialSize: 60
},
center:
{
margins: {top: 10, left: 10, right: 10, bottom: 10},
tabPosition: 'top',
alwaysShowTabs: true,
resizeTabs: true,
preservePanel: false,
title: 'Application Title'
}
});
lo.beginUpdate();
lo.add('north', new YAHOO.ext.ContentPanel('north'));
lo.add('center', new YAHOO.ext.ContentPanel('center', {title: 'File Checkout', autoCreate: {tag: 'div', id: 'defaultTab'}}));
lo.endUpdate();
this.layout = lo;
this.centerRegion = lo.getRegion('center');
}
Page.loadTabs = function()
{
// This will hide the file grid. We cannot use the more obvious style.display = "none" because this leads to an IE bug
document.getElementById("select-configuration").style.position = "absolute";
document.getElementById("select-configuration").style.left = "-1000px";
var centerRegion = this.layout.getRegion('center');
// We need to preserve the ContentPanel that contains the checkout grid.
this.checkoutPanel = centerRegion.remove(0, true);
// Panel handlers maintain the loaded pages
centerRegion.on('beforeremove', this.beforeRemoveListener, this, true);
centerRegion.on('paneladded', this.panelAddedListener, this, true);
centerRegion.on('panelactivated', this.panelActivatedListener, this, true);
centerRegion.on('panelremoved', this.panelRemovedListener, this, true);
// Show the command buttons (action buttons)
getEl('command').setStyle('display', 'block');
// Schema for the pages that are openable
this.schema =
[
//An array of paired values of labels and pages, used below.
];
var pageSelectDom = getEl('PageSelect').dom;
for(var i =0, len = this.schema.length; i < len; i++)
{
pageSelectDom.options[i] = new Option(this.schema[i].label, this.schema[i].page);
}
this.pageSelectDom = pageSelectDom;
var pageSelectButton = getEl('PageSelectButton');
pageSelectButton.on('click', this.selectButtonHandler, this, true);
debugger;
}
Page.selectButtonHandler = function()
{
var pageSelectDom = this.pageSelectDom;
var label = pageSelectDom.options[pageSelectDom.selectedIndex].text;
var value = pageSelectDom.value;
this.activatePagePanel(label, value);
}
Page.activatePagePanel = function(label, value){
var tabIdStub = label.replace(/\s/g, '-');
var cp = this.centerRegion.getPanel(tabIdStub + '-Frame');
if(cp != null)
{
this.centerRegion.showPanel(cp);
}
else
{
var cp = new YAHOO.ext.ContentPanel(null,
{
autoCreate: {
tag: 'iframe',
id: tabIdStub + '-Frame',
frameBorder: 0
},
title: label,
fitToFrame: true,
closable: true
}
);
cp.page = value;
this.centerRegion.add(cp);
}
}
Page.panelAddedListener = function(region, panel)
{
//this.ActivationQueue.activate(panel);
var panelFrames = this.panelFrames;
var panelDom = panel.getEl().dom;
if(!panelFrames[panelDom.id] || panelFrames[panelDom.id] == undefined){
panelFrames[panelDom.id] = true;
panelDom.src = 'app?page=' + panel.page + '&service=page';
}
}
Page.beforeRemoveListener = function(region, panel)
{
debugger;
this.ActivationQueue.remove(panel);
var panelFrames = this.panelFrames;
var panelDom = panel.getEl().dom;
panelFrames[panelDom.id] = false;
}
Page.panelRemovedListener = function(region, panel)
{
debugger;
}
Page.panelActivatedListener = function(region, panel)
{
var toRemove = this.ActivationQueue.activate(panel);
if(toRemove != null){
this.centerRegion.remove(toRemove);
}
}
mdocter
02-05-2007, 06:27 AM
Hi,
I had the same problem. In my case it was a BASE ref in the HTML head, which caused the problem.
See also my original post: http://www.yui-ext.com/forum/viewtopic.php?t=2158&highlight=
Grtz,
Maarten
ojintoad
02-05-2007, 10:54 AM
mdocter: Thanks, your solution turned out to work!
I still don't see though why an anchor tag would be used to draw the tab element code, so I dug through the code and found the TabPanel's private createStripElments function which generates the HTML for the Tabs. You can replace the code manually to resolve the issue as well. Below is what I used:
YAHOO.ext.TabPanel.prototype.createStripElements = function(stripEl, text, closable){
var td = document.createElement('td');
stripEl.appendChild(td);
if(closable){
td.className = "ytab-closable";
if(!this.closeTpl){
this.closeTpl = new YAHOO.ext.Template(
'<span class="ytab-right"><span class="ytab-left"><em class="ytab-inner">' +
'<span unselectable="on" title="{text}" class="ytab-text">{text}</span>' +
'<div unselectable="on" class="close-icon"> </div>[/i]</span></a>'
);
}
var el = this.closeTpl.overwrite(td, {'text': text});
var close = el.getElementsByTagName('div')[0];
var inner = el.getElementsByTagName('em')[0];
return {'el': el, 'close': close, 'inner': inner};
} else {
if(!this.tabTpl){
this.tabTpl = new YAHOO.ext.Template(
'<span class="ytab-right"><span class="ytab-left"><em class="ytab-inner">' +
'<span unselectable="on" title="{text}" class="ytab-text">{text}</span>[/i]</span></a>'
);
}
var el = this.tabTpl.overwrite(td, {'text': text});
var inner = el.getElementsByTagName('em')[0];
return {'el': el, 'inner': inner};
}
};
You can compare that with the last method defined at http://www.jackslocum.com/deploy/yui-ext/docs/output/TabPanel.js.html
So I'm guessing here that the base tag, when removed, renders the href='#' to just be interpreted as # and not http://properurl/#. When the browser visits #, no refresh is done so there is no error.
In the case of replacing the Anchor tag, it prevents the refresh from possibly occurring in the first place.
mdocter
02-06-2007, 02:56 AM
You're welcome. I'm glad it worked.
The anchor tag is probably used for an extra CSS styling handle, so that shouldn't be a big problem.
I think the main issue here is the event bubbling/propogation of the Anchor tag. This should be stopped by using the YAHOO.util.Event.stopEvent() function.
vBulletin® v3.8.4, Copyright ©2000-2010, Jelsoft Enterprises Ltd.