PDA

View Full Version : [DEFER] Combobox stops working after window is moved



stephen.friedrich
10 Jun 2010, 4:54 AM
Ext version tested:

Ext 3.2.1


Adapter used:

ext


css used:

only default ext-all.css


Browser versions tested against:

FF3.6.3 (firebug 1.5X.4 installed)


Operating System:

Win Vista 64bit


Description:

When a combo box is in a window and has a remote store, then it stops working when the window is moved while the combo box has focus.



Test Case:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<title>ExtJS Test</title>

<link rel="stylesheet" type="text/css" href="http://www.extjs.com/deploy/dev/resources/css/ext-all.css"/>

<script type="text/javascript" src="http://www.extjs.com/deploy/dev/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="http://www.extjs.com/deploy/dev/ext-all-debug.js"></script>
</head>

<body>
<div id="button"></div>
</body>

<script language="JavaScript">
Ext.onReady(function() {
Ext.QuickTips.init();

var ComboWindow = Ext.extend(Ext.Window, {
constructor: function(config) {
config = config || {};

var partNoStore = new Ext.data.JsonStore({

method: 'GET',
proxy: new Ext.data.HttpProxy({
url: null,
api: {
read: {url: 'part-nos.json', method: 'GET'}
}
}),
autoDestroy: true,
root: 'data',
fields: [ 'partNo' ]
});

var defaultConfig = {
modal: true,

// Why doesn't this have any effect when first showing the window?
// In 3.1.1 that used to work. Now I have to call setFocus() manually (see below)
defaultButton: 'partNo',

title: 'Combo Test',
width: 500,
height: 200,
layout: 'fit',
items: [
{
xtype: 'form',
ref: 'formPanel',
labelWidth: 100,
defaults: {
width: 300
},
items: [
{
id: 'partNo',
name: 'partNo',
ref: 'partNo',
fieldLabel: 'Part No',
xtype: 'combo',
store: partNoStore,
typeAhead: false,
allowBlank: false,
maxLength: 15,
displayField: 'partNo',
hideTrigger: true,
minChars: 1
},
{
name: 'foo',
fieldLabel: 'Foo',
xtype: 'textfield'
}
],
buttons: [
{
text: 'Close',
handler: this.close.createDelegate(this)
}
]
}
]
};
Ext.applyIf(config, defaultConfig);

ComboWindow.superclass.constructor.call(this, config);

this.show();

this.formPanel.partNo.focus.defer(300, this.formPanel.partNo);
}

});

new Ext.Button({
text: 'Click me',
handler: function() {
new ComboWindow();
},
renderTo: 'button'
});
});
</script>
</html>

This fixed json file is serving as the remotely loaded content (part-nos.json):



{
"total":10,
"data": [
{"partNo":"100"},
{"partNo":"101"},
{"partNo":"102"},
{"partNo":"103"},
{"partNo":"104"},
{"partNo":"105"},
{"partNo":"106"},
{"partNo":"107"},
{"partNo":"108"},
{"partNo":"110"}
],
"message":"",
"success":true,
"errors":{}
}


See this URL : http://www.eekboom.de/combo.htm

Steps to reproduce the problem:

Open http://www.eekboom.de/combo.htm
Click on "Click me"
Type any character in the "Part No" combo field
Note that the popup correctly appears after the store has received the data
Delete the character again (make the Part No field empty)
Move the window (i.e. drag it a little)
Type any character again
=> The request to the backend is fired, the response is correctly send, but no popup appears


Debugging already done:

Combobox has some special code that mimics blur event on mousedown anywhere in the document (see function mimicBlur in TriggerField).
That triggers when the window is moved making the combo think it has lost focus. The caret however is still in the combo field. When the data response is received it is ignored by the combobox because hasFocus==false

Possible fix:

not provided

evant
10 Jun 2010, 5:04 AM
I've seen a similar bug, except if you switch tabs while the combo has focus, then come back, you'll get the same result.

I believe it's because certain click/mousedown events are stopped/not propogated. I don't think it's going to be easy to solve.

stephen.friedrich
10 Jun 2010, 5:50 AM
For my specific problem I found a workaround:
If I do _not_ use "defaultButton" property, then the focus is simply lost after moving or resizing the dialog.
If I then click on "Part No" field again it works ok.

When I leave "defaultButton" the field stays focused, but thinks it isn't focused.

Of course the desired behavior is to not change the focus in any way when a window is moved or resized - I am surprised that it doesn't work this way. That's a more general usability bug.

For this specific dialog I used custom code and the document.activeElement property (now supported in all major browsers) to fix the focus afterwards. In that case the "Part No" combo stays focused and still works after resize/move:



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<title>ExtJS Test</title>

<link rel="stylesheet" type="text/css" href="http://www.extjs.com/deploy/dev/resources/css/ext-all.css"/>

<script type="text/javascript" src="http://www.extjs.com/deploy/dev/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="http://www.extjs.com/deploy/dev/ext-all-debug.js"></script>
</head>

<body>
<div id="button"></div>
</body>

<script language="JavaScript">
Ext.onReady(function() {
Ext.QuickTips.init();

var ComboWindow = Ext.extend(Ext.Window, {
constructor: function(config) {
config = config || {};

var partNoStore = new Ext.data.JsonStore({

method: 'GET',
proxy: new Ext.data.HttpProxy({
url: null,
api: {
read: {url: 'part-nos.json', method: 'GET'}
}
}),
autoDestroy: true,
root: 'data',
fields: [ 'partNo' ]
});

var defaultConfig = {
modal: true,

// Why doesn't this have any effect when first showing the window?
// In 3.1.1 that used to work. Now I have to call setFocus() manually (see below)
//defaultButton: 'partNo',

title: 'Combo Test',
width: 500,
height: 200,
layout: 'fit',
items: [
{
xtype: 'form',
ref: 'formPanel',
labelWidth: 100,
defaults: {
width: 300
},
items: [
{
id: 'partNo',
name: 'partNo',
ref: 'partNo',
fieldLabel: 'Part No',
xtype: 'combo',
store: partNoStore,
typeAhead: false,
allowBlank: false,
maxLength: 15,
displayField: 'partNo',
hideTrigger: true,
minChars: 1
},
{
name: 'foo',
fieldLabel: 'Foo',
xtype: 'textfield'
}
],
buttons: [
{
text: 'Close',
handler: this.close.createDelegate(this)
}
]
}
]
};
Ext.applyIf(config, defaultConfig);

ComboWindow.superclass.constructor.call(this, config);

this.show();

this.on("move", this.reFocus, this);
this.on("resize", this.reFocus, this);

this.formPanel.partNo.focus.defer(300, this.formPanel.partNo);
},

reFocus: function() {
if(document.activeElement) {
var formItems = this.formPanel.items;
var itemCount = formItems.getCount();
for(var i = 0; i < itemCount; ++i) {
var item = formItems.itemAt(i);
if(item.el.dom == document.activeElement) {
item.focus.defer(100, item);
}
}
}
}

});

new Ext.Button({
text: 'Click me',
handler: function() {
new ComboWindow();
},
renderTo: 'button'
});
});
</script>
</html>
Could you implement a general fix in ExtJS so that focus is not affected by moviong/resizing a window?

Jamie Avins
10 Jun 2010, 8:39 AM
Could you implement a general fix in ExtJS so that focus is not affected by moviong/resizing a window?

We cannot do that as it would be a breaking change for too many applications. We are planning on implementing a focus manager to handle these types of issues in the next major release.