PDA

View Full Version : Minimum width and height for Viewport



Dipish
15 Dec 2011, 6:41 AM
For Ext 3 I used this override to allow setting minimum width and/or height to Viewport (actually any component with Border layout):
http://stanislav-dev-blog.blogspot.com/2009/10/setting-min-width-and-min-height-for.html

(http://stanislav-dev-blog.blogspot.com/2009/10/setting-min-width-and-min-height-for.html)This way, if the window size is smaller than applied constraints, scrollbars will appear.
Now it doesn't work anymore and I can't figure out how to tweak the new layout system to support the desired behavior.

I would appreciate if somebody shared the solution, I think it's a pretty common issue and don't understand why Ext devs keep not including such config option out-of-the box.

Dipish
15 Dec 2011, 8:25 AM
Looks like I've finally found the solution. Probably not pretty but does the thing.
First, we use this override for the Viewport class:

Ext.override(Ext.Viewport, { setSize : function(width, height) {
var el = this.el;


if(width < this.minWidth) {
width = this.minWidth;
el.setStyle('width', width + 'px');
el.up('').setStyle('overflow', 'auto')
} else {
el.setStyle('width', '');
}


if(height < this.minHeight) {
height = this.minHeight;
el.setStyle('height', height + 'px');
el.up('').setStyle('overflow', 'auto');
} else {
el.setStyle('height', '');
}


this.callOverridden(arguments);
}
});

As in Ext 4 the Border layout uses other layouts internally, one should introduce the minWidth/minHeight support into every layout class (I wish there was a better way of doing it but haven't found it so far). Here is an example of override for the Fit layout:

Ext.override(Ext.layout.FitLayout, { onLayout : function() {
var me = this,
size,
item,
margins;
me.callParent();


if (me.owner.items.length) {
item = me.owner.items.get(0);
margins = item.margins || me.defaultMargins;
size = me.getLayoutTargetSize();


if(this.minWidth) {
size.width = Math.max(size.width, this.minWidth);
}
if(this.minHeight) {
size.height = Math.max(size.height, this.minHeight);
}


size.width -= margins.width;
size.height -= margins.height;
me.setItemBox(item, size);


// If any margins were configure either through the margins config, or in the CSS style,
// Then positioning will be used.
if (margins.left || margins.top) {
item.setPosition(margins.left, margins.top);
}
}
}
});

Now we can specify minimum width and height to our viewport like that:

var vp = new Ext.Viewport({ layout: {
type: 'border',
minWidth: 600,
minHeight: 400
},
minWidth: 600,
minHeight: 400,
...


Note that the implementation requires specifying minWidth and minHeight twice: for the viewport Component itself and for its layout.

Hope that helps someone else!
Critics and improvements are highly appreciated.

gszczepanczyk
21 Aug 2012, 1:58 AM
Hi!

It works ootb now in extjs4: http://docs.sencha.com/ext-js/4-1/#!/api/Ext.container.Viewport-cfg-minWidth

Dipish
14 Jan 2013, 6:11 AM
It does indeed! Thanks for noticing.

However you should add overflow: auto; to viewport element if you want the scrollbars to appear. Here's a simple override that sets the style only when necessary (to avoid displaying scrollbars in some browsers when there is enough space):


Ext.override(Ext.Viewport, { setSize: function(width, height) {
if(this.rendered) {
var el = this.el,
overflowStyle = 'hidden';


if(width < this.minWidth) {
overflowStyle = 'auto';
}


if(height < this.minHeight) {
overflowStyle = 'auto';
}


el.parent().setStyle('overflow', overflowStyle);
}


this.callOverridden(arguments);
}
});

Tested on latest Chrome, Opera & Firefox.

Perceptive
13 Feb 2013, 9:42 AM
In ExtJS 4.2.0-beta2 you need to modify the code supplied by Dipish slightly, instead of calling setStyle on the el.parent(), just call it on el.



Ext.override(Ext.container.Viewport, {
setSize: function(width, height) {
if(this.rendered) {
var el = this.el,
overflowStyle = 'hidden';

if(width < this.minWidth) {
overflowStyle = 'auto';
}

if(height < this.minHeight) {
overflowStyle = 'auto';
}

el.setStyle('overflow', overflowStyle);
}
this.callOverridden(arguments);
}
});