PDA

View Full Version : Ext.ux.layout.RowFitLayout



kx
4 Nov 2007, 11:19 AM
I wanted to have a layout that distributes multiple components so they fill 100% of the container height. For sure, I can do that with AnchorLayout or TableLayout, but it seems some effort is required to manage these when there are a bunch of child elements.

My idea was that child elements can have height given in percent, and that value should be relative to the "unallocated" height (which is the difference between container height and the sum of the heights of all elements that are set in pixels).


+-------------------------------------------------------------------+
| { height: 100 } |
| panel with a fixed height of 100px (height will remain the same |
| when container size container size changes) |
+-------------------------------------------------------------------+
| |
| { height: "50%" } |
| Will fill half of the remaining space |
| (container.height - 100) / 2 |
+-------------------------------------------------------------------+
| |
| ( no height in config) |
| Will fill all the space that is unallocated (50% in that case) |
| |
+-------------------------------------------------------------------+

Analogous layout in Ext is ColumnLayout, where you can give width or columnWidth and layout will manage that automatically.

I had some hours to spare and decided, "Why don't make that?"

Here's what I came up to:


Ext.namespace('Ext.ux.layout');

/**
* @class Ext.ux.layout.RowFitLayout
* @extends Ext.layout.ContainerLayout
* <p>Layout that distributes heights of elements so they take 100% of the
* container height.</p>
* <p>Height of the child element can be given in pixels (as an integer) or
* in percent. All elements with absolute height (i.e. in pixels) always will
* have the given height. All "free" space (that is not filled with elements
* with 'absolute' height) will be distributed among other elements in
* proportion of their height percentage. Elements without 'height' in the
* config will take equal portions of the "unallocated" height.</p>
* <p>Supports panel collapsing, hiding, removal/addition. The adapter is provided
* to use with Ext.SplitBar: <b>Ext.ux.layout.RowFitLayout.SplitAdapter</b>.</p>
* <p>Example usage:</p>
* <pre><code>
var vp = new Ext.Viewport({
layout: 'row-fit',
items: [
{ xtype: 'panel', height: 100, title: 'Height in pixels', html: 'panel height = 100px' },
{ xtype: 'panel', height: "50%", title: '1/2', html: 'Will take half of remaining height' },
{ xtype: 'panel', title: 'No height 1', html: 'Panel without given height' },
{ xtype: 'panel', title: 'No height 2', html: 'Another panel' }
]
});
* </code></pre>
* Usage of the split bar adapter:
* <pre><code>
var split = new Ext.SplitBar("elementToDrag", "elementToSize", Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
// note the Ext.SplitBar object is passed to the adapter constructor to set
// correct minSize and maxSize:
split.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));
* </code></pre>
*/

Ext.ux.layout.RowFitLayout = Ext.extend(Ext.layout.ContainerLayout, {
// private
monitorResize: true,

// private
trackChildEvents: ['collapse', 'expand', 'hide', 'show'],

// private
renderAll: function(ct, target) {
Ext.ux.layout.RowFitLayout.superclass.renderAll.apply(this, arguments);
// add event listeners on addition/removal of children
ct.on('add', this.containerListener);
ct.on('remove', this.containerListener);
},

// private
renderItem: function(c, position, target) {
Ext.ux.layout.RowFitLayout.superclass.renderItem.apply(this, arguments);

// add event listeners
for (var i=0, n = this.trackChildEvents.length; i < n; i++) {
c.on(this.trackChildEvents[i], this.itemListener);
}
c.animCollapse = false; // looks ugly together with row-fit layout

// store some layout-specific calculations
c.rowFit = {
hasAbsHeight: false, // whether the component has absolute height (in pixels)
relHeight: 0, // relative height, in pixels (if applicable)
calcRelHeight: 0, // calculated relative height (used when element is resized)
calcAbsHeight: 0 // calculated absolute height
};

// process height config option
if (c.height) {
// store relative (given in percent) height
if (typeof c.height == "string" && c.height.indexOf("%")) {
c.rowFit.relHeight = parseInt(c.height);
}
else { // set absolute height
c.setHeight(c.height);
c.rowFit.hasAbsHeight = true;
}
}
},

// private
onLayout: function(ct, target) {
Ext.ux.layout.RowFitLayout.superclass.onLayout.call(this, ct, target);

if (this.container.collapsed || !ct.items || !ct.items.length) { return; }

// first loop: determine how many elements with relative height are there,
// sums of absolute and relative heights etc.
var absHeightSum = 0, // sum of elements' absolute heights
relHeightSum = 0, // sum of all percent heights given in children configs
relHeightRatio = 1, // "scale" ratio used in case sum <> 100%
relHeightElements = [], // array of elements with 'relative' height for the second loop
noHeightCount = 0; // number of elements with no height given

for (var i=0, n = ct.items.length; i < n; i++) {
var c = ct.items.itemAt(i);

if (!c.isVisible()) { continue; }

// collapsed panel is treated as an element with absolute height
if (c.collapsed) { absHeightSum += c.getFrameHeight(); }
// element that has an absolute height
else if (c.rowFit.hasAbsHeight) {
absHeightSum += c.height;
}
// 'relative-heighted'
else {
if (!c.rowFit.relHeight) { noHeightCount++; } // element with no height given
else { relHeightSum += c.rowFit.relHeight; }
relHeightElements.push(c);
}
}

// if sum of relative heights <> 100% (e.g. error in config or consequence
// of collapsing/removing panels), scale 'em so it becomes 100%
if (noHeightCount == 0 && relHeightSum != 100) {
relHeightRatio = 100 / relHeightSum;
}

var freeHeight = target.getStyleSize().height - absHeightSum, // "unallocated" height we have
absHeightLeft = freeHeight; // track how much free space we have

while (relHeightElements.length) {
var c = relHeightElements.shift(), // element we're working with
relH = c.rowFit.relHeight * relHeightRatio, // height of this element in percent
absH = 0; // height in pixels

// no height in config
if (!relH) {
relH = (100 - relHeightSum) / noHeightCount;
}

// last element takes all remaining space
if (!relHeightElements.length) { absH = absHeightLeft; }
else { absH = Math.round(freeHeight * relH / 100); }

// anyway, height can't be negative
if (absH < 0) { absH = 0; }

c.rowFit.calcAbsHeight = absH;
c.rowFit.calcRelHeight = relH;

c.setHeight(absH);
absHeightLeft -= absH;
}

},


/**
* Event listener for container's children
* @private
*/
itemListener: function(item) {
item.ownerCt.doLayout();
},


/**
* Event listener for the container (on add, remove)
* @private
*/
containerListener: function(ct) {
ct.doLayout();
}

});

// Split adapter
if (Ext.SplitBar.BasicLayoutAdapter) {

/**
* @param {Ext.SplitBar} splitbar to which adapter is applied.
* If supplied, will set correct minSize and maxSize.
*/
Ext.ux.layout.RowFitLayout.SplitAdapter = function(splitbar) {
if (splitbar && splitbar.el.dom.nextSibling) {
var next = Ext.getCmp( splitbar.el.dom.nextSibling.id ),
resized = Ext.getCmp(splitbar.resizingEl.id);

if (next) {
splitbar.maxSize = (resized.height || resized.rowFit.calcAbsHeight) +
next.getInnerHeight() - 1; // seems can't set height=0 in IE, "1" works fine
}
splitbar.minSize = resized.getFrameHeight() + 1;
}
}

Ext.extend(Ext.ux.layout.RowFitLayout.SplitAdapter, Ext.SplitBar.BasicLayoutAdapter, {

setElementSize: function(splitbar, newSize, onComplete) {
var resized = Ext.getCmp(splitbar.resizingEl.id);

// can't resize absent, collapsed or hidden panel
if (!resized || resized.collapsed || !resized.isVisible()) return;

// resizingEl has absolute height: just change it
if (resized.rowFit.hasAbsHeight) {
resized.setHeight(newSize);
}
// resizingEl has relative height: affects next sibling
else {
if (splitbar.el.dom.nextSibling) {
var nextSibling = Ext.getCmp( splitbar.el.dom.nextSibling.id ),
deltaAbsHeight = newSize - resized.rowFit.calcAbsHeight, // pixels
nsRf = nextSibling.rowFit, // shortcut
rzRf = resized.rowFit,
// pixels in a percent
pctPxRatio = rzRf.calcRelHeight / rzRf.calcAbsHeight,
deltaRelHeight = pctPxRatio * deltaAbsHeight; // change in height in percent

rzRf.relHeight = rzRf.calcRelHeight + deltaRelHeight;

if (nsRf.hasAbsHeight) {
var newHeight = nextSibling.height - deltaAbsHeight;
nextSibling.height = newHeight;
nextSibling.setHeight(newHeight);
}
else {
nsRf.relHeight = nsRf.calcRelHeight - deltaRelHeight;
}
}
}
// recalculate heights
resized.ownerCt.doLayout();
} // of setElementSize

}); // of SplitAdapter
}

Ext.Container.LAYOUTS['row-fit'] = Ext.ux.layout.RowFitLayout;


There's also an SplitBar adapter as a bonus.

I haven't tested that a lot, was in hurry to share my excitement about Ext 2.0 :) (Actually the free time ran out...)
There are some known issues and limitations, e.g. collapsed panels are considered elements with absolute height regardless their initial settings, and that can produce somewhat strange visual effect when there are a lot of collapsed panels.

Hope that will help someone, but even if I had just re-invented the wheel, that exercise helped me to dive into the depths of the Ext. Gee-whiz! The whole Ext 2.0 layout system is so-o-o damned cool!!! No doubt Jack and his team are geniuses!

Here you can see the layout in action (http://exteriments.chl.ru/row-fit-layout/).

netsuo
12 Nov 2007, 2:27 PM
Hey, i don't know why nobody has responded to this.. but.. this is great !
I'm not so experienced in Ext so for me this extension is the perfect solution to all my problems !

Thanks a lot, i will test it very soon !

dselkirk
13 Nov 2007, 6:14 AM
I agree, nice work.

gimler
15 Nov 2007, 5:12 AM
this is exactly what i have searched for.

it work very well the only limitation is the height value only except px ;(

sfwalter
16 Nov 2007, 6:39 AM
Outstanding work! Kudos to you!=D>

pavel.dolinin
29 Nov 2007, 6:21 AM
I have to thank you very mach
Your code of row-fit just solve my problem in 3 minutes :D

dxd
29 Nov 2007, 2:06 PM
It's a great addition :)
I'll surely use it :)

wpichler
11 Dec 2007, 3:48 AM
your row-fit layout did saved my day - its exactly what i was looking for.

Where do vote for inclusion into Ext ?

jasonbronson
12 Dec 2007, 10:39 AM
bug jack to include it

kx
12 Dec 2007, 9:58 PM
Thanks everybody who rated my tiny plugin that high! Glad it is useful not for me only.

Yet there are issues to be fixed (e.g. there may be some problems with SplitAdapter - minSize and maxSize aren't updated after resize)...

At a local copy I renamed 'row-fit' to 'Vertical Layout' (because child components are stacked vertically) and also created 'Horizontal Layout' (latter is merely an interface to ColumnLayout to provide consistent config options. No SplitAdapter for horizontal layout yet.)

I'll try to find some time to fix problems I'm aware of and then publish the update here. Any feedback/bug reports are appreciated!

Animal
19 Dec 2007, 3:16 AM
Bump!

Someone was (or should have been!) looking for this thread!

mangrar
19 Dec 2007, 6:38 AM
Hi,

Maybe this class is what I'm looking for. I want to do the same that the portal example but disposing panels in rows instead of columns. Read this thread:

http://extjs.com/forum/showthread.php?t=21215

Bye.

rkrishna_1975
19 Dec 2007, 7:49 AM
Wow great work. I was looking for something similar to this myself.

mangrar
20 Dec 2007, 7:52 AM
Yesterday, I tested this new layout. I added three panels and each one fills a row. But this is half what I need. I need a row-layout, that's fine. The next step is a new layout, one like the horizontal panel in GWT library, to be used in each row. I need drag&drop panels to a row to be positioned horizontally in the row. See the Portal example of Ext2. I need the same application but in rows. So in the first row you can add 3 panels, each one with the same height but with different width.

I've been thinking about creating a new layout using anchor layout philosophy. This layout, displays panels using HTML positioning. So, the second panel you add goes below the first one you added previously. This is what I need but in horizontal. So, when you add a new panel in a row of an row-layout, goes at the right of the previous one.

Can someone give me some advice?

Thanks a lot.

ray007
27 Dec 2007, 12:54 AM
Thanks for sharing your work, I've tried to improve a bit on it and extended it to automatically add the needed sliders and splitbars. Just add a property 'split' to the items to be resizable.

Here we go:


Ext.namespace('Ext.ux.layout');

/**
* @class Ext.ux.layout.RowFitLayout
* @extends Ext.layout.ContainerLayout
* <p>Layout that distributes heights of elements so they take 100% of the
* container height.</p>
* <p>Height of the child element can be given in pixels (as an integer) or
* in percent. All elements with absolute height (i.e. in pixels) always will
* have the given height. All "free" space (that is not filled with elements
* with 'absolute' height) will be distributed among other elements in
* proportion of their height percentage. Elements without 'height' in the
* config will take equal portions of the "unallocated" height.</p>
* <p>Supports panel collapsing, hiding, removal/addition. The adapter is provided
* to use with Ext.SplitBar: <b>Ext.ux.layout.RowFitLayout.SplitAdapter</b>.</p>
* <p>Example usage:</p>
* <pre><code>
var vp = new Ext.Viewport({
layout: 'row-fit',
items: [
{ xtype: 'panel', height: 100, title: 'Height in pixels', html: 'panel height = 100px' },
{ xtype: 'panel', height: "50%", title: '1/2', html: 'Will take half of remaining height' },
{ xtype: 'panel', title: 'No height 1', html: 'Panel without given height', id: '' },
{ xtype: 'panel', title: 'No height 2', html: 'Another panel' }
]
});
* </code></pre>
* Usage of the split bar adapter:
* <pre><code>
var split = new Ext.SplitBar("elementToDrag", "elementToSize", Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
// note the Ext.SplitBar object is passed to the adapter constructor to set
// correct minSize and maxSize:
split.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));
* </code></pre>
*/

Ext.ux.layout.RowFitLayout = Ext.extend(Ext.layout.ContainerLayout, {
// private
monitorResize: true,

// private
trackChildEvents: ['collapse', 'expand', 'hide', 'show'],

// private
splitHeight: 5,
rendered: false,

// private
renderItem: function(c, position, target) {
Ext.ux.layout.RowFitLayout.superclass.renderItem.apply(this, arguments);

// add event listeners
for (var i=0, n = this.trackChildEvents.length; i < n; i++) {
var ev = this.trackChildEvents[i];
//c.on(this.trackChildEvents[i], this.itemListener, this);
c.on(ev, this['_item_' + ev], this);
}
c.animCollapse = false; // looks ugly together with row-fit layout

this.checkRelHeight(c);
},

checkRelHeight: function(c) {

// store some layout-specific calculations
if(!c.rowFit) c.rowFit = {
hasAbsHeight: false, // whether the component has absolute height (in pixels)
relHeight: 0, // relative height, in pixels (if applicable)
calcRelHeight: 0, // calculated relative height (used when element is resized)
calcAbsHeight: 0, // calculated absolute height
height: c.height // save height config
};

// process height config option
if (c.height) {
var height = c.rowFit.height || c.height;
// store relative (given in percent) height
if (typeof height == "string" && height.indexOf("%")) {
c.rowFit.relHeight = parseInt(height);
}
else { // set absolute height
c.setHeight(c.height);
//c.rowFit.hasAbsHeight = true;
c.rowFit.hasAbsHeight = !Boolean(c.split);
}
}
//if(c.split) c.rowFit.hasAbsHeight = false;
c.isResizable = c.isResizable || Boolean(c.split) || !c.rowFit.hasAbsHeight;
},

// private
onLayout: function(ct, target) {

Ext.ux.layout.RowFitLayout.superclass.onLayout.call(this, ct, target);

if (this.container.collapsed || !ct.items || !ct.items.length) {
return;
}

// first loop: determine how many elements with relative height are there,
// sums of absolute and relative heights etc.
var absHeightSum = 0, // sum of elements' absolute heights
relHeightSum = 0, // sum of all percent heights given in children configs
relHeightRatio = 1, // "scale" ratio used in case sum <> 100%
noHeightCount = 0, // number of elements with no height given
relHeightElements = []; // array of elements with 'relative' height for the second loop

for (var i=0, n = ct.items.length; i < n; i++) {
var c = ct.items.itemAt(i);

if (!c.isVisible()) { continue; }

// collapsed panel is treated as an element with absolute height
if (c.collapsed) {
absHeightSum += c.getFrameHeight();
}
else if (c.rowFit.hasAbsHeight) { // element that has an absolute height
absHeightSum += c.height;
}
else { // 'relative-heighted'
if (!c.rowFit.relHeight) { // element with no height given
noHeightCount++;
}
else {
relHeightSum += c.rowFit.relHeight;
}
relHeightElements.push(c);
}
}

// if sum of relative heights <> 100% (e.g. error in config or consequence
// of collapsing/removing panels), scale 'em so it becomes 100%
if (noHeightCount == 0 && relHeightSum != 100) {
relHeightRatio = 100 / relHeightSum;
}

var freeHeight = target.getStyleSize().height - absHeightSum, // "unallocated" height we have
absHeightLeft = freeHeight; // track how much free space we have

while (relHeightElements.length) {
var c = relHeightElements.shift(), // element we're working with
relH = c.rowFit.relHeight * relHeightRatio, // height of this element in percent
absH = 0; // height in pixels

// no height in config
if (!relH) {
relH = (100 - relHeightSum) / noHeightCount;
}

// last element takes all remaining space
if (!relHeightElements.length) { absH = absHeightLeft; }
else { absH = Math.round(freeHeight * relH / 100); }

// anyway, height can't be negative
if (absH < 0) { absH = 0; }

c.rowFit.calcAbsHeight = absH;
c.rowFit.calcRelHeight = relH;

c.setHeight(absH);
absHeightLeft -= absH;
}

for (var i=0, n = ct.items.length; i < n; i++) {
var c = ct.items.itemAt(i);
if(c.isSlider && c.el2resize) {
// this.checkRelHeight(c);
var split = new Ext.SplitBar(c.el, c.el2resize.el, Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
split.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));
c.el2resize.sliderId = c.getId();
c.el2resize = false;
}
}

if(!this.rendered) { // keep watching for changes of items
ct.on('add', this.ctAddItem, this);
ct.on('remove', this.ctDelItem, this);
this.rendered = true;
}
},

// private - called from Ext.Container
setContainer : function(ct){
Ext.ux.layout.RowFitLayout.superclass.setContainer.call(this, ct);
this._addSliders(ct);
},

// private
_addSliders: function(ct) {
var sh = ct.splitHeight || this.splitHeight;
var skip1 = true;
var n = ct.items.length;
for(var i = n-1; i >= 0; i--) {
var c = ct.items.itemAt(i);

this.checkRelHeight(c);
if(c.isResizable) { // !c.rowFit.hasAbsHeight) {
if(skip1) {
skip1 = false;
continue;
}

if(c.split) {
var slider = new Ext.Panel({height:sh, isSlider: true});
slider.el2resize = c;
slider.addClass('x-splitbar-y');
ct.insert(i+1, slider);
}
}
}
},

/**
* Add event listener for container children
* @private
*/
itemListener: function(item) {
item.ownerCt.doLayout();
},
_item_show: function(comp) {
if(!comp.isSlider && comp.sliderId) {
var sl = comp.ownerCt.findById(comp.sliderId);
if(!sl.isVisible()) {
sl.show();
return;
}
}
comp.ownerCt.doLayout();
},
_item_hide: function(comp) {
if(!comp.isSlider && comp.sliderId) {
var sl = comp.ownerCt.findById(comp.sliderId);
if(sl.isVisible()) {
sl.hide();
return;
}
}
comp.ownerCt.doLayout();
},
_item_expand: function(comp) {
this._item_show(comp);
},
_item_collapse: function(comp) {
this._item_hide(comp);
},

/**
* Event listener for the container (on add, remove)
* @private
*/
ctAddItem: function(ct, comp, idx) {
// TODO: ev. add slider & splitbar
ct.doLayout();
},
ctDelItem: function(ct, comp) {
// TODO: ev. remove slider & splitbar
ct.doLayout();
}

});


// Split adapter
if (Ext.SplitBar.BasicLayoutAdapter) {

/**
* @param {Ext.SplitBar} splitbar to which adapter is applied.
* If supplied, will set correct minSize and maxSize.
*/
Ext.ux.layout.RowFitLayout.SplitAdapter = function(splitbar) {
if (splitbar && splitbar.el.dom.nextSibling) {
var next = Ext.getCmp( splitbar.el.dom.nextSibling.id ),
resized = Ext.getCmp(splitbar.resizingEl.id);

// skip abs-height non-resizable components
while(next && (next.collapsed || !next.isVisible() || !next.isResizable)) {
next = Ext.getCmp(next.el.dom.nextSibling.id);
}

if (next) {
//splitbar.maxSize = (resized.height || resized.rowFit.calcAbsHeight) +
splitbar.maxSize = (resized.rowFit.hasAbsHeight ? resized.rowFit.calcAbsHeight : resized.getSize().height) +
next.getInnerHeight() - 1; // seems can't set height=0 in IE, "1" works fine
}
splitbar.minSize = resized.getFrameHeight() + 1;
}
}

Ext.extend(Ext.ux.layout.RowFitLayout.SplitAdapter, Ext.SplitBar.BasicLayoutAdapter, {

setElementSize: function(splitbar, newSize, onComplete) {
var resized = Ext.getCmp(splitbar.resizingEl.id);

// can't resize absent, collapsed or hidden panel
if (!resized || resized.collapsed || !resized.isVisible()) return;

// resizingEl has absolute height: just change it
if (resized.rowFit.hasAbsHeight) {
resized.setHeight(newSize);
}
// resizingEl has relative height: affects next sibling
else {
if (splitbar.el.dom.nextSibling) {
var nextSibling = Ext.getCmp( splitbar.el.dom.nextSibling.id );
// skip abs-height non-resizable components
while(nextSibling && (nextSibling.collapsed || !nextSibling.isVisible() || !nextSibling.isResizable)) {
nextSibling = Ext.getCmp(nextSibling.el.dom.nextSibling.id);
}

var deltaAbsHeight = newSize - resized.rowFit.calcAbsHeight, // pixels
nsRf = nextSibling.rowFit, // shortcut
rzRf = resized.rowFit,
// pixels in a percent
pctPxRatio = rzRf.calcRelHeight / rzRf.calcAbsHeight,
deltaRelHeight = pctPxRatio * deltaAbsHeight; // change in height in percent

rzRf.relHeight = rzRf.calcRelHeight + deltaRelHeight;

if (nsRf.hasAbsHeight) {
var newHeight = nextSibling.height - deltaAbsHeight;
nextSibling.height = newHeight;
nextSibling.setHeight(newHeight);
}
else {
nsRf.relHeight = nsRf.calcRelHeight - deltaRelHeight;
}
}
}
// recalculate heights
resized.ownerCt.doLayout();
} // of setElementSize

}); // of SplitAdapter
}

Ext.Container.LAYOUTS['row-fit'] = Ext.ux.layout.RowFitLayout;
still missing: better handling of add- and remove-events on the container to add/remove sliders and splitbars as well.

Now if only someone extended the ColumnLayout to have resizable columns ;-)

Comments?

ray007
27 Dec 2007, 6:03 AM
I just found a little problem, probably also with the original version and not only with my modified one:
internet explorer doesn't scroll the content of the items in the container if too large, while firefox and opera are doing just fine here. I'm getting a rendering error in a different place with those 2 browsers, but that's another story ...
Does anybody have an idea what's going wrong here?

sgan
5 Jan 2008, 8:37 AM
Hi,


I need to add a Ext.ViewPort to an existing jsp, basically render the viewport to a div which resides in the existing jsp page.

I found the Ext.viewport(with all its panels within) always rendered starting at leftmost and topmost point of the browser(FireFox specifically).Is it correct to try to render a Ext.ViewPort into portion of JSP? For the viewport part seems to take over the whole screen.

Thanks a lot,

DigitalSkyline
5 Jan 2008, 3:16 PM
You could've posted in help, but anyways to answer, no ViewPort is descendant of document.body, it can not reside in a div. For this you'll need to use a panel.

ps - Isn't JSP irrelevant to the browser/discussion?

sgan
6 Jan 2008, 11:03 AM
Yep, you are right. I can not render the viewport to a div.

What i tried is to put the viewport into a ext panel and then render the panel to a div.
The div is within an existing JSP, my hope is to embed the previous panel to the page,
what i saw is the panel (with viewport in it) occupy the full browser screen, which is not expected of my original attempt.

Note:can the viewport not occupy the full screen or am i wrong in expecting it not?

mgeri
8 Jan 2008, 9:43 AM
Thanks for your work. Using GridPanel as items I could't get the horizontal scrollbar to show up. I changed the doLayout method to set also the panel width and now seems to work.



onLayout : function(ct, target) {

Ext.ux.layout.RowFitLayout.superclass.onLayout.call(this,
ct, target);

if (this.container.collapsed || !ct.items
|| !ct.items.length) {
return;
}

// first loop: determine how many elements with relative
// height are there,
// sums of absolute and relative heights etc.
var absHeightSum = 0, // sum of elements' absolute heights
relHeightSum = 0, // sum of all percent heights given in
// children configs
relHeightRatio = 1, // "scale" ratio used in case sum <>
// 100%
noHeightCount = 0, // number of elements with no height
// given
relHeightElements = []; // array of elements with 'relative'
// height for the second loop

var targetSize = target.getStyleSize();

for (var i = 0, n = ct.items.length;i < n; i++) {
var c = ct.items.itemAt(i);

if (!c.isVisible()) {
continue;
}

// collapsed panel is treated as an element with
// absolute height
if (c.collapsed) {
var h = c.getFrameHeight();
absHeightSum += h;
c.setSize({width:targetSize.width, height: h});

} else if (c.rowFit.hasAbsHeight) { // element that has
// an absolute
// height
absHeightSum += c.height;
c.setSize({width:targetSize.width, height: c.heigh});

} else { // 'relative-heighted'
if (!c.rowFit.relHeight) { // element with no
// height given
//noHeightCount++;
absHeightSum += c.getFrameHeight();
c.setSize({width:targetSize.width, height: c.heigh});
} else {
relHeightSum += c.rowFit.relHeight;
relHeightElements.push(c);
}

}
}

// if sum of relative heights <> 100% (e.g. error in config
// or consequence
// of collapsing/removing panels), scale 'em so it becomes
// 100%
if (noHeightCount == 0 && relHeightSum != 100) {
relHeightRatio = 100 / relHeightSum;
}

var freeHeight = target.getStyleSize().height
- absHeightSum, // "unallocated" height we have
absHeightLeft = freeHeight; // track how much free space we
// have

while (relHeightElements.length) {
var c = relHeightElements.shift(), // element we're
// working with
relH = c.rowFit.relHeight * relHeightRatio, // height of
// this
// element
// in
// percent
absH = 0; // height in pixels

// no height in config
if (!relH) {
relH = (100 - relHeightSum) / noHeightCount;
}

// last element takes all remaining space
if (!relHeightElements.length) {
absH = absHeightLeft;
} else {
absH = Math.round(freeHeight * relH / 100);
}

// anyway, height can't be negative
if (absH < 0) {
absH = 0;
}

c.rowFit.calcAbsHeight = absH;
c.rowFit.calcRelHeight = relH;
c.setSize({width:targetSize.width, height: absH});

absHeightLeft -= absH;
}

for (var i = 0, n = ct.items.length;i < n; i++) {
var c = ct.items.itemAt(i);
if (c.isSlider && c.el2resize) {
// this.checkRelHeight(c);
var split = new Ext.SplitBar(c.el, c.el2resize.el,
Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
split
.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));
c.el2resize.sliderId = c.getId();
c.el2resize = false;
}
}

if (!this.rendered) { // keep watching for changes of
// items
ct.on('add', this.ctAddItem, this);
ct.on('remove', this.ctDelItem, this);
this.rendered = true;
}
}

bcamp1973
25 Jan 2008, 10:27 AM
I'm having some trouble with the plugin. the first panel always loads collapsed. It also doesn't seem to tie into the state manager? More here...

http://extjs.com/forum/showthread.php?p=114992#post114992

thommy
14 Feb 2008, 12:00 AM
It doesn't render perfect as a part of a border layout (with collapsable neighbors), but the result is convenient.

It supports the minWidth property of panels in connection with the split adapter.



Ext.namespace('Ext.ux.layout');

/**
* @class Ext.ux.layout.ColFitLayout
* @extends Ext.layout.ColumnLayout
* <p>Layout that distributes widths of elements so they take 100% of the
* container width.</p>
* <p>Width of the child element can be given in pixels (as an integer) or
* in percent. All elements with absolute width (i.e. in pixels) always will
* have the given width. All "free" space (that is not filled with elements
* with 'absolute' width) will be distributed among other elements in
* proportion of their width percentage. Elements without 'width' in the
* config will take equal portions of the "unallocated" width.</p>
* <p>Supports panel hiding, removal/addition. The adapter is provided
* to use with Ext.SplitBar: <b>Ext.ux.layout.ColFitLayout.SplitAdapter</b>.</p>
* <p>Example usage:</p>
* <pre><code>
var vp = new Ext.Viewport({
layout: 'col-fit',
items: [
{ xtype: 'panel', width: 100, title: 'Width in pixels', split: true, html: 'panel width = 100px' },
{ xtype: 'panel', width: "50%", title: '1/2', split: true, html: 'Will take half of remaining width' },
{ xtype: 'panel', title: 'No width 1', html: 'Panel without given width', id: '' },
{ xtype: 'panel', title: 'No width 2', html: 'Another panel' }
]
});
* </code></pre>
*/

Ext.ux.layout.ColFitLayout = Ext.extend(Ext.layout.ColumnLayout, {
// private
monitorResize: true,

// private
adapters: [], // access to split adapters for recalculate the size limits
splitWidth: 3,
rendered: false,

// private
renderItem: function(c, position, target) {
Ext.ux.layout.ColFitLayout.superclass.renderItem.apply(this, arguments);
this.checkRelWidth(c);
},

checkRelWidth: function(c) {
// store some layout-specific calculations
if (!c.colFit) {
// map columnWidth to width given in percent
if (c.columnWidth) {
c.width = Math.round(c.columnWidth*100) + '%';
}
c.colFit = {
hasAbsWidth: false, // whether the component has absolute width (in pixels)
relWidth: 0, // relative width, in pixels (if applicable)
calcRelWidth: 0, // calculated relative width (used when element is resized)
calcAbsWidth: 0, // calculated absolute width
width: c.width, // save width config
minWidth: c.minWidth ? c.minWidth : 10
};
}
// process width config option
if (c.width) {
var width = c.colFit.width || c.width;
// store relative (given in percent) width
if (typeof width == "string" && width.indexOf("%")) {
c.colFit.relWidth = parseInt(width);
}
else { // set absolute width
c.setWidth(c.width);
c.colFit.hasAbsWidth = !Boolean(c.split);
}
}
c.isResizable = c.isResizable || Boolean(c.split) || !c.colFit.hasAbsWidth;
},

// private
onLayout: function(ct, target) {

Ext.ux.layout.ColFitLayout.superclass.onLayout.call(this, ct, target);

if (!ct.items || !ct.items.length) {
return;
}

// first loop: determine how many elements with relative width are there,
// sums of absolute and relative heights etc.
var absWidthSum = 0, // sum of elements' absolute heights
relWidthSum = 0, // sum of all percent heights given in children configs
relWidthRatio = 1, // "scale" ratio used in case sum <> 100%
noWidthCount = 0, // number of elements with no width given
relWidthElements = []; // array of elements with 'relative' width for the second loop

for (var i=0, n = ct.items.length; i < n; i++) {
var c = ct.items.itemAt(i);

if (!c.isVisible()) { continue; }

if (c.colFit.hasAbsWidth) { // element that has an absolute width
absWidthSum += c.width;
}
else { // 'relative-widthed'
if (!c.colFit.relWidth) { // element with no width given
noWidthCount++;
}
else {
relWidthSum += c.colFit.relWidth;
}
relWidthElements.push(c);
}
}

// if sum of relative widths <> 100% (e.g. error in config or consequence
// of removing panels), scale 'em so it becomes 100%
if (noWidthCount == 0 && relWidthSum != 100) {
relWidthRatio = 100 / relWidthSum;
}

var viewSize = target.getViewSize();

var outerWidth = viewSize.width;
var innerDiv = Ext.get(target.dom.firstChild.id);
var innerWidth = innerDiv ? innerDiv.getViewSize().width : outerWidth;
var height = viewSize.height;

// outerWidth != innerWidth if a scrollbar is showing

var doScndCalc = this.setItemsWidth(relWidthElements, outerWidth - absWidthSum, relWidthSum, noWidthCount, relWidthRatio, height);
if (doScndCalc && outerWidth != innerWidth) {
// to suppress horizontal scrollbars recalculate the widths
this.setItemsWidth(relWidthElements, innerWidth - absWidthSum, relWidthSum, noWidthCount, relWidthRatio, height);
}
else {
// suppress the vertical scrollbar
if (outerWidth != target.getViewSize().width) {
var e = Ext.get(target.dom.firstChild.id);
e.setWidth(outerWidth);
}
}

var sliderHeight = 0;

for (var i=0, n = ct.items.length; i < n; i++) {
var c = ct.items.itemAt(i);
// sliders height is set to the heightest resizable element
if (!c.isSlider) {
sliderHeight = Math.max(sliderHeight, c.getSize().height);
}
if (c.isSlider && c.el2resize) {
var split = new Ext.SplitBar(c.el, c.el2resize.el, Ext.SplitBar.HORIZONTAL, Ext.SplitBar.RIGTH);
split.setAdapter(new Ext.ux.layout.ColFitLayout.SplitAdapter(split));
c.el2resize.sliderId = c.getId();
c.el2resize = false;
c.el.adapters = this.adapters;
this.adapters.push(split);
}
}

sliderHeight = Math.max(sliderHeight, target.getViewSize().height);

// set the sliders height
for (var i = 0, n = ct.items.length; i < n; i++) {
var c = ct.items.itemAt(i);
if(c.isSlider) {
c.setHeight(sliderHeight);
}
}

if(!this.rendered) { // keep watching for changes of items
ct.on('add', this.ctAddItem, this);
ct.on('remove', this.ctDelItem, this);
this.rendered = true;
}
},

setItemsWidth: function(items, freeWidth, relWidthSum, noWidthCount, relWidthRatio, parentHeight) {
var absWidthLeft = freeWidth;
var isHigher = false;

for (var i = 0, n = items.length; i < n; i++) {
var c = items[i], // element we're working with
relW = c.colFit.relWidth * relWidthRatio, // width of this element in percent
absW = 0; // width in pixels
// no width in config
if (!relW) {
relW = (100 - relWidthSum) / noWidthCount;
}
// last element takes all remaining space
absW = i == n - 1? absWidthLeft: Math.round(freeWidth * relW / 100);

// anyway, width can't be negative
absW = Math.max(0, absW);

c.colFit.calcAbsWidth = absW;
c.colFit.calcRelWidth = relW;
c.setWidth(absW);
isHigher == isHigher || (c.getSize().height > parentHeight);
absWidthLeft -= absW;
}
return isHigher;
},

// private - called from Ext.Container
setContainer : function(ct){
Ext.ux.layout.ColFitLayout.superclass.setContainer.call(this, ct);
this._addSliders(ct);
},

// private
_addSliders: function(ct) {
var sw = ct.splitWidth || this.splitWidth;
var skip1 = true;

for (var i = ct.items.length-1; i >= 0; i--) {
var c = ct.items.itemAt(i);

this.checkRelWidth(c);
if (c.isResizable) {
if (skip1) {
skip1 = false;
continue;
}

if (c.split) {
var slider = new Ext.Panel({width: sw, isSlider: true});
slider.el2resize = c;
slider.addClass('y-splitbar-x');
ct.insert(i+1, slider);
}
}
}
},

/**
* Event listener for the container (on add, remove)
*
* @private
*/
ctAddItem: function(ct, comp, idx) {
// todo
ct.doLayout();
},
ctDelItem: function(ct, comp) {
// todo
ct.doLayout();
}
});


// Split adapter
if (Ext.SplitBar.BasicLayoutAdapter) {

/**
* @param {Ext.SplitBar} splitbar to which adapter is applied.
* If supplied, will set correct minSize and maxSize.
*/
Ext.ux.layout.ColFitLayout.SplitAdapter = function(splitbar){
this.setLimits(splitbar);
}

Ext.extend(Ext.ux.layout.ColFitLayout.SplitAdapter, Ext.SplitBar.BasicLayoutAdapter, {

setLimits: function(splitbar) {
if (splitbar && splitbar.el.dom.nextSibling) {
var next = Ext.getCmp(splitbar.el.dom.nextSibling.id), resized = Ext.getCmp(splitbar.resizingEl.id);

// skip abs-width non-resizable components
while (next && (!next.isVisible() || !next.isResizable)) {
next = Ext.getCmp(next.el.dom.nextSibling.id);
}

if (next) {
splitbar.maxSize = (resized.colFit.hasAbsWidth ?
resized.colFit.calcAbsWidth : resized.getSize().width)
+ next.getInnerWidth() - 1 // seems can't set width=0 in IE, "1" works fine
- next.colFit.minWidth;
}
splitbar.minSize = resized.getFrameWidth() + 1 + resized.colFit.minWidth;
}
},

setElementSize: function(splitbar, newSize, onComplete){
var resized = Ext.getCmp(splitbar.resizingEl.id);

// can't resize absent or hidden panel
if (!resized || !resized.isVisible())
return;

// resizingEl has absolute width: just change it
var oldWidth = resized.getSize().width;

if (resized.colFit.hasAbsWidth) {
resized.setWidth(newSize);
}
// resizingEl has relative width: affects next sibling
else {
if (splitbar.el.dom.nextSibling) {
var nextSibling = Ext.getCmp(splitbar.el.dom.nextSibling.id);
// skip abs-width non-resizable components
while (nextSibling && (!nextSibling.isVisible() || !nextSibling.isResizable)) {
nextSibling = Ext.getCmp(nextSibling.el.dom.nextSibling.id);
}

var deltaAbsWidth = newSize - resized.colFit.calcAbsWidth, // pixels
nsRf = nextSibling.colFit, // shortcut
rzRf = resized.colFit, // pixels in a percent
pctPxRatio = rzRf.calcRelWidth / rzRf.calcAbsWidth, deltaRelWidth = pctPxRatio * deltaAbsWidth; // change in width in percent
rzRf.relWidth = rzRf.calcRelWidth + deltaRelWidth;

if (nsRf.hasAbsWidth) {
var newWidth = nextSibling.width - deltaAbsWidth;
nextSibling.width = newWidth;
nextSibling.setWidth(newWidth);
}
else {
nsRf.relWidth = nsRf.calcRelWidth - deltaRelWidth;
}
}
}
// recalculate widths
resized.ownerCt.doLayout();

// recalculate limits
for (var i = 0, n = splitbar.el.adapters.length; i < n; i++) {
this.setLimits(splitbar.el.adapters[i]);
}
} // of setElementSize
}); // of SplitAdapter
}

Ext.Container.LAYOUTS['col-fit'] = Ext.ux.layout.ColFitLayout;

benjamin.arroyo
25 Feb 2008, 8:57 AM
Mgeri, thanks for your modification.
It works fine but you have to correct a small bug: "heigh" should be "height" :)

Here is your onLayout function corrected:


onLayout : function(ct, target) {

Ext.ux.layout.RowFitLayout.superclass.onLayout.call(this,
ct, target);

if (this.container.collapsed || !ct.items
|| !ct.items.length) {
return;
}

// first loop: determine how many elements with relative
// height are there,
// sums of absolute and relative heights etc.
var absHeightSum = 0, // sum of elements' absolute heights
relHeightSum = 0, // sum of all percent heights given in
// children configs
relHeightRatio = 1, // "scale" ratio used in case sum <>
// 100%
noHeightCount = 0, // number of elements with no height
// given
relHeightElements = []; // array of elements with 'relative'
// height for the second loop

var targetSize = target.getStyleSize();

for (var i = 0, n = ct.items.length;i < n; i++) {
var c = ct.items.itemAt(i);

if (!c.isVisible()) {
continue;
}

// collapsed panel is treated as an element with
// absolute height
if (c.collapsed) {
var h = c.getFrameHeight();
absHeightSum += h;
c.setSize({width:targetSize.width, height: h});

} else if (c.rowFit.hasAbsHeight) { // element that has
// an absolute
// height
absHeightSum += c.height;
c.setSize({width:targetSize.width, height: c.height});

} else { // 'relative-heighted'
if (!c.rowFit.relHeight) { // element with no
// height given
//noHeightCount++;
absHeightSum += c.getFrameHeight();
c.setSize({width:targetSize.width, height: c.height});
} else {
relHeightSum += c.rowFit.relHeight;
relHeightElements.push(c);
}

}
}

// if sum of relative heights <> 100% (e.g. error in config
// or consequence
// of collapsing/removing panels), scale 'em so it becomes
// 100%
if (noHeightCount == 0 && relHeightSum != 100) {
relHeightRatio = 100 / relHeightSum;
}

var freeHeight = target.getStyleSize().height
- absHeightSum, // "unallocated" height we have
absHeightLeft = freeHeight; // track how much free space we
// have

while (relHeightElements.length) {
var c = relHeightElements.shift(), // element we're
// working with
relH = c.rowFit.relHeight * relHeightRatio, // height of
// this
// element
// in
// percent
absH = 0; // height in pixels

// no height in config
if (!relH) {
relH = (100 - relHeightSum) / noHeightCount;
}

// last element takes all remaining space
if (!relHeightElements.length) {
absH = absHeightLeft;
} else {
absH = Math.round(freeHeight * relH / 100);
}

// anyway, height can't be negative
if (absH < 0) {
absH = 0;
}

c.rowFit.calcAbsHeight = absH;
c.rowFit.calcRelHeight = relH;
c.setSize({width:targetSize.width, height: absH});

absHeightLeft -= absH;
}

for (var i = 0, n = ct.items.length;i < n; i++) {
var c = ct.items.itemAt(i);
if (c.isSlider && c.el2resize) {
// this.checkRelHeight(c);
var split = new Ext.SplitBar(c.el, c.el2resize.el,
Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
split
.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));
c.el2resize.sliderId = c.getId();
c.el2resize = false;
}
}

if (!this.rendered) { // keep watching for changes of
// items
ct.on('add', this.ctAddItem, this);
ct.on('remove', this.ctDelItem, this);
this.rendered = true;
}
}



Thanks for your work. Using GridPanel as items I could't get the horizontal scrollbar to show up. I changed the doLayout method to set also the panel width and now seems to work.



onLayout : function(ct, target) {

Ext.ux.layout.RowFitLayout.superclass.onLayout.call(this,
ct, target);

if (this.container.collapsed || !ct.items
|| !ct.items.length) {
return;
}

// first loop: determine how many elements with relative
// height are there,
// sums of absolute and relative heights etc.
var absHeightSum = 0, // sum of elements' absolute heights
relHeightSum = 0, // sum of all percent heights given in
// children configs
relHeightRatio = 1, // "scale" ratio used in case sum <>
// 100%
noHeightCount = 0, // number of elements with no height
// given
relHeightElements = []; // array of elements with 'relative'
// height for the second loop

var targetSize = target.getStyleSize();

for (var i = 0, n = ct.items.length;i < n; i++) {
var c = ct.items.itemAt(i);

if (!c.isVisible()) {
continue;
}

// collapsed panel is treated as an element with
// absolute height
if (c.collapsed) {
var h = c.getFrameHeight();
absHeightSum += h;
c.setSize({width:targetSize.width, height: h});

} else if (c.rowFit.hasAbsHeight) { // element that has
// an absolute
// height
absHeightSum += c.height;
c.setSize({width:targetSize.width, height: c.heigh});

} else { // 'relative-heighted'
if (!c.rowFit.relHeight) { // element with no
// height given
//noHeightCount++;
absHeightSum += c.getFrameHeight();
c.setSize({width:targetSize.width, height: c.heigh});
} else {
relHeightSum += c.rowFit.relHeight;
relHeightElements.push(c);
}

}
}

// if sum of relative heights <> 100% (e.g. error in config
// or consequence
// of collapsing/removing panels), scale 'em so it becomes
// 100%
if (noHeightCount == 0 && relHeightSum != 100) {
relHeightRatio = 100 / relHeightSum;
}

var freeHeight = target.getStyleSize().height
- absHeightSum, // "unallocated" height we have
absHeightLeft = freeHeight; // track how much free space we
// have

while (relHeightElements.length) {
var c = relHeightElements.shift(), // element we're
// working with
relH = c.rowFit.relHeight * relHeightRatio, // height of
// this
// element
// in
// percent
absH = 0; // height in pixels

// no height in config
if (!relH) {
relH = (100 - relHeightSum) / noHeightCount;
}

// last element takes all remaining space
if (!relHeightElements.length) {
absH = absHeightLeft;
} else {
absH = Math.round(freeHeight * relH / 100);
}

// anyway, height can't be negative
if (absH < 0) {
absH = 0;
}

c.rowFit.calcAbsHeight = absH;
c.rowFit.calcRelHeight = relH;
c.setSize({width:targetSize.width, height: absH});

absHeightLeft -= absH;
}

for (var i = 0, n = ct.items.length;i < n; i++) {
var c = ct.items.itemAt(i);
if (c.isSlider && c.el2resize) {
// this.checkRelHeight(c);
var split = new Ext.SplitBar(c.el, c.el2resize.el,
Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
split
.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));
c.el2resize.sliderId = c.getId();
c.el2resize = false;
}
}

if (!this.rendered) { // keep watching for changes of
// items
ct.on('add', this.ctAddItem, this);
ct.on('remove', this.ctDelItem, this);
this.rendered = true;
}
}

sjivan
2 Mar 2008, 6:15 PM
RowFitLayout appears to break with Ext 2.0.2. It appears to be breaking when Ext is calling


setLayout : function(layout){
if(this.layout && this.layout != layout){
this.layout.setContainer(null);
}
this.initItems();
this.layout = layout;
==> layout.setContainer(this);
}

No such method on the layout.setContainer(this) line.

Sanjiv

mm_202
7 Mar 2008, 7:40 AM
Anyone else have a problem with getting the width of the container to play nice when using layout:'row-fit' inside IE?



var memberpanel = new Ext.grid.GridPanel({
//title:qn,
//id:qid,
//seen:true,
autoScroll:true,
stripeRows:true,
//autoWidth:true,
autoHeight:true,
//closable:true,
store: memberds,
columns: [
{header:'AgentID', width:80, sortable:true, dataIndex:'code', renderer:drCode},
{header:'Agent Name', sortable:true, dataIndex:'name'},
{header:'Priority', width:100, sortable:true, dataIndex:'penalty'},
{header:'Extension', width:100, sortable:true, dataIndex:'ext'},
{header:'Elapsed', width:120, sortable:true, dataIndex:'statustime', renderer:drDuration},
{header:'StatusID', sortable:true, dataIndex:'statusid', hidden:true},
{header:'Status', sortable:true, dataIndex:'status'},
{header:'Calls Taken', sortable:true, dataIndex:'callstaken'},
{header:'Last Call', sortable:true, dataIndex:'lastcall', align:'right', renderer:drDuration}
],
view:gvRowColor
});

var panel = new Ext.Panel({
title:qn,
id:qid,
seen:true,
layout:'row-fit',
//autoWidth:true,
//autoHeight:true,
width:750,
border:false,
items:[infopanel,memberpanel],
listeners:{
show:function(){
...
return true;
},
hide:function(){
...
return true;
}
},
tbar: new Ext.Toolbar({
frame:false, border:false,
bodyStyle:'padding:5px 5px 5px 5px',
items: [
....
]
})
});

parent.add(panel);


parent is a TabPanel, and memberpanel works perfect if I just add it directly to parent.

It has to be something minor (or something that Im doing wrong) because it renders perfectly in FF...

wasp
5 Apr 2008, 3:57 AM
I'm having weird bug when resize window which have row fit layout somewhere inside ...

This is my example:
http://up.drun.net/v/s/2/f/row-fit-bug-01.png (http://up.drun.net/i/f/row-fit-bug-01.png)

when i resize horizontally, it does not resize correctly:

http://up.drun.net/v/s/2/f/row-fit-bug-02.png (http://up.drun.net/i/f/row-fit-bug-02.png)

and after this, when I resize vertically it is okay again:

http://up.drun.net/v/s/2/f/row-fit-bug-03.png (http://up.drun.net/i/f/row-fit-bug-03.png)


I tried to find out what the problem is, but could not find anything unusual :( onLayout gets called in both cases, but different things happen.

Any ideas ?

adrianrosca
11 Apr 2008, 3:58 AM
This class was the perfect solution to what nearly drove me nuts with the AnchorLayout. Superb!

But I also had problems with getting the width to work properly. So i added "c.setWidth();" in the bottom of the onLayout method. Worked for me, but it may screw up other cases than mine.

tarini
16 Apr 2008, 1:34 PM
it works very well :)

thank u so much

PS
can i make a suggestion?? it will be useful adding a SplitBar to resize vertically panels maybe using the split properties of the panel

tarini
17 Apr 2008, 5:27 AM
I found a little bug...

If I resize a rowFitLayout panel it correctly resize its contained panel
but it doesn't refresh nested panel...

In my example-screenshot i have a border layout viewport with two region:
- west region: a treepanel
- center region: a rowFitLayout panel contains two tabPanel. The first tabPanel contains a simple Panel and two GridPanel. The second just a simple Panel

when I collapse westregion of the viewport grids don't resize...

adrianrosca
17 Apr 2008, 6:53 AM
I think it might be settings on your gridpanel that causes that since your bottom tabpanel seems to behave properly. Maybe grid.setWidth() after the collapse?

tarini
17 Apr 2008, 7:16 AM
I think it might be settings on your gridpanel that causes that since your bottom tabpanel seems to behave properly. Maybe grid.setWidth() after the collapse?


i don't think so because if i change layout-model of my center region (for example table layout with 1 columns and 2 rows) the grid will resize automatically in a right way...

a274688
28 Apr 2008, 5:31 AM
I'm trying to use row-fit in a tab panel. (see code below).

When I specify the height in % it does not work ..

Any ideas.

I'm using Extjs 2.0.2 but I tried it on 2.1 and there was no difference.


var cTab1 = new Ext.Panel({ title: 'Summary',
id: 'summaryTab',
layout: 'column',
items:[
{ columnWidth:.45,
style:'padding: 2px 2px 2px 2px',
items: new Ext.Panel ({
layout: 'row-fit',
items: [
{ xtype: 'panel',
height: 20%,
title: 'Summary Panel 1',
style:'padding:2px',
id: 'Panel1',
html: '<BR><BR>'
},
{ xtype: 'panel',
height: "20%",
title: 'Summary Panel 2',
style: 'padding:2px',
id: 'Panel2',
html: '<BR><BR>'
},
{ xtype: 'panel',
height: "20%",
title: 'Summary Panel 3',
style:'padding:2px',
id: 'Panel3',
html: '<BR><BR>'
},
{ xtype: 'panel',
height: "20%",
title: 'Summary Panel 4',
style:'padding:2px',
id: 'Panel4',
html: '<BR><BR>'
}]})

},{ columnWidth:.55,
style: 'padding: 2px 2px 2px 2px',
items: new Ext.Panel ({
layout: 'row-fit',
items:[{ height: 460,
style: 'padding:2px',
title: ' Data Grid 1 ',
id: 'Grid1',
layout: 'fit',
items: new dataGrid() },
{ autoHeight: true,
title: ' Data Grid 2 ',
style:'padding:2px',
id: 'Grid2',
layout: 'fit',
items: new dataGrid() }] })
}]
});

tarini
28 Apr 2008, 7:23 AM
maybe bacause the first height property doesn't have "" around 20%


because RowFitLayout SplitBar is different from BorderLayout SplitBar??

a274688
28 Apr 2008, 7:50 AM
That's a typo on my part ..

I had to correct the code because I had a fixed value of 200 there.
In my haste I missed the ""

tarini
5 May 2008, 12:14 AM
I've got a problem with this plugin. I've a panel (with row-fit layout) with two panel with height = 50% and a SplitBar between them.

I created 3 toolbar buttons to minimize, maximize and restore panel height.

In these buttons I call the method setHeight of each inner panel and it works.

But when I resize the window, row-fit layout restore my heights to initial values...

How can I tell the new forced height to the row-fit layout??

PS if I resize with splitbar I don't have this problem... I think I should call the same method called by SplitBar

pokerking400
12 May 2008, 3:53 AM
Big Thanks for this layout! Add it to extjs now!>:)

pokerking400
12 May 2008, 4:26 AM
How do i get split bar show up? My top panel size increase as i drop another panel inside... i need split bar to show the content

pokerking400
12 May 2008, 4:36 AM
How do i get the second panel goes down when i click user information ?...it is another hidden panel..also no split bars shows up when i add split:true

http://farm3.static.flickr.com/2077/2485662347_3269aa6603_o.png

welcome suggestion and advise!.:)

Every layout has something missing...i spent whole week in this layout...i should start hacking the code if nothing works...

tarini
20 May 2008, 7:55 AM
I've the same problem as pokerking...
how can we re-set "by hand" panel height?? i tried with setHeight method but if i resize page, my row-fit layout panel return as initial config (50%)

pokerking400
20 May 2008, 8:54 AM
Hey i solved mine!!!!!!


I was facing two issues though. One is panel inside formpanel was not 'fitting'. I fixed it by using anchor:'100% 100%" inside any child panels that is inside form panel and remove layout:'fit' from formpanel.

Secondly i used click event like this to resize the parent window and also i added scrollbar with autoScroll:true <=== see the caption of "S"...i was wasting lots of time putting autoscroll:true which was wrong..case sensitive...

here is sample code...



listeners: {
expand: {
fn: function()
{
var t=mywindow.ownerCt;
//myHeight=t.getEl().getHeight();
//t.setHeight(myHeight+200);
t.doLayout();
}
},
collapse: {
fn: function()
{
if(myHeight)
{
var t=mywindow.ownerCt;
//if(myHeight)
// t.setHeight(myHeight);
t.doLayout();
}
}
}
}

Hope that helps.:)

There is two you can fix it...either you resize window and bring it back when you collapse fieldset..or have doLayout and have autoScroll...

Both option works...here is autoScroll image

http://farm3.static.flickr.com/2400/2508301216_6d067f4cc1_o.png


http://farm3.static.flickr.com/2242/2497719347_e83578e202_o.png

pokerking400
20 May 2008, 8:55 AM
There is another trickk...i added fixed size to bottom panel...you can dynamically change settings if it neccessary and call doLayout.

Eric24
7 Jun 2008, 6:43 PM
Is there a "current version" of this extension? From the original posting, there have obviously been lots of bugs fixed and good enhancements added, but all with code snippets. Before I started reconstructing the modification chain, I was hoping that I could find the latest code.

By the way, for something simple like a panel with two grids (top and bottom) separated by a splitter, is this extension the way to go, or am I missing something simple that would let me do this?

Thanks!
Eric

badgerd
14 Aug 2008, 10:56 PM
Has anyone got this working for portals example?

I wish to keep all my portlets within the browser window instead of having to scroll if there are so many under each other. (I have a left tree navigation as well).

hansellh
18 Aug 2008, 2:44 AM
Why not just have it added to the extensions page?
http://extjs.com/learn/Ext_Extensions

hansellh
18 Aug 2008, 3:05 AM
Here is an updated version with all the changes in it


Ext.namespace('Ext.ux.layout');

/**
* @class Ext.ux.layout.RowFitLayout
* @extends Ext.layout.ContainerLayout
* <p>Layout that distributes heights of elements so they take 100% of the
* container height.</p>
* <p>Height of the child element can be given in pixels (as an integer) or
* in percent. All elements with absolute height (i.e. in pixels) always will
* have the given height. All "free" space (that is not filled with elements
* with 'absolute' height) will be distributed among other elements in
* proportion of their height percentage. Elements without 'height' in the
* config will take equal portions of the "unallocated" height.</p>
* <p>Supports panel collapsing, hiding, removal/addition. The adapter is provided
* to use with Ext.SplitBar: <b>Ext.ux.layout.RowFitLayout.SplitAdapter</b>.</p>
* <p>Example usage:</p>
* <pre><code>
var vp = new Ext.Viewport({
layout: 'row-fit',
items: [
{ xtype: 'panel', height: 100, title: 'Height in pixels', html: 'panel height = 100px' },
{ xtype: 'panel', height: "50%", title: '1/2', html: 'Will take half of remaining height' },
{ xtype: 'panel', title: 'No height 1', html: 'Panel without given height', id: '' },
{ xtype: 'panel', title: 'No height 2', html: 'Another panel' }
]
});
* </code></pre>
* Usage of the split bar adapter:
* <pre><code>
var split = new Ext.SplitBar("elementToDrag", "elementToSize", Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
// note the Ext.SplitBar object is passed to the adapter constructor to set
// correct minSize and maxSize:
split.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));
* </code></pre>
*/

Ext.ux.layout.RowFitLayout = Ext.extend(Ext.layout.ContainerLayout, {
// private
monitorResize: true,

// private
trackChildEvents: ['collapse', 'expand', 'hide', 'show'],

// private
splitHeight: 5,
rendered: false,

// private
renderItem: function(c, position, target) {
Ext.ux.layout.RowFitLayout.superclass.renderItem.apply(this, arguments);

// add event listeners
for (var i = 0,
n = this.trackChildEvents.length; i < n; i++) {
var ev = this.trackChildEvents[i];
//c.on(this.trackChildEvents[i], this.itemListener, this);
c.on(ev, this['_item_' + ev], this);
}
c.animCollapse = false; // looks ugly together with row-fit layout

this.checkRelHeight(c);
},

checkRelHeight: function(c) {

// store some layout-specific calculations
if (!c.rowFit) {
c.rowFit = {
hasAbsHeight: false,
// whether the component has absolute height (in pixels)
relHeight: 0,
// relative height, in pixels (if applicable)
calcRelHeight: 0,
// calculated relative height (used when element is resized)
calcAbsHeight: 0,
// calculated absolute height
height: c.height // save height config
};
}

// process height config option
if (c.height) {
var height = c.rowFit.height || c.height;
// store relative (given in percent) height
if (typeof height == "string" && height.indexOf("%")) {
c.rowFit.relHeight = parseInt(height);
} else { // set absolute height
c.setHeight(c.height);
//c.rowFit.hasAbsHeight = true;
c.rowFit.hasAbsHeight = !Boolean(c.split);
}
}
//if(c.split) c.rowFit.hasAbsHeight = false;
c.isResizable = c.isResizable || Boolean(c.split) || !c.rowFit.hasAbsHeight;
},

// private
onLayout: function(ct, target) {

Ext.ux.layout.RowFitLayout.superclass.onLayout.call(this, ct, target);

if (this.container.collapsed || !ct.items || !ct.items.length) {
return;
}

// first loop: determine how many elements with relative
// height are there,
// sums of absolute and relative heights etc.
var absHeightSum = 0,
// sum of elements' absolute heights
relHeightSum = 0,
// sum of all percent heights given in
// children configs
relHeightRatio = 1,
// "scale" ratio used in case sum <>
// 100%
noHeightCount = 0,
// number of elements with no height
// given
relHeightElements = []; // array of elements with 'relative'
// height for the second loop

var targetSize = target.getStyleSize();

for (var i = 0,
n = ct.items.length; i < n; i++) {
var c = ct.items.itemAt(i);

if (!c.isVisible()) {
continue;
}

// collapsed panel is treated as an element with
// absolute height
if (c.collapsed) {
var h = c.getFrameHeight();
absHeightSum += h;
c.setSize({
width: targetSize.width,
height: h
});

} else if (c.rowFit.hasAbsHeight) { // element that has
// an absolute
// height
absHeightSum += c.height;
c.setSize({
width: targetSize.width,
height: c.height
});

} else { // 'relative-heighted'
if (!c.rowFit.relHeight) { // element with no
// height given
//noHeightCount++;
absHeightSum += c.getFrameHeight();
c.setSize({
width: targetSize.width,
height: c.height
});
} else {
relHeightSum += c.rowFit.relHeight;
relHeightElements.push(c);
}

}
}

// if sum of relative heights <> 100% (e.g. error in config
// or consequence
// of collapsing/removing panels), scale 'em so it becomes
// 100%
if (noHeightCount == 0 && relHeightSum != 100) {
relHeightRatio = 100 / relHeightSum;
}

var freeHeight = target.getStyleSize().height - absHeightSum,
// "unallocated" height we have
absHeightLeft = freeHeight; // track how much free space we
// have

while (relHeightElements.length) {
var c = relHeightElements.shift(),
// element we're
// working with
relH = c.rowFit.relHeight * relHeightRatio,
// height of
// this
// element
// in
// percent
absH = 0; // height in pixels

// no height in config
if (!relH) {
relH = (100 - relHeightSum) / noHeightCount;
}

// last element takes all remaining space
if (!relHeightElements.length) {
absH = absHeightLeft;
} else {
absH = Math.round(freeHeight * relH / 100);
}

// anyway, height can't be negative
if (absH < 0) {
absH = 0;
}

c.rowFit.calcAbsHeight = absH;
c.rowFit.calcRelHeight = relH;
c.setSize({
width: targetSize.width,
height: absH
});

absHeightLeft -= absH;
}

for (var i = 0,
n = ct.items.length; i < n; i++) {
var c = ct.items.itemAt(i);
if (c.isSlider && c.el2resize) {
// this.checkRelHeight(c);
var split = new Ext.SplitBar(c.el, c.el2resize.el, Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
split.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));
c.el2resize.sliderId = c.getId();
c.el2resize = false;
}
}

if (!this.rendered) { // keep watching for changes of
// items
ct.on('add', this.ctAddItem, this);
ct.on('remove', this.ctDelItem, this);
this.rendered = true;
}
},
// private - called from Ext.Container
setContainer: function(ct) {
Ext.ux.layout.RowFitLayout.superclass.setContainer.call(this, ct);
this._addSliders(ct);
},

// private
_addSliders: function(ct) {
var sh = ct.splitHeight || this.splitHeight;
var skip1 = true;
var n = ct.items.length;
for (var i = n - 1; i >= 0; i--) {
var c = ct.items.itemAt(i);

this.checkRelHeight(c);
if (c.isResizable) { // !c.rowFit.hasAbsHeight) {
if (skip1) {
skip1 = false;
continue;
}

if (c.split) {
var slider = new Ext.Panel({
height: sh,
isSlider: true
});
slider.el2resize = c;
slider.addClass('x-splitbar-y');
ct.insert(i + 1, slider);
}
}
}
},

/**
* Add event listener for container children
* @private
*/
itemListener: function(item) {
item.ownerCt.doLayout();
},
_item_show: function(comp) {
if (!comp.isSlider && comp.sliderId) {
var sl = comp.ownerCt.findById(comp.sliderId);
if (!sl.isVisible()) {
sl.show();
return;
}
}
comp.ownerCt.doLayout();
},
_item_hide: function(comp) {
if (!comp.isSlider && comp.sliderId) {
var sl = comp.ownerCt.findById(comp.sliderId);
if (sl.isVisible()) {
sl.hide();
return;
}
}
comp.ownerCt.doLayout();
},
_item_expand: function(comp) {
this._item_show(comp);
},
_item_collapse: function(comp) {
this._item_hide(comp);
},

/**
* Event listener for the container (on add, remove)
* @private
*/
ctAddItem: function(ct, comp, idx) {
// TODO: ev. add slider & splitbar
ct.doLayout();
},
ctDelItem: function(ct, comp) {
// TODO: ev. remove slider & splitbar
ct.doLayout();
}

});

// Split adapter
if (Ext.SplitBar.BasicLayoutAdapter) {

/**
* @param {Ext.SplitBar} splitbar to which adapter is applied.
* If supplied, will set correct minSize and maxSize.
*/
Ext.ux.layout.RowFitLayout.SplitAdapter = function(splitbar) {
if (splitbar && splitbar.el.dom.nextSibling) {
var next = Ext.getCmp(splitbar.el.dom.nextSibling.id),
resized = Ext.getCmp(splitbar.resizingEl.id);

// skip abs-height non-resizable components
while (next && (next.collapsed || !next.isVisible() || !next.isResizable)) {
next = Ext.getCmp(next.el.dom.nextSibling.id);
}

if (next) {
//splitbar.maxSize = (resized.height || resized.rowFit.calcAbsHeight) +
splitbar.maxSize = (resized.rowFit.hasAbsHeight ? resized.rowFit.calcAbsHeight: resized.getSize().height) + next.getInnerHeight() - 1; // seems can't set height=0 in IE, "1" works fine
}
splitbar.minSize = resized.getFrameHeight() + 1;
}
};

Ext.extend(Ext.ux.layout.RowFitLayout.SplitAdapter, Ext.SplitBar.BasicLayoutAdapter, {

setElementSize: function(splitbar, newSize, onComplete) {
var resized = Ext.getCmp(splitbar.resizingEl.id);

// can't resize absent, collapsed or hidden panel
if (!resized || resized.collapsed || !resized.isVisible()) {
return;
}

// resizingEl has absolute height: just change it
if (resized.rowFit.hasAbsHeight) {
resized.setHeight(newSize);
}
// resizingEl has relative height: affects next sibling
else {
if (splitbar.el.dom.nextSibling) {
var nextSibling = Ext.getCmp(splitbar.el.dom.nextSibling.id);
// skip abs-height non-resizable components
while (nextSibling && (nextSibling.collapsed || !nextSibling.isVisible() || !nextSibling.isResizable)) {
nextSibling = Ext.getCmp(nextSibling.el.dom.nextSibling.id);
}

var deltaAbsHeight = newSize - resized.rowFit.calcAbsHeight,
// pixels
nsRf = nextSibling.rowFit,
// shortcut
rzRf = resized.rowFit,
// pixels in a percent
pctPxRatio = rzRf.calcRelHeight / rzRf.calcAbsHeight,
deltaRelHeight = pctPxRatio * deltaAbsHeight; // change in height in percent

rzRf.relHeight = rzRf.calcRelHeight + deltaRelHeight;

if (nsRf.hasAbsHeight) {
var newHeight = nextSibling.height - deltaAbsHeight;
nextSibling.height = newHeight;
nextSibling.setHeight(newHeight);
} else {
nsRf.relHeight = nsRf.calcRelHeight - deltaRelHeight;
}
}
}
// recalculate heights
resized.ownerCt.doLayout();
} // of setElementSize

}); // of SplitAdapter
}

Ext.Container.LAYOUTS['row-fit'] = Ext.ux.layout.RowFitLayout;

rmesser
3 Sep 2008, 8:48 AM
Thanks for posting the updated version, that is very helpful. (Really this extension should probably go into the core Ext code, a row layout is just as important as the column layout which is in Ext core. In fact my 2 cents is that arranging things by rows is more valuable than by column.)

Anyway, the only thing I noticed is that specifying a width doesn't seem to work. So if I have this as my items:


items: [
{
title: 'panel 1',
height: '50%',
},
{
title: 'panel 2',
height: '50%',
width: '50%'
}
]


then both panel 1 and panel 2 size at 100% width. Does anyone know if there is some other config option for width or am I missing something? I also tried absolute widths and that didn't work either. Thanks.

galdaka
3 Sep 2008, 9:13 AM
Hi,

If you attach a live example in a ZIP file I upload it into www.jadacosta.es (http://www.jadacosta.es) for test pourposes.


Thanks in advance,

Juvs
5 Sep 2008, 6:11 PM
Hi, there's a bug when you set in a panel the frame attribute in true, I guess is something related with the background and borders and the extension don't calculate them. This happen when you collapsed any panel and the last panel doesn't resize to fit the window.

Also, I try this extension on Ext 2.2 using collapsible panels and something odd appends with the panel.

Here's my sample code:


var viewport = new Ext.Viewport({
layout : "row-fit",
id : "main_layout",
items : [{
xtype : "form",
title : "Form",
height : 100,
frame : true,
collapsible : true,
collapsed: true,
items : [{
xtype : "fieldset",
title : "Legend",
autoHeight : true,
items : [{
xtype : "combo",
fieldLabel : "Text",
name : "combovalue",
hiddenName : "combovalue"
}]
}]
}, {
xtype : "form",
title : "Form",
height : 100,
frame : true,
collapsible : true,
collapsed: true,
items : [{
xtype : "fieldset",
title : "Legend",
autoHeight : true,
items : [{
xtype : "combo",
fieldLabel : "Text",
name : "combovalue",
hiddenName : "combovalue"
}]
}]
}, {
xtype : "tabpanel",
id : "tab",
activeTab : 0,
height : "50%",
items : [{
title : "A"
}, {
title : "B"
}, {
title : "C"
}]
},
{ xtype: 'panel', height: 50, title: "I'm the panel with height in pixels too", html: "Nothing special, 50px panel", id: 'bottom' }
]
});

SamuraiJack1
12 Sep 2008, 5:48 AM
2kx

Great extension. Would you mind, if I'll publish it in repo (with you as an author of course), so it will not get lost in the forum?

SamuraiJack1
17 Sep 2008, 2:40 AM
I've fixed a bug, concerning sizing of elements with horizontal margins and published new version in repository:

http://extjs-ux.org/docs

For further updates please create patches against the repository last revision.

mdissel
17 Sep 2008, 4:54 AM
I've fixed a bug, concerning sizing of elements with horizontal margins and published new version in repository:

http://extjs-ux.org/docs
For further updates please create patches against the repository last revision.

Windows users can't do a checkout /update anymore, because there's a uppercase Layout directory en lowercase layout directory...

SamuraiJack1
17 Sep 2008, 5:27 AM
Thanks for pointing - I've republished Carousel under Ext.ux.layout namespace

Documentation will be updated maximum in 2 hours.

bluefox
5 Oct 2008, 7:52 AM
Has anyone used this extension with 2.2? I have a very simple layout and it presents a few problems:
1. I'm not able to resize the panels
2. When collapsing the panels, I'm not able to uncollapse them again.



Ext.onReady(function(){

var extra = '<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>...';

new Ext.Viewport({
layout: 'row-fit',
id: 'container',
items: [
{ xtype: 'panel', title: "I'll take some too...", html: "...if you don't mind. I don't have a <tt>height</tt> in the config.<br>Btw, you can resize me!"+extra, id: 'panel3', autoScroll:true, collapsible: true },
{ xtype: 'panel', id: 'slider', height: 5 },
{ xtype: 'panel', title: "Let me settle too",
html: "Since there are two of us without <tt>height</tt> given, each will take 1/2 of the unallocated space (which is 50%), that's why my height initially is 25%."+extra, autoScroll: true, collapsible: true }
]
});

var split = new Ext.SplitBar("slider", "panel3", Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
split.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));

});
Thoughts?

SamuraiJack1
6 Oct 2008, 8:14 AM
Has anyone used this extension with 2.2? I have a very simple layout and it presents a few problems:
1. I'm not able to resize the panels
2. When collapsing the panels, I'm not able to uncollapse them again.



Ext.onReady(function(){

var extra = '<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>...';

new Ext.Viewport({
layout: 'row-fit',
id: 'container',
items: [
{ xtype: 'panel', title: "I'll take some too...", html: "...if you don't mind. I don't have a <tt>height</tt> in the config.<br>Btw, you can resize me!"+extra, id: 'panel3', autoScroll:true, collapsible: true },
{ xtype: 'panel', id: 'slider', height: 5 },
{ xtype: 'panel', title: "Let me settle too",
html: "Since there are two of us without <tt>height</tt> given, each will take 1/2 of the unallocated space (which is 50%), that's why my height initially is 25%."+extra, autoScroll: true, collapsible: true }
]
});

var split = new Ext.SplitBar("slider", "panel3", Ext.SplitBar.VERTICAL, Ext.SplitBar.TOP);
split.setAdapter(new Ext.ux.layout.RowFitLayout.SplitAdapter(split));

});
Thoughts?

You can try to patch it - it will be a good excursion to Ext internals for you :)

mviens
7 Oct 2008, 4:18 PM
bluefox,

I am having the same issue as you with not being able to expand them panels once they have been collapsed. I can resize mine, but something is "weird" with the splitter. Hopefully, someone more familar with this code can reolve the issue with Ext 2.2.

Mike V.

dmcclean
21 Oct 2008, 2:01 PM
I seem the same 2.2 resize issue with IE, but not firefox. Shame, it was
really good with 2.1. I will have to remove it from my app if it is not resolved.

SamuraiJack1
22 Oct 2008, 3:25 AM
I've made some fixes to this ux recently and code clean-up - you can try with the latest version from repository:
http://extjs-ux.org/docs/?class=Ext.ux.layout.RowFitLayout

If the bug still persists please upload the test case to ftp://sandbox.extjs-ux.org - I'll try to fix it.

SamuraiJack1
31 Oct 2008, 4:37 AM
Fixed bug with collapsing/expanding childs.

Latest version in repository:
http://extjs-ux.org/docs/?class=Ext.ux.layout.RowFitLayout

dmcclean
4 Nov 2008, 6:59 AM
Thank you! It works great now.

Regards,
Don McClean

tarini
19 Nov 2008, 4:00 AM
Hi, thanks for your extension...

I'm using Ext.ux.layout.RowFitLayout.SplitAdapter but it doesn't looks like Ext.SplitBar (used in a border layout panel).
Using firebug I discovered that:

Ext.SplitBar is a simple DIV that is sibling of its resizable DIVs and it styles itself using x-layout-split css class
Ext.ux.layout.RowFitLayout.SplitAdapter is composed by 3 DIVs nested each other and styles itself using x-panel css class


Is there a reason for all??

thanks

Iveco
17 Dec 2008, 6:58 AM
Just came in handy, thank you very much for this extension!

Exactly what I was looking for now, as always great community :)

Regards

azbok
26 Dec 2008, 7:11 PM
This row layout seems great so far (once I figured the first panel collapse problem)! I'm using Ext 2.2.

Initial go at it:


new Ext.Panel({
id : 'panel-id',
title : 'This Is The Title',
layout : 'row-fit',
items : [
{ xtype: 'panel', height: 100, title: 'Title 1', html: 'height = 100px' },
{ xtype: 'panel', height: 150, title: 'Title 2', html: 'height = 150px' }
]
});
Solution:


new Ext.Panel({
id : 'this-is-the-id',
title : 'This Is The Title',
layout : 'row-fit',
items : [
{ xtype: 'panel', id: 'NEED-ID1', height: 100, title: 'Title 1', html: 'height = 100px' },
{ xtype: 'panel', id: 'NEED-ID2', height: 150, title: 'Title 2', html: 'height = 150px' }
]
});
The solution is to use an id for each panel. I have a feeling somewhere in the component construction phase, if there's no id, the collapsed flag gets set to true!

This is actually the 2nd time I've ran into this problem, it's not specific to this row layout module, I think it's a general Ext 2.2 thing.

If in doubt, put in an ID!!

Eric24
28 Dec 2008, 7:50 AM
Great extension!

From my perspective, it seems like this should just be the standard "fit" layout. With a single item and no height config, it does the same thing as "fit" does now, so it can be dropped in without affecting existing "fit" implementations. Adding additional items and/or height configs seamlessly extends basic "fit" functionality to "row-fit" functionality.

--Eric

cmschick
5 Mar 2009, 7:19 PM
Is anyone else seeing this issue. In both IE7 and FF 3.0.6 when I resize with the spitter a dark gray DIV shows up that is the size of the "element to drag". Its very hokey and I was hoping someone had already addressed this.

At any rate I'll be looking into to it to see what I can find.

sircyaj
14 Apr 2009, 4:32 AM
Very nice! :) Exactly what I wanted. Thanks!

jnadler
13 May 2009, 11:26 AM
I had some significant problems in Safari with the latest version of this component (I had been using an older version).

I have a TabPanel with dynamically added tabs that all contain a row-fit layout. When adding a new tab, all the other tabs content disappears. The tabs are still there, they are just visually empty (Safari only, works fine in FF).

I resolved this problem by reverting just the onLayout() method to the version of that method from an older version of this extension.

SamuraiJack1
13 May 2009, 11:36 AM
Can you post a test case?

jnadler
13 May 2009, 1:12 PM
Extracting a test case from my massive app would be a chore - instead I'd like to isolate the problem a bit more and maybe I can just suggest a fix.

Great component by the way. This is way more useful than some of the things that are actually part of ExtJS in my opinion. They should include it in the framework.

SamuraiJack1
13 May 2009, 2:59 PM
Very useful layout indeed, should be polished as much as possible.

jnadler
13 May 2009, 3:43 PM
Here's what I found, making this change in onLayout resolved my problems and it seems to be working with both FF and Safari as expected:


c.setSize({
width: targetSize.width, // - c.getEl().getMargins('lr'), <-- remove the subtraction
height: absH
});

absHeightLeft -= absH;
}
I still have a minor issue related to the one the guy above has where he gets a big gray box - in some cases a component in my rowfitlayout grows a few pixels each time the screen is resized. If/when I fix that one I'll post another fix here.

SamuraiJack1
13 May 2009, 10:53 PM
Hm.. This subtraction makes the layout aware of items margins - I'd not remove it. Are you sure this is the cause? Do the elements in your tabs have horizontal margins?

jnadler
14 May 2009, 7:56 AM
In my testing this change was critical to getting Safari working correctly. I had a bug where row-fit panels were not expanding/contracting width when a border layout slider was moved, this change fixed that problem. I had the big problem where tab content disappeared, this change fixed that as well.

I don't use many margins in my app and I understand that I may have introduced another bug here for users that do. A better solution might be to make this calculation conditional on Ext.isSafari

flylaputa
9 Jun 2009, 1:56 AM
Hi,

I like this extension and have been using it for some time. It is also compatible with ExtJS 3.0. I am wondering whether it will migrate to use the vbox layout that is available in ExtJS 3.0?

brookd
15 Jul 2009, 7:09 AM
Can rowFit be replaced with the new hBox layout in Ext3.0?

SamuraiJack1
15 Jul 2009, 7:14 AM
May be. The difference may be in handling "height: auto" on the container.

From my experience RowFit works well with it, have not tested hBox in this regard yet.

brookd
15 Jul 2009, 7:30 AM
Thanks for the reply, I just want to keep file size down so I will see if I can remove the rowFitLayout...

tarini
1 Sep 2009, 4:29 AM
Has anyone tried to use this layout with Element mask ?

I have a RowFitLayout Panel with two tabPanels inside it (50% each)...

When I create a mask over tabPanel el attributes (that should be the main HTML element), it - the mask - will overflow and cover also the other tabPanel...

I attach a screenshot of my problem

cginzel
22 Oct 2009, 12:23 PM
This layout saved me some grief on a west panel with panel above and a treepanel below. However, the height of the treepanel that was to take up the remaining space was cheated by what appears the treepanel's title and so I had to make the following change:


frameH = c.getFrameHeight ? c.getFrameHeight() : 0;

c.setSize({
width: targetSize.width - c.getEl().getMargins('lr'),
height: absH + frameH
});

absHeightLeft -= absH;

vidj
6 Mar 2012, 11:25 PM
Hi everyone!

Has someone a actual working version of this extension? The repo doesn't seem to exist anymore... Would be cool if some of you could post the latest availible version here or some repo where i can get this extension.

thx in advance

vidj