PDA

View Full Version : [CLOSED] Ext.Element -> getWidth + fix



tobiu
13 Jul 2010, 5:42 AM
hi team,

this might be the biggest bugfix i posted so far, since it will resolve quite a bunch of issues.
in the past i had several problems with rendering hidden items and width calculations, most were tabbed forms with deferredRender: false.

+ i had comboBoxes that were 17px (the width of the trigger) to wide
+ errorIcons displayed over the fieldLabel
+ sliders with the thumb always at zero

and many more issues. this all went down to the point, that the width-calculations returned 0 if rendered hidden. i used hideMode: offsets quite a lot because of this. the solution i found also works with the default display-mode.

so, here it is:



Ext.override(Ext.Element, {
getWidth : function(contentWidth){
var me = this,
dom = me.dom,
hidden = Ext.isIE && me.isStyle('display', 'none'),
w = Math.max(dom.offsetWidth || parseInt(dom.style.width, 10), hidden ? 0 : dom.clientWidth) || 0;

w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
return w < 0 ? 0 : w;
}
});


i had to write "Math" instead of "MATH", since i can not access the attribute with an override.

here is a small usecase, showing my sliderField usecase with normal hideMode:display.
tested in ff3.6, ie8 and chrome. the fix for getHeight should work the same way.



Ext.onReady(function(){

Ext.override(Ext.Element, {
getWidth : function(contentWidth){
var me = this,
dom = me.dom,
hidden = Ext.isIE && me.isStyle('display', 'none'),
w = Math.max(dom.offsetWidth || parseInt(dom.style.width, 10), hidden ? 0 : dom.clientWidth) || 0;

w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
return w < 0 ? 0 : w;
}
});

new Ext.form.FormPanel({
renderTo: document.body,
width:600,
height:250,
layout:'fit',
border:false,
labelWidth : 100,
items : [{
xtype: 'tabpanel',
activeTab: 0,
deferredRender: false,
layoutOnTabChange: true,
plain:true,
defaults:{autoScroll: true},
items:[{
title: 'Tab 1',
html: "My content was added during construction."
},{
title: 'Tab 2',
layout: 'form',
items: [{
fieldLabel: 'Sliderfield',
maxValue : 500,
minValue : 0,
value : 250,
width : 200,
xtype : 'sliderfield'
}]
}
]
}]
});
});



kind regards,
tobiu

Jamie Avins
13 Jul 2010, 11:34 AM
Its an interesting workaround for the problem but I don't think we can generalize it to the extent where it's included in Element.

tobiu
14 Jul 2010, 4:50 AM
hi jamie,

please don't underestimate the override, it fixes many other tickets as well.
for example the triggerField-issue of ticket 1110:
http://www.sencha.com/forum/showthread.php?103405


kind regards,
tobias

tobiu
14 Jul 2010, 7:32 AM
hi jamie,

i build a new version of the fix:



Ext.override(Ext.Element, {
getWidth : function(contentWidth){
var me = this,
dom = me.dom,
w = dom.offsetWidth|| 0;

w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");

if(w <= 0){
w = parseInt(dom.style.width, 10) || 0;

while(dom.parentNode){
if(dom.parentNode.style){
w += (parseInt(dom.parentNode.style.marginLeft, 10) || 0);
w += (parseInt(dom.parentNode.style.paddingLeft, 10) || 0);
}
dom = dom.parentNode;
}
}
return w;
}
});


i removed the max (clientWidth, offsetWidth) check and improved the new routine a bit more:
it checks all parentNodes for margins and paddings.

since this might increase the needed execution-time, it is only used when the width is 0.
otherwise it could replace the whole old mechanism.

the advantage of this version is:
you can use tabpanels with


,deferredRender : false
,layoutOnTabChange : false


and hideMode -> display. so, basically we don't need layoutOnTabchange anymore if the fix works as i think it does.

here an example:



Ext.onReady(function(){

Ext.override(Ext.Element, {
getWidth : function(contentWidth){
var me = this,
dom = me.dom,
w = dom.offsetWidth|| 0;

w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");

if(w <= 0){
w = parseInt(dom.style.width, 10) || 0;

while(dom.parentNode){
if(dom.parentNode.style){
w += (parseInt(dom.parentNode.style.marginLeft, 10) || 0);
w += (parseInt(dom.parentNode.style.paddingLeft, 10) || 0);
}
dom = dom.parentNode;
}
console.log(w);
}
return w;
}
});

var tabs = new Ext.FormPanel({
labelWidth : 75
,border : false
,items: {
xtype : 'tabpanel'
,activeTab : 0
,deferredRender : false
//,layoutOnTabChange : true
,id : 'tp'
,anchor : '100% 100%'
,style : 'margin-bottom:10px;'
,defaults:{
autoScroll : true
,bodyStyle :'padding:10px;'
}
,items:[{
title : 'Personal Details',
layout : 'form',
id : 'tab1'
,items: [{
anchor : '-20'
,autoHeight : true
,title : 'Customer'
,checkboxName : 'checkAnimation'
,checkboxToggle : true
,xtype : 'fieldset'
,defaults: {
anchor : '-22'
,width : 230
,msgTarget : 'side'
},
defaultType: 'textfield',
items :[{
fieldLabel: 'First Name',
allowBlank: false,
name: 'first',
id: 'focus1'
},{
fieldLabel: 'Last Name',
allowBlank: false,
name: 'last'
},{
fieldLabel: 'Company',
name: 'company',
value: 'Ext JS'
}, {
fieldLabel: 'Email',
name: 'email',
vtype:'email'
},{
fieldLabel: 'Business',
name: 'business'
},{
fieldLabel: 'Mobile',
name: 'mobile'
},{
fieldLabel: 'Fax',
name: 'fax'
}]
}]
},{
title : 'Phone Numbers'
,layout : 'form'
,id : 'tab2'
,defaults : {
width : 230
,anchor : '-22'
,msgTarget : 'side'
}
,defaultType: 'textfield',

items: [{
fieldLabel: 'Home',
allowBlank: false,
name: 'home',
value: '(888) 555-1212'
}, {
fieldLabel: 'Email',
allowBlank: false,
name: 'email',
vtype:'email'
},{
fieldLabel: 'Business',
name: 'business'
},{
fieldLabel: 'Mobile',
name: 'mobile'
},{
fieldLabel: 'Fax',
name: 'fax',
style:'margin-bottom:10px;'
}]
}]
}
});

var myWindow = new Ext.Window({
height : 400
,border : false
,layout : 'fit'
,title : 'a window'
,width : 400
,items : tabs
,buttons: [{
text: 'Step 1',
handler : function(){
Ext.getCmp('focus1').focus();
Ext.getCmp('tp').setActiveTab(1);
}
},{
text: 'Step 2',
handler : function(){
Ext.getCmp('tp').setActiveTab(0);
}
}]
});

myWindow.show();
});


try it out with and without the fix.


kind regards,
tobiu

Jamie Avins
14 Jul 2010, 9:25 AM
I understand the logic behind what you are doing, but the potential impact to existing applications doing this implementation is too large for us to include it.

steffenk
15 Jul 2010, 6:21 AM
Hi,

i tested the patch with a big application of mine, and it has no side effects, all is working as expected.

tobiu
20 Jul 2010, 8:10 AM
after further testing, i prefer



Ext.override(Ext.Element, {
getWidth : function(contentWidth){
var me = this,
dom = me.dom,
hidden = Ext.isIE && me.isStyle('display', 'none'),
w = Math.max(dom.offsetWidth || parseInt(dom.style.width, 10), hidden ? 0 : dom.clientWidth) || 0;

w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");

return w < 0 ? 0 : w;
}
});


again ;)


for details, just ask.

szalansun
8 Oct 2012, 9:38 PM
Ext.override(Ext.Element, { getWidth : function (contentWidth) {
var me = this, dom = me.dom, hidden = Ext.isIE && me.isStyle('display', 'none');
var outerWidth = me.getBorderWidth("lr") + me.getPadding("lr");
var styleWidth = parseInt(dom.style.width, 10) + outerWidth;
var w = Math.max(dom.offsetWidth || styleWidth, hidden ? 0 : dom.clientWidth) || 0;
w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");

return w < 0 ? 0 : w;
}
});