PDA

View Full Version : [CLOSED-113][3.0.0] Constrained,maximized window onWindowResize problem



Tewr
10 Aug 2009, 6:32 AM
Ext version tested:

Ext 3.0Adapter used:
extcss used:
only default ext-all.cssBrowser versions tested against:

IE8
FF3 (FireBug 1.4.2)Operating System:

WinXP Pro x64Description:

Problem occurs when creating a constrained window, rendered inside a panel body. The reason for putting it in a panel body is that the panel would have a bottom and top toolbar with menus etc, to get that MDI-style feeling. If the window is maximized, you do not want these toolbars to be covered by the maximized window.

However, since upgrading to 3.0, the window doesn't resize correctly when the browser window is resized if the ext window is maximized.

Test Case:

Ext.onReady(function() {
var testPanel = new Ext.Panel({
listeners: { 'render': function() {
new Ext.Window({
title: 'Test window not resizing correctly when browser is resized (when maximized)',
html: 'Test Content',
maximizable: true,
constrainHeader: true,
renderTo: testPanel.body
}).show();

new Ext.Window({
title: 'Test window resizing correctly when maximized(in document body)',
html: 'Test Content',
maximizable: true,
}).show();
} }
});

new Ext.Viewport({
layout: 'fit',
items: [testPanel]
});
});
Observe that the same behaviour can be reproduced by omitting
renderTo: testPanel.body and the show() call and adding
testPanel.add([the constrained window reference]) with a show() call after.

Steps to reproduce the problem:

Maximize the constrained window
Restore the browser window
Maximize the browser windowThe result that was expected:
That the constrained window is resized after the browser has been resizedThe result that occurs instead:
The constrained window is resized erronously.Screenshot or Video

Video link (http://www.screencast.com/users/TewrJing/folders/Jing/media/a2cdc2cb-f746-4867-bea1-65c5f6ba719a) (unfortunately at x2 speed at some computers)

Debugging already done:
Debug revealed that
this.container.getViewSize(); returns erroneous values.
This function behaves correctly, however the error lies in that the values that are returned are fetched from the parent container. The parent container is yet to receive the news about the browser window being resized, so the values that are fetched are "old", that is the values that are returned are the ones the parent container had just before the browser was resized.

Possible fix:

Listen to the parent container's resize event.

Quickfix for test case provided:




Ext.onReady(function() {
var testPanel = new Ext.Panel({
listeners: { 'render': function() {
var errWin = new Ext.Window({
title: 'Test window not resizing correctly when browser is resized (when maximized)',
html: 'Test Content',
maximizable: true,
constrainHeader: true,
renderTo: testPanel.body
});

errWin.on('show', function(win) {
testPanel.on('resize', win.onWindowResize, win);
});

errWin.on('hide', function(win) {
testPanel.un('resize', win.onWindowResize, win);
});

errWin.show();

new Ext.Window({
title: 'Test window resizing correctly when maximized(in document body)',
html: 'Test Content',
maximizable: true,
}).show();
} }
});

new Ext.Viewport({
layout: 'fit',
items: [testPanel]
});
});
In the quickfix, onWindowResize will be called twice, first once when the window is resized and then after when the holding container is resizing, so this is obviously not a good solution, but it shows an unoptimized version the correct behaviour.

A sketch of an override for permanent solution to the problem:
(getParentContainer() is left as an exercise, as I do not know how to implement it in the context of these functions, if I did the temporary fix above would be redundant ;) )



Ext.override(Ext.Window, {
afterShow : function(isAnim){
this.proxy.hide();
this.el.setStyle('display', 'block');
this.el.show();
if(this.maximized){
this.fitContainer();
}
if(Ext.isMac && Ext.isGecko){ // work around stupid FF 2.0/Mac scroll bar bug
this.cascade(this.setAutoScroll);
}

if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
var doc = document,
d = this.container.dom,
isDoc = (d == doc || d == doc.body);
if (isDoc) {
Ext.EventManager.onWindowResize(this.onWindowResize, this);
}
else {
getParentContainer().on('resize', this.onWindowResize, this);
}
}
this.doConstrain();
this.doLayout();
if(this.keyMap){
this.keyMap.enable();
}
this.toFront();
this.updateHandles();
if(isAnim && (Ext.isIE || Ext.isWebKit)){
var sz = this.getSize();
this.onResize(sz.width, sz.height);
}
this.fireEvent('show', this);
},

// private
afterHide : function(){
this.proxy.hide();
if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
var doc = document,
d = this.container.dom,
extdom = Ext.lib.Dom,
isDoc = (d == doc || d == doc.body);
if (isDoc) {
Ext.EventManager.removeResizeListener(this.onWindowResize, this);
}
else {
getParentContainer().un('resize', this.onWindowResize, this);
}
}
if(this.keyMap){
this.keyMap.disable();
}
this.fireEvent('hide', this);
}
});
Another solution could be to modify Ext.Container.getViewSize(), I guess.

First posted in Help in thread http://extjs.com/forum/showthread.php?t=76902

Jamie Avins
19 Jan 2010, 12:39 PM
The first solution in this case would be correct as you are coupling the event because the framework cannot know that relationship. Using renderTo does not couple the window in this example to a parent component, but rather directly to the element. That element does not have a resize event to listen to.

Tewr
20 Jan 2010, 2:03 AM
Using renderTo does not couple the window in this example to a parent component, but rather directly to the element.

I guess the above is true, however the element will eventually be be resized. So your statement:

That element does not have a resize event to listen to does not sound equally true to me. When the window reads the size of the parent element it gets the size as it was just before the last browser resize. So no matter in what way you put it, an erroneous resize WILL be carried out. And then, the listeners that is added in my "quickfix" kicks in and fixes it, by calling the exact same function at a time when the returned values are correct.

However, as you point out, it has to do with the fact that the renderTo config option points to an element rather than a container, so its all in a half-ass order in the first place. There should simply be another way to specify a "constrainer container" than using renderTo. But thats another story. I agree on closing the bug ticket, as the simple resolution to a not-so-common problem is just an additional resize... its not that bad... I sleep well at nights ;)