PDA

View Full Version : [2.2] Combo's dropdown list offset by negative-margin when inside floated container



NightAvatar
20 Nov 2008, 5:42 AM
Description
When using ComboBox in floated container (i.e. placing in layout that uses floats) the dropdown list is offset by negative margin in FF and Safari. (See attached examples)

What steps will reproduce the problem?
From Combos example here (http://extjs.com/deploy/dev/examples/form/combos.html), remove all but first ComboBox from HTML
Place combo's INPUT field inside DIV with style="width:50%;float:right;clear:both" (blue code in example below)
Remove excess code - everything below first combobox
Load page in Firefox (2 or 3) or Safari (3)
Click on combobox-arrow to activate dropdown list
Example code for combos.html


<div style="width:50%;float:right;clear:both">
<input type="text" id="local-states" size="20" />
</div>

Result
Dropdown list is offset by negative margin and extra arrow-button on left side of input field. (See first attachment (http://extjs.com/forum/attachment.php?attachmentid=10609&d=1227186806).)

Subsequent clicks will render the dropdown correct. (But extra button still shows.)

Removing all code from combos.js EXCEPT the bit that applies to the one combo on the page (see example code below) will remove the extra button, but the negative-margin offset still occurs! (See second attached image for Firefox (http://extjs.com/forum/attachment.php?attachmentid=10610&d=1227186813), third for Safari (http://extjs.com/forum/attachment.php?attachmentid=10614&d=1227188120).)

Example code for combos.js


Ext.onReady(function(){
// simple array store
var store = new Ext.data.SimpleStore({
fields: ['abbr', 'state', 'nick'],
data : Ext.exampledata.states // from states.js
});
var combo = new Ext.form.ComboBox({
store: store,
displayField:'state',
typeAhead: true,
mode: 'local',
forceSelection: true,
triggerAction: 'all',
emptyText:'Select a state...',
selectOnFocus:true,
applyTo: 'local-states'
});
});
I have searched for hours for a fix to this problem but can't see it listed. I am coming to my wits end! :((

Thanks in advance for a great tool and for the excellent support and help! =D>

NightAvatar
20 Nov 2008, 6:57 AM
Sorry, I forgot to link to the ComboBox example (http://extjs.com/deploy/dev/examples/form/combos.html) in step 1, above.

Fixed...

jsakalos
20 Nov 2008, 10:01 AM
It seems that list positioning logic gets fooled by something. First guess would be width:50%. Anyway, trying to lay out controls/components in an existing html markup is not the preferred method in Ext and it may often lead to some problems. Better would be to use layouts to position/size components.

NightAvatar
20 Nov 2008, 10:14 AM
Thanks for your reply.

It's the float, not the 50%. Even if I set it to 90% or any % the same problem occurs.

I am developing for a BIG corporation that has an established styleguide including templates for their code - using floats. It's not exactly a small job to recode the entire thing to suit a combobox (the only element from ext which I will use on their site).

This must be consided a bug?

Or what would you suggest? You can't be serious about me recoding their entire site layout to suit the combobox?

mystix
20 Nov 2008, 10:22 AM
i wouldn't consider it a bug if external css messes up a Component's visual display.

that said, you can still fit the combo into your current environment with the following override


Ext.override(Ext.form.ComboBox, {
listOffsets: null,

expand : function(){
if(this.isExpanded() || !this.hasFocus){
return;
}
this.list.alignTo(this.wrap, this.listAlign, this.listOffsets);
this.list.show();
this.innerList.setOverflow('auto'); // necessary for FF 2.0/Mac
Ext.getDoc().on('mousewheel', this.collapseIf, this);
Ext.getDoc().on('mousedown', this.collapseIf, this);
this.fireEvent('expand', this);
}
});

following which you should be able to create combos for your environment as such


new Ext.form.ComboBox({
listOffsets: [Ext.isIE? 0 : 10, 0] // apply a 10 pixel x-axis offset to the combo list for non-IE browsers -- adjust as necessary

// other combo configs
});

you may need to add additional logic where necessary since you also mentioned subsequent clicks solve the problem.

[edit]
just saw the additional arrow button thingy in your first above -- you'll need to poke around in firebug to see exactly what styles are being applied to the combobox in your environment, and counter-adjust with other css where necessary. this is the recommended method for dealing with the combo list issue too.

NightAvatar
20 Nov 2008, 10:36 AM
Thanks Mystix. :)

I consider it a bug when I can't implement a component into a pre-existing layout.

The external stylesheet does nothing to the component itself. It only floats a container which contains the component (in my case several layers above).

Floats are a very common tool for styling layouts.

Will your fix only affect FF and Safari? (Possibly Opera?) I don't want to change the visual for IE. That browser works fine for some reason.

I know the stylesheet for the environment I use very well and nothing in it is affecting the arrow button. And as I mention, it only bugs when the js file defines combos that are not present on the page. IS that a requirement? (Does each page using a combo require it's own combo js? I wanted to have one that included all of them, even though not all are used on all pages.)

I appreciate the help. Sorry if I come off as ungrateful. I just don't want this to be "brushed off" as an external css issue when it shouldn't be.

Cheers,
Rich

jsakalos
20 Nov 2008, 11:54 AM
I've made the following test that runs flawlessly:


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="./ext/resources/css/ext-all.css">
<script type="text/javascript" src="./ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="./ext/ext-all-debug.js"></script>
<script type="text/javascript" src="./application.js"></script>
<title id="page-title">Combo</title>
<script type="text/javascript">
Ext.onReady(function() {
var combo = new Ext.form.ComboBox({
triggerAction:'all'
,store:[1,2,3,4,5,6,7,8,9,10]
,renderTo:'combo-ct'
});
});
</script>
</head>
<body>
<div id="combo-ct" style="float:right;margin:10px"></div>
</body>
</html>

NightAvatar
20 Nov 2008, 11:20 PM
I guess we agree that it is caused by a combination of FLOAT and %.

While I (and probably most designers) prefer fixed grid layouts, this company requires a liquid grid. Thus the % - and shouldn't it be supported?

Thanks for taking the time to respond. I really appreciate all the help.

Condor
21 Nov 2008, 1:35 AM
OK, I finally figured out what happens here.

When the comobobox list is initially created it has height:auto. In this example this means that the list is bigger than the screen and the first time it is shown it will cause a vertical scrollbar on the body, shifting the combobox wrap to the left (with scrollbar width * 50% = 9px).
Next, the combobox list is given its correct height, but in the process it is realigned to the shifted combobox wrap. Setting the height removes the scrollbar which restores the combobox wrap position, leaving a misaligned combobox list.

You can fix this by initially creating the combobox list with height:0.

Ext.override(Ext.form.ComboBox, {
initList : function(){
if(!this.list){
var cls = 'x-combo-list';
this.list = new Ext.Layer({
shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
});
var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
this.list.setSize(lw, 0);
this.list.swallowEvent('mousewheel');
this.assetHeight = 0;
if(this.title){
this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
this.assetHeight += this.header.getHeight();
}
this.innerList = this.list.createChild({cls:cls+'-inner'});
this.innerList.on('mouseover', this.onViewOver, this);
this.innerList.on('mousemove', this.onViewMove, this);
this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
if(this.pageSize){
this.footer = this.list.createChild({cls:cls+'-ft'});
this.pageTb = new Ext.PagingToolbar({
store:this.store,
pageSize: this.pageSize,
renderTo:this.footer
});
this.assetHeight += this.footer.getHeight();
}
if(!this.tpl){
this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
}
this.view = new Ext.DataView({
applyTo: this.innerList,
tpl: this.tpl,
singleSelect: true,
selectedClass: this.selectedClass,
itemSelector: this.itemSelector || '.' + cls + '-item'
});
this.view.on('click', this.onViewClick, this);
this.bindStore(this.store, true);
if(this.resizable){
this.resizer = new Ext.Resizable(this.list, {
pinned:true, handles:'se'
});
this.resizer.on('resize', function(r, w, h){
this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
this.listWidth = w;
this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
this.restrictHeight();
}, this);
this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
}
}
}
});

NightAvatar
21 Nov 2008, 1:44 AM
That's it! Condor, YOU DA MAN!

I just noticed that it only happens when there's a scrollbar in the combo. I didn't make the connection. Thanks!

I just implemented your code and it works perfect in FF and Safari. You can now set this to [SOLVED] and I recommend/hope this will be the default settings in next release.

Cheers! :)

mystix
21 Nov 2008, 2:09 AM
That's it! Condor, YOU DA MAN!

I just noticed that it only happens when there's a scrollbar in the combo. I didn't make the connection. Thanks!

I just implemented your code and it works perfect in FF and Safari. You can now set this to [SOLVED] and I recommend/hope this will be the default settings in next release.

Cheers! :)

woot. glad you found the solution. do i still need to reply to your p.m.? :-?

Animal
21 Nov 2008, 2:15 AM
Keep an eye on the SVN revisions to check the fix makes it in.

NightAvatar
21 Nov 2008, 2:21 AM
do i still need to reply to your p.m.? :-?
Lol, nah. Condor posted that after I sent it. So I guess I was a bit too quick. ;)

Thanks for looking into it though Mystix! :)

NightAvatar
16 Jan 2009, 6:44 AM
This bug appears again when I ditch ext-all and use the build-your-own ext-js instead. Do you know if I need any specific file for it to work?

Condor
16 Jan 2009, 6:57 AM
Are you applying the patch after including the build ext.js file?

ps. If you really want small files you should use the SVN code, make any bugfixes in that source an build your ext.js files from that (you can even include your own .js files in the process). And don't forget to use the YUI Compressor (it gets a much higher compression ratio than the build in JSMin).

NightAvatar
16 Jan 2009, 9:11 AM
Are you applying the patch after including the build ext.js file?
Yes, I am. Exactly as you describe in post #9. Perhaps it's unnecessary now?

I would love to use the SVN code but I'm afraid I would need a tutorial on how to set it up. Same goes for the YUI Compressor. I am a HTML and CSS guy (gui, design) not so much this advanced javascript and development stuff. I try my best but it sometimes (often) goes way over my head.

Condor
16 Jan 2009, 11:05 AM
Have you read the tutorial (http://extjs.com/learn/Tutorial:Building_Ext_From_Source)?

ps. And for the YUI Compressor read this (http://www.julienlecomte.net/yuicompressor/README) (can be used on .js and .css).

NightAvatar
10 Mar 2009, 5:23 AM
I have spent the last 4 hours trying to create a ext.js from source that will support the datePicker and combos. So far, nothing is able to work for me.

When I use the "build-your-own (http://extjs.com/products/extjs/build/)" tool, both widgets work on my page, but this "offset" bug (that you fixed in this thread) persists!

One problem I have is that several of the files that are supposedly "required" (according to the build-your-own" page) are missing from SVN. I'm not sure what they are replaced with!

How on Earth can I knkow which files I need for the combos and DatePicker? Is there some kind of magic oracle I must visit?

Build-your-own works for me when I select the following:

Ext Core
DomHelper.js Template.js DomQuery.js Observable.js EventManager.js Element.js Fx.js CompositeElement.js UpdateManager.js DelayedTask.js

Core Components
Component.js BoxComponent.js ComponentMgr.js
MixedCollection.js

+ Layers
Layer.js Shadow.js

Data View
DataView.js
Component.js BoxComponent.js ComponentMgr.js XTemplate.js

Resizable
Resizable.js

Date Picker Widget (DateMenu)
DateMenu.js DatePicker.js DateItem.js
Date.js Layer.js Shadow.js MenuMgr.js Menu.js BaseItem.js Adapter.js Component.js KeyNav.js ClickRepeater.js

Slider
Slider.js
DragTracker.js

Data - Core
Connection.js DataField.js DataProxy.js DataReader.js Record.js SortTypes.js Store.js HttpProxy.js ScriptTagProxy.js MemoryProxy.js
MixedCollection.js

+ Multi-store SupportStoreMgr.js

Data - Simple Store
SimpleStore.js
JsonReader.js ArrayReader.js Connection.js DataField.js DataReader.js Record.js SortTypes.js Store.js MixedCollection.js

Form - ComboBox Widget
Combo.jsComponent.js BoxComponent.js ComponentMgr.js Field.js TextField.js TriggerField.js View.js KeyNav.js

Form - Date Field
DateField.jsTriggerField.js Field.js TextField.js Component.js BoxComponent.js ComponentMgr.js DateMenu.js DatePicker.js DateItem.js Date.js Layer.js Shadow.js MenuMgr.js Menu.js BaseItem.js Adapter.js KeyNav.js ClickRepeater.js


* Represents dependencies

Can I please get some help here?

What files do I need from SVN (using JS Builder) and why is the offset bug still occuring (when I include the hack you described above)?

I have even tried using EVERYTHING (checking ALL files to include in build). That doesn't work either. :-/

kapil gupta
29 Oct 2010, 5:35 AM
But in firefox and Windows 7 OS , its still opens towards left.you can see in attachement. there is any permanent solution for this bug in EXTJS. Attachment 23070 (http://www.sencha.com/forum/attachment.php?attachmentid=23070)