PDA

View Full Version : Advanced Combo box functionality



djMax
17 Oct 2007, 4:57 PM
I'd like to change the ComboBox so that if it fetches say 8 records for the prefix "foo" (when configured to get 10) that it continues to hone down the existing list rather than refetching every time. So this setting would be "prefixCombo" or something. Now, my question is where might I put this logic? Obviously, I'd like to do this as an extension rather than modifying Ext code. I feel like it has to go in the JsonReader, but there are some strange side effects there, like the jsonData member which is meant to store the "opaque" blob that came back.

Anyhow, has anyone done something like this? Any thoughts on alternative implementations?

djMax
18 Oct 2007, 7:32 AM
So I had some success doing this directly in Combo.js. I had to access a few private variables in Store, but whaddyagonnado. The new property "requestSize" controls when this feature is enabled, and it means "how many records did you ask for, and if I get less than that I will assume further characters can only reduce the matches".

First, I have it check for whether local filtering should be used during doQuery:



doQuery : function(q, forceAll){
if(q === undefined || q === null){
q = '';
}
var qe = {
query: q,
forceAll: forceAll,
combo: this,
cancel:false
};
if(this.fireEvent('beforequery', qe)===false || qe.cancel){
return false;
}
q = qe.query;
forceAll = qe.forceAll;
if(forceAll === true || (q.length >= this.minChars)){
if(this.lastQuery != q){
var oldQ = this.lastQuery; // I ADDED THIS
this.lastQuery = q;
if(this.mode == 'local'){
this.selectedIndex = -1;
if(forceAll){
this.store.clearFilter();
}else{
this.store.filter(this.displayField, q);
}
this.onLoad();
}else{
this.store.baseParams[this.queryParam] = q;
if (this.requestSize && this.filterLocal(oldQ, q)) // I ADDED THIS AND THE FILTER LINES BELOW
{
this.store.filter(this.displayField, q);
this.onLoad();
}
else
{
this.store.load({
params: this.getParams(q)
});
}
this.expand();
}
}else{
this.selectedIndex = -1;
this.onLoad();
}
}
},


Then, the filterLocal function does some stuff to handle both a "bigger substring" and a "smaller substring" from the original set:



// private
filterLocal: function(oldQ, q)
{
var st = this.store, stn = st.snapshot;
var ct = st.getTotalCount(), rct = st.getCount();
var hf = (stn && stn != st.data);
ct = Math.max(ct, hf ? stn.length : rct);
if (ct > this.requestSize) return false;
if (!hf)
{
if (oldQ && q.indexOf(oldQ) == 0)
{
st.oldQ = oldQ;
return true;
}
return false;
}
else if (st.oldQ && q.indexOf(st.oldQ) == 0)
{
st.clearFilter(true);
return true;
}
return false;
},