Code:
// to fix a bug in Ext where if a combo's TriggerField is hidden,
// the combo will not render in IE
Ext.form.TriggerField.override({
afterRender: function() {
Ext.form.TriggerField.superclass.afterRender.call(this);
var y;
if (Ext.isIE && !this.hideTrigger && this.el.getY() != (y = this.trigger.getY())) {
this.el.position();
this.el.setY(y);
}
}
});
// workaround to get keyUp working for combo boxes
Ext.override(Ext.form.ComboBox, {
initEvents : function(){
Ext.form.ComboBox.superclass.initEvents.call(this);
this.keyNav = new Ext.KeyNav(this.el, {
"up" : function(e){
this.inKeyMode = true;
this.selectPrev();
},
"down" : function(e){
if(!this.isExpanded()){
this.onTriggerClick();
}else{
this.inKeyMode = true;
this.selectNext();
}
},
"enter" : function(e){
this.onViewClick();
this.delayedCheck = true;
this.unsetDelayCheck.defer(10, this);
},
"esc" : function(e){
this.collapse();
},
"tab" : function(e){
this.onViewClick(false);
return true;
},
"pageDown": function(e) {
if( !this.rowHeight ) {
return;
}
var index = Math.min(this.selectedIndex + this.rowsPerPage, this.store.getCount() - 1);
this.select(index);
},
"pageUp": function(e) {
if( !this.rowHeight ) {
return;
}
var index = Math.max(this.selectedIndex - this.rowsPerPage, 0);
this.select(index);
},
"home": function(e) {
this.select(0);
},
"end": function(e) {
this.select(this.store.getCount() - 1);
},
scope : this,
doRelay : function(foo, bar, hname){
if(hname == 'down' || this.scope.isExpanded()){
return Ext.KeyNav.prototype.doRelay.apply(this, arguments);
}
return true;
},
forceKeyDown : true
});
this.queryDelay = Math.max(this.queryDelay || 10,
this.mode == 'local' ? 10 : 250);
this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
if(this.typeAhead){
this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
}
if((this.editable !== false) && !this.enableKeyEvents) {
this.el.on("keyup", this.onKeyUp, this);
}
if(this.forceSelection){
this.on('blur', this.doForce, this);
}
},
calcRowsPerPage: function() {
if (this.store.getCount()) {
if (!this.rowHeight)
this.rowHeight = Ext.fly(this.view.getNode(0)).getHeight();
this.rowsPerPage = Math.floor(this.maxHeight / this.rowHeight);
} else {
this.rowHeight = false;
}
},
onKeyUp : function(e){
if(this.editable !== false && !e.isSpecialKey()){
this.lastKey = e.getKey();
//this.dqTask.delay(this.queryDelay);
// overriding the previous line so that the 1st query
// gets issued after 1 ms and subsequent queries get issued at the
// normal config value
this.dqTask.delay(this.lastQuery != undefined ? this.queryDelay : 1);
}
Ext.form.ComboBox.superclass.onKeyUp.call(this, e);
}
});
var lastSelection = null;
// as long as the 1st n chars of the query
// matches the 1st n chars of the 1st item in the list,
// cancel the query
function handleBeforeQuery(qe) {
if (qe.isDeleted) {
qe.combo.store.removeAll();
return true;
}
// try to match 1st n chars
var firstRec = qe.combo.store.getAt(0);
if (firstRec) {
var test = firstRec.get('Contract').substring(qe.query.length, 0);
if (test.toUpperCase() == qe.query.toUpperCase() && qe.combo.isExpanded()) {
// override Ext's lastQuery check
// so when a backspace is hit,
// a new AJAX call will be issued
qe.combo.lastQuery = test;
return false;
}
}
}
function handleKeyUp(field, e) {
if (e.isSpecialKey())
return;
var rawVal = field.getRawValue();
var doRequery = false;
var key = e.getCharCode();
var isDeleted = false;
// if combo is not expanded, and the user
// is typing in chars which are already in store,
// we need to expand the list somehow
if (rawVal && rawVal.length != 0) {
// if DELETE or BACKSPACE has been used, force a reload
if (key == e.BACKSPACE || key == e.DELETE) {
doRequery = true;
isDeleted = true;
}
else if (field.isExpanded() == false) {
var firstRec = field.store.getAt(0);
if (!firstRec) {
// no records present, force load
doRequery = true;
}
else {
var test = firstRec.get('Contract').substring(rawVal.length, 0);
if (test.toUpperCase() == rawVal.toUpperCase()) {
// for some reason, expand doesn't work
// so force all records from store to be remoded
// and a new query to be issued
doRequery = true;
}
}
}
}
// if the list is collapsed because of loss of focus, expand it
if (field.isExpanded() == false && field.store.getTotalCount() != 0) {
field.keyNav.down.call(field);
}
if (field.isExpanded() == false) {
field.expand();
}
// if number of chars is less than minChars,
// collapse the list if it's expanded
if (rawVal.length < field.minChars && field.isExpanded()) {
field.collapse();
}
if (doRequery && rawVal.length >= field.minChars) {
var qe = {
forceReload: true,
query: rawVal,
combo: field,
cancel: false,
isDeleted: isDeleted
};
field.fireEvent('beforequery', qe);
// force a collapse and expand to requery
field.collapse();
field.expand();
}
}
function handleBlur(combo) {
// if the list is still visible after the
// combo looses focus, force it to be hidden
if (combo.isExpanded())
combo.collapse();
}
comboRet = new Ext.form.ComboBox(
{
name: id,
id: id,
fieldLabel: fieldLabel,
tabIndex: 1,
store: contractSearchDS,
displayField: 'Contract',
minChars: 2,
forceSelection: true,
typeAhead: false,
hideTrigger: true,
enableKeyEvents: true,
queryDelay: '5',
listWidth:450,
maxHeight: 288, // single row Height is 18px so this is in multiples of 18 to prevent
// odd pgUp/pgDn behavior towards start and end of the list
tpl: contractTmpl,
itemSelector: 'div.ux-search-item',
listeners: {
beforequery: handleBeforeQuery,
keyup: handleKeyUp,
blur: handleBlur
}
});