PDA

View Full Version : [OPEN] ComboBox TypeAhead incorrect behaviour



nahab
8 May 2015, 5:34 AM
Hi

I found incorrect behaviour of combobox TypeAhead feature. At first I found it in ExtJS 3, then decided to check this in ExtJS 4. It's little bit differ bug behaviour in 3 and in 4 but root is the same.

Let's assume we have some list of values like: "000","AAA","ABA","ABC".
And we typing "A" then "B" look what happening:

For ExtJs 4 if you "found" "correct" typing speed bug behaviour will be next:
you type "A", you type "B" and instead of options "ABA" and "ABC" you see only "ABA".
Tip -> "ABA" is a first item in list of "ABA" & "ABC"

For ExtJs3 behaviour will be next:
you type "A", you type "B" and instead of options "ABA" and "ABC" you see only "AAA". Tip -> Actually "AAA" is a first result after you typed "A".

But root of issue for both ExtJs3 and ExtJs4 is the same - onTypeAhead() method relies on this.getRawValue() that can be changed while ExtJS processed previous value.

I didn't check ExtJs5 yet, but I think this bug can be still present in it.

For making better understanding you can look at the attached .gif files - one for ExtJs4 and one for ExtJs3.

Code for ExtJS4:

<script type="text/javascript">
Ext.onReady(function(){
clientStore = new Ext.data.JsonStore({
data: [
{NAME: "000", ID: "-1"},
{NAME:"AAA", ID:"0"},
{NAME:"AAB", ID:"1"},
{NAME:"AAC", ID:"2"},
{NAME:"AAD", ID:"3"},
{NAME:"ABA", ID:"4"},
{NAME:"ABB", ID:"5"},
{NAME:"ABC", ID:"6"},
{NAME:"ACA", ID:"7"},
{NAME:"ACB", ID:"8"},
{NAME:"ACC", ID:"9"}],
fields: [{name: 'NAME', type: 'string'}, {name: 'ID', type: 'string'}]
});


clientDD = new Ext.form.ComboBox({
queryMode: 'local',
emptyText: 'start',
displayField: 'NAME',
valueField: 'ID',
store: clientStore,
typeAhead: true,
resizable: true,
selectOnFocus: true,
forceSelection: true,
triggerAction: 'all',
width: 200,
maxHeight: 200,
listWidth: 400,
// queryDelay:100, //def 10
typeAheadDelay: 50, // def 250
renderTo: 'id_div'
});
});


</script>


<div id="id_div"></div>


My logs of Ext.form.field.ComboBox, first colum is time deltas between previous and current actions in milliseconds:


0 onKeyUp():: lastKey=65; rawValue("a")
16 doRawQuery():: rawValue("a")
0 doQuery():: rawQuery="true"; rawValue("a")
1 doLocalQuery():: filtering store by "a"; rawValue("a")
27 afterQuery():: rawValue("a")
0 afterQuery():: call doTypeAhead(); rawValue("a")
0 doAutoSelect():: rawValue("a")
51 onTypeAhead():: rawValue("ab")
25 onKeyUp():: lastKey=66; rawValue("ABA")
11 doRawQuery():: rawValue("ABA")
0 doQuery():: rawQuery="true"; rawValue("ABA")
0 doLocalQuery():: filtering store by "ABA"; rawValue("ABA")
6 afterQuery():: rawValue("ABA")
0 afterQuery():: call doTypeAhead(); rawValue("ABA")
1 doAutoSelect():: rawValue("ABA")
51 onTypeAhead():: rawValue("ABA")

nahab
8 May 2015, 5:46 AM
This one is for ExtJS3.

Here list was "000","FAT","FUT".


Ext.onReady(function () {
clientStore = new Ext.data.JsonStore({
data: {clients: [
{NAME: "000", ID: "-1"},
{NAME: "AAA", ID: "0"},
{NAME: "AAB", ID: "1"},
{NAME: "AAC", ID: "2"},
{NAME: "AAD", ID: "3"},
{NAME: "ABA", ID: "4"},
{NAME: "ABB", ID: "5"},
{NAME: "ABC", ID: "6"},
{NAME: "ACA", ID: "7"},
{NAME: "ACB", ID: "8"},
{NAME: "ACC", ID: "9"}
]},
root: 'clients',
fields: [
{name: 'NAME', type: 'string'},
{name: 'ID', type: 'string'}
]
});




clientDD = new Ext.form.ComboBox({
mode: 'local',
displayField: 'NAME',
valueField: 'ID',
store: clientStore,
typeAhead: true,
resizable: true,
selectOnFocus: true,
forceSelection: true,
triggerAction: 'all',
width: 200,
maxHeight: 200,
listWidth: 400,
// queryDelay:0, //def 10
// typeAheadDelay: 0, // def 250
renderTo: 'id_div'
});


//clientDD.queryDelay = 0;
});


===================================================================
Normal behaviour
===================================================================
typing too fast
-------------------------------------------------------------------


0 onKeyUp():: lastKey is 70; rawValue("f")
15 initQuery():: doQuery("f")
0 doQuery():: filtering Store by "f"; rawValue("f")
17 onLoad():: selectNext() - select first item from combo list
1 onLoad():: taTask.delay(); rawValue("f")


207 onKeyUp():: lastKey is 85; rawValue("fu")
11 initQuery():: doQuery("fu")
0 doQuery():: filtering Store by "fu"; rawValue("fu")
2 onLoad():: selectNext() - select first item from combo list
0 onLoad():: taTask.delay(); rawValue("fu")
252 onTypeAhead():: newValue "FUT"; rawValue("fu")


===================================================================
typing slow
-------------------------------------------------------------------


0 onKeyUp():: lastKey is 70; rawValue("f")
11 initQuery():: doQuery("f")
0 doQuery():: filtering Store by "f"; rawValue("f")
15 onLoad():: selectNext() - select first item from combo list
1 onLoad():: taTask.delay(); rawValue("f")
249 onTypeAhead():: newValue "FAT"; rawValue("f")


569 onKeyUp():: lastKey is 85; rawValue("Fu")
12 initQuery():: doQuery("Fu")
0 doQuery():: filtering Store by "Fu"; rawValue("Fu")
3 onLoad():: selectNext() - select first item from combo list
1 onLoad():: taTask.delay(); rawValue("Fu")
252 onTypeAhead():: newValue "FUT"; rawValue("Fu")


===================================================================
Bug appearing
===================================================================
1. onTypeAhead() before second onKeyUp()
-------------------------------------------------------------------


0 onKeyUp():: lastKey is 70; rawValue("f")
11 initQuery():: doQuery("f")
0 doQuery():: filtering Store by "f"; rawValue("f")
29 onLoad():: selectNext() - select first item from combo list
0 onLoad():: taTask.delay(); rawValue("f")
252 onTypeAhead():: newValue "FAT"; rawValue("fu")


35 onKeyUp():: lastKey is 85; rawValue("FAT")
12 initQuery():: doQuery("FAT")
0 doQuery():: filtering Store by "FAT"; rawValue("FAT")
1 onLoad():: selectNext() - select first item from combo list
1 onLoad():: taTask.delay(); rawValue("FAT")
252 onTypeAhead():: newValue "FAT"; rawValue("FAT")


====================================================================
2. second onKeyUp() before onTypeAhead()
-------------------------------------------------------------------


0 onKeyUp():: lastKey is 70; rawValue("f")
12 initQuery():: doQuery("f")
0 doQuery():: filtering Store by "f"; rawValue("f")
14 onLoad():: selectNext() - select first item from combo list
0 onLoad():: taTask.delay(); rawValue("f")


246 onKeyUp():: lastKey is 85; rawValue("fu")
6 onTypeAhead():: newValue "FAT"; rawValue("fu")


4 initQuery():: doQuery("FAT")
1 doQuery():: filtering Store by "FAT"; rawValue("FAT")
4 onLoad():: selectNext() - select first item from combo list
1 onLoad():: taTask.delay(); rawValue("FAT")
252 onTypeAhead():: newValue "FAT"; rawValue("FAT")


======================================================================
3. Bug with
typeAheadDelay = 0
queryDelay = 0
-------------------------------------------------------------------


0 onKeyUp():: lastKey is 70; rawValue("f")
5 initQuery():: doQuery("f")
0 doQuery():: filtering Store by "f"; rawValue("f")
14 onLoad():: selectNext() - select first item from combo list
1 onLoad():: taTask.delay(); rawValue("f")
5 onTypeAhead():: newValue "FAT"; rawValue("fu")


47 onKeyUp():: lastKey is 85; rawValue("FAT")
5 initQuery():: doQuery("FAT")
0 doQuery():: filtering Store by "FAT"; rawValue("FAT")
2 onLoad():: selectNext() - select first item from combo list
0 onLoad():: taTask.delay(); rawValue("FAT")
6 onTypeAhead():: newValue "FAT"; rawValue("FAT")


======================================================================

nahab
8 May 2015, 6:16 AM
My fix for ExtJS3 was to check is selected value from list for typeaheading starts from rawValue symbols, if not just don't do typeaheading:


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

Ext.ux.form.TypeAheadComboBox = Ext.extend(Ext.form.ComboBox, {
/**/
onTypeAhead : function(){
if(this.store.getCount() > 0){
var r = this.store.getAt(0);
var newValue = r.data[this.displayField];
var len = newValue.length;
var rawValue = this.getRawValue();
var selStart = rawValue.length;
if(selStart != len && newValue.toUpperCase().indexOf(rawValue.toUpperCase()) == 0){
this.setRawValue(newValue);
this.selectText(selStart, newValue.length);
}
}
}
/* */
});

Ext.reg('typeAheadCombo', Ext.ux.form.TypeAheadComboBox);

Gary Schlosberg
8 May 2015, 11:21 AM
Thanks for the report! I have opened a bug in our bug tracker.