PDA

View Full Version : Border Layout broken when used inside table



alainmoran
26 Jan 2007, 8:42 AM
The following code works perfectly:


<html><head><title>test</title>
<script type="text/javascript" src="yui/build/utilities/utilities.js"></script>
<script type="text/javascript" src="yui-ext.0.33/yui-ext.js"></script>
<link rel="stylesheet" type="text/css" href="yui-ext.0.33/resources/css/yui-ext.css">

<script type="text/javascript">
var borderLayout;
var tabPanel;
function init () {
if (borderLayout!=null) return;
borderLayout = new YAHOO.ext.BorderLayout("layoutselector", {
hideOnLayout: true,
autoCreate: true,
west: {
split:true,
initialSize: 255,
minSize: 255,
maxSize: 400,
titlebar: true,
collapsible: true,
animate: true,
autoCreate: true,
autoScroll: false
},
south: {
split:true,
initialSize: 100,
minSize: 100,
maxSize: 200,
titlebar: true,
collapsible: true,
animate: true,
autoCreate: true,
autoScroll: false
},
center: {
titlebar: false,
tabPosition: 'top',
autoCreate: true,
autoScroll: true
}
});
getEl("layoutselector").borderLayout=borderLayout;
// build the layout
borderLayout.beginUpdate();
borderLayout.add('south', new YAHOO.ext.ContentPanel('helppanel', {title: 'Information', autoScroll: true, closable: true, autoCreate: true}));
borderLayout.add('west', new YAHOO.ext.ContentPanel('treepanel', {title: 'Theme Hierarchy', autoScroll: true, autoCreate: true}));
borderLayout.add('center', new YAHOO.ext.ContentPanel('quickpreview', {title: 'Quick', autoScroll: true, autoCreate: true}));
borderLayout.add('center', new YAHOO.ext.ContentPanel('fullpreview', {title: 'Full', autoScroll: true, autoCreate: true}));
borderLayout.endUpdate();
tabPanel = borderLayout.getRegion("center").getTabs();
tabPanel.activate('quickpreview');
}

YAHOO.ext.EventManager.onDocumentReady(init);
</script></head><body>

<div id="layoutselector"></div>

</body></html>


However if you put the div that the border layout should occupy inside a table, then it breaks horribly, eg:


<html><head><title>test</title>
<script type="text/javascript" src="yui/build/utilities/utilities.js"></script>
<script type="text/javascript" src="yui-ext.0.33/yui-ext.js"></script>
<link rel="stylesheet" type="text/css" href="yui-ext.0.33/resources/css/yui-ext.css">

<script type="text/javascript">
var borderLayout;
var tabPanel;
function init () {
if (borderLayout!=null) return;
borderLayout = new YAHOO.ext.BorderLayout("layoutselector", {
hideOnLayout: true,
autoCreate: true,
west: {
split:true,
initialSize: 255,
minSize: 255,
maxSize: 400,
titlebar: true,
collapsible: true,
animate: true,
autoCreate: true,
autoScroll: false
},
south: {
split:true,
initialSize: 100,
minSize: 100,
maxSize: 200,
titlebar: true,
collapsible: true,
animate: true,
autoCreate: true,
autoScroll: false
},
center: {
titlebar: false,
tabPosition: 'top',
autoCreate: true,
autoScroll: true
}
});
getEl("layoutselector").borderLayout=borderLayout;
// build the layout
borderLayout.beginUpdate();
borderLayout.add('south', new YAHOO.ext.ContentPanel('helppanel', {title: 'Information', autoScroll: true, closable: true, autoCreate: true}));
borderLayout.add('west', new YAHOO.ext.ContentPanel('treepanel', {title: 'Theme Hierarchy', autoScroll: true, autoCreate: true}));
borderLayout.add('center', new YAHOO.ext.ContentPanel('quickpreview', {title: 'Quick', autoScroll: true, autoCreate: true}));
borderLayout.add('center', new YAHOO.ext.ContentPanel('fullpreview', {title: 'Full', autoScroll: true, autoCreate: true}));
borderLayout.endUpdate();
tabPanel = borderLayout.getRegion("center").getTabs();
tabPanel.activate('quickpreview');
}

YAHOO.ext.EventManager.onDocumentReady(init);
</script></head><body>

<table><tr><td>
<div id="layoutselector"></div>
</td></tr></table>

</body></html>


[/code]

gfraser
26 Jan 2007, 8:47 AM
First, ensure you have a tbody tag in there for correct table markup. Then add width/height to the table.

alainmoran
26 Jan 2007, 8:50 AM
Oddly, adding a width & height to the table allows the border layout to render correctly:



<table width="500" height="500"><tr><td>
<div id="layoutselector"></div>
</td></tr></table>


For prerelease coding I can hard-code the width/height however before I can release my app I will need to have a resolution/workaround (that will allow my content to take up all of the available area)[/code]

alainmoran
26 Jan 2007, 9:01 AM
First, ensure you have a tbody tag in there for correct table markup. Then add width/height to the table.

tbody makes no difference whatsoever, and fixing the width/height of the table is not an option for the finally released application, since it requires the interface to fill the available area.

alainmoran
26 Jan 2007, 9:04 AM
Also oddly, percentage heights work too!



<table width="100%" height="100%"><tr><td>
<div id="layoutselector"></div>
</td></tr></table>

Animal
26 Jan 2007, 9:10 AM
That's expected. The Layout adjusts itself to whatever height the containing element has.

If you don't give the containing element a height, it won't work - there's no size to size itself to.

The exception is when the containing element is document.body.

The code is



getViewSize : function(){
var size;
if(this.el.dom != document.body){
this.el.beginMeasure();
size = this.el.getSize();
this.el.endMeasure();
}else{
size = {width: YAHOO.util.Dom.getViewportWidth(), height: YAHOO.util.Dom.getViewportHeight()};
}
size.width -= this.el.getBorderWidth('lr')-this.el.getPadding('lr');
size.height -= this.el.getBorderWidth('tb')-this.el.getPadding('tb');
return size;
},


Anyway, why are you using a table for page layout? That's what the BorderLayout is for!

alainmoran
26 Jan 2007, 9:12 AM
Frustratingly when I apply the same workaround to my actual application (pixel OR percentage, tbody or no), then the display is still broken .. the YUI-ext code in the examples above is a cut/paste of the init code from my application, only the nesting of the target div is different (it's much deeper in my app)

alainmoran
26 Jan 2007, 9:14 AM
Anyway, why are you using a table for page layout? That's what the BorderLayout is for!

I am not using a table, however the rest of the webapp is ... I am embedding a YUI interface within 'confluence' an already existing webapp, it is neither possible nor desirable to break out of the webapp's sitemesh decoration.

alainmoran
26 Jan 2007, 9:18 AM
Frustratingly when I apply the same workaround to my actual application (pixel OR percentage, tbody or no), then the display is still broken .. the YUI-ext code in the examples above is a cut/paste of the init code from my application, only the nesting of the target div is different (it's much deeper in my app)

Update: If you use pixel sizes, then resize the screen, the border layout appears at the fixed pixel size, but positioned at 0,0 !!

Animal
26 Jan 2007, 9:26 AM
Make it not listen for window resizes. It's a config option.

http://www.yui-ext.com/deploy/yui-ext/docs/output/YAHOO.ext.BorderLayout.html#monitorWindowResize

alainmoran
26 Jan 2007, 9:30 AM
Heh, no .. thats worse .. it ONLY appears when you resize the screen.

alainmoran
26 Jan 2007, 9:36 AM
I dont know if this is a separate bug, or part of the same problem, however border-layout seems to have problems with coexisting with other content that is not yui-ext generated


<html><head><title>test</title>
<script type="text/javascript" src="yui/build/utilities/utilities.js"></script>
<script type="text/javascript" src="yui-ext.0.33/yui-ext.js"></script>
<link rel="stylesheet" type="text/css" href="yui-ext.0.33/resources/css/yui-ext.css">

<script type="text/javascript">
var borderLayout;
var tabPanel;
function init () {
if (borderLayout!=null) return;
borderLayout = new YAHOO.ext.BorderLayout("layoutselector", {
hideOnLayout: true,
autoCreate: true,
west: {
split:true,
initialSize: 255,
minSize: 255,
maxSize: 400,
titlebar: true,
collapsible: true,
animate: true,
autoCreate: true,
autoScroll: false
},
south: {
split:true,
initialSize: 100,
minSize: 100,
maxSize: 200,
titlebar: true,
collapsible: true,
animate: true,
autoCreate: true,
autoScroll: false
},
center: {
titlebar: false,
tabPosition: 'top',
autoCreate: true,
autoScroll: true
}
});
getEl("layoutselector").borderLayout=borderLayout;
// build the layout
borderLayout.beginUpdate();
borderLayout.add('south', new YAHOO.ext.ContentPanel('helppanel', {title: 'Information', autoScroll: true, closable: true, autoCreate: true}));
borderLayout.add('west', new YAHOO.ext.ContentPanel('treepanel', {title: 'Theme Hierarchy', autoScroll: true, autoCreate: true}));
borderLayout.add('center', new YAHOO.ext.ContentPanel('quickpreview', {title: 'Quick', autoScroll: true, autoCreate: true}));
borderLayout.add('center', new YAHOO.ext.ContentPanel('fullpreview', {title: 'Full', autoScroll: true, autoCreate: true}));
borderLayout.endUpdate();
tabPanel = borderLayout.getRegion("center").getTabs();
tabPanel.activate('quickpreview');
}

YAHOO.ext.EventManager.onDocumentReady(init);
</script></head><body>
<div>This is some other content ...........................................This is some other content ...........................................This is some other content ...........................................</div>
<div>This is some other content ...........................................This is some other content ...........................................This is some other content ...........................................</div>
<div>This is some other content ...........................................This is some other content ...........................................This is some other content ...........................................</div>
<table width="500" height="500"><tr><td>
<div id="layoutselector"></div>
</td></tr></table>

</body></html>

Animal
26 Jan 2007, 10:52 AM
Heh, no .. thats worse .. it ONLY appears when you resize the screen.

Explicitly calling layout should make it appear: http://www.yui-ext.com/deploy/yui-ext/docs/output/YAHOO.ext.BorderLayout.html#layout

alainmoran
26 Jan 2007, 11:22 AM
That seems to force it to display :D

So, any idea how to get it to position itself inside of the original target div, rather than appearing at 0,0 ?

Animal
26 Jan 2007, 12:26 PM
divs don't size themselves. your content div won't automagically size to the size of the table!

Try this:



<table cellspacing="0" cellpadding="0">
<tr>
<td id="layoutselector" style="height:500px;width:500px"></td>
</tr>
</table>

alainmoran
26 Jan 2007, 7:19 PM
divs don't size themselves. your content div won't automagically size to the size of the table!

Try this:



<table cellspacing="0" cellpadding="0">
<tr>
<td id="layoutselector" style="height:500px;width:500px"></td>
</tr>
</table>


If only it were that simple ... using



<table><tr><td id="layoutselector" style="width:100%;height:500;"></td></tr></table>


I get

http://www.adaptavist.com/download/attachments/11514/reallychimped.png

using



<table width="100%" height="500"><tr><td id="layoutselector"></td></tr></table>


I get

http://www.adaptavist.com/download/attachments/11514/chimped.png



Obviously, neither is actually usable in a production environment!

Any suggestions you may have would be very welcome!

JeffHowden
26 Jan 2007, 10:19 PM
Have you tried adding position: relative to the element containing the border layout?

alainmoran
27 Jan 2007, 5:02 AM
Good idea ... however ... no cigar :(

I have tried:


<table width="100%" height="500"><tr><td id="layoutselector" style="position:relative;"></td></tr></table>

<table><tr><td id="layoutselector" style="position:relative;width:100%;height:500px;"></td></tr></table>

<table style="position:relative;width:100%;height:500px;"><tr><td id="layoutselector"></td></tr></table>

<table width="100%" height="500" style="position:relative;"><tr><td id="layoutselector"></td></tr></table>


None of which make slightest bit of different to the display ... If I wasnt being pulled off this project and told to go work on someting else, I'd start stepping through yui-ext itself and find the bug that causes it ... however you know bosses, they love to mess up your development flow, perhaps when I come back to this project in a month or so's time (when I've forgotten everything that I knew about what was going on) I will be able to step through and find the issue in YUI that is causing this.

I suspect as Animal says, finding the width/height/top/left of an element is/can-be a fairly thorny issue, and that for-now its a) requiring forced heights to be set, and b) just defaults to 0,0 so that the coder could get on with whatever task they were working on before.

jack.slocum
27 Jan 2007, 5:29 PM
This is not a bug in BL, tables do not follow the same rules as other page elements. They have their own sizing, layout and sometimes (Safari) offset calculations. The only way it is going to work is to put a normal element inside the table, and render your layout in it. Even then, you may run into problems with Opera.


<table><tr><td>
<div id="layout-container" style="position:relative;width:600px;height:600px;">
// layout goes in here
</div>
</td></tr></table>

A size on the div is required, because like Animal said the layout "fits" itself to the size of it's container.

Position relative is required to make the absolute positioning constrain to the container div (and not appear at 0,0 on the page).

That div doesn't have to be statically sized, you might consider using JS plus a call to layout() to resize the div and force a layout when something changes.

alainmoran
27 Jan 2007, 6:34 PM
I did try the position:relative (although not on the original div within a td, as you have suggested) and all other solutions offered (including calling layout()), however as mentioned none of them worked for me so I decided that I couldnt let it lie and have spent a little time working it out for myself.

It does look very much like you got interrupted partway through sorting it out, since you have unused x & y variables hanging about in the layout method.

So, by setting those values to this.el.getLeft & this.el.getTop respectivley, and then using them in the x & y position calculations for each of the panels, I am now able to make my layout appear inside of the element it was told to appear within rather than up in the top/left corner.

You can download the new BorderLayout from here:
http://www.adaptavist.com/download/attachments/11514/BorderLayout.js


For an illustration of the issue, use my third HTML example which demonstrates the problem in a simple testbed. (The one with 'this is some other content' in it)

So far I have tested this with code that used tabLayouts within autogenerated tabs within a borderlayout, I guess test of nested borderlayouts will be needed before it can be submitted.

alainmoran
28 Jan 2007, 10:51 AM
OK I just tried this as per Jack's suggestion that I should use my original HTML layout and add position:relative to the inner div, which works perfectly using the original codebase.

Would it be worth adding something to the docs to mention this?

You also may want to remove the unused 'x' and 'y' declarations from the BorderLayout.layout() method.

Thanks for the help, I dont think my changes to the source will be needed.

jack.slocum
28 Jan 2007, 12:23 PM
Those unused x/y declarations were in there for panel drag drop (e.g. dragging a panel from east to west) that never made it into the main codebase. I commented them out.

I've added a note at the top of BorderLayout about relative position. Sorry you lost time on this.

alainmoran
28 Jan 2007, 4:56 PM
No worries man ... yui-ext is a tastic library, and it's saved me a LOT more time than I lost messing about with it! I'm looking forward to the full drag/drop capabilities so that I can ditch the JS tree that we actually paid to license in favour of yours ... you have much cleaner code, even if it werent so clean, the mere fact that you use AO's gives you kudos in my book (although you could take it a little further IMO)