Ext.form.ClearComboBox = Ext.extend(Ext.form.TwinTriggerField, {
defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
listClass : '',
selectedClass : 'x-combo-selected',
listEmptyText: '- All -',
trigger1Class: 'x-form-clear-trigger',
trigger2Class: 'x-form-arrow-trigger',
hideTrigger1: true,
shadow : 'sides',
listAlign : 'tl-bl?',
maxHeight : 300,
minHeight : 90,
triggerAction : 'query',
minChars : 4,
autoSelect : true,
typeAhead : false,
queryDelay : 500,
pageSize : 0,
selectOnFocus : false,
queryParam : 'query',
loadingText : 'Loading...',
resizable : false,
handleHeight : 8,
allQuery: '- All -',
mode: 'remote',
minListWidth : 70,
forceSelection : false,
typeAheadDelay : 250,
lazyInit : true,
clearFilterOnReset : true,
submitValue: undefined,
initComponent : function(){
Ext.form.ClearComboBox.superclass.initComponent.call(this);
this.addEvents(
'expand',
'collapse',
'beforeselect',
'select',
'beforequery'
);
if(this.transform){
var s = Ext.getDom(this.transform);
if(!this.hiddenName){
this.hiddenName = s.name;
}
if(!this.store){
this.mode = 'local';
var d = [], opts = s.options;
for(var i = 0, len = opts.length;i < len; i++){
var o = opts[i],
value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;
if(o.selected && Ext.isEmpty(this.value, true)) {
this.value = value;
}
d.push([value, o.text]);
}
this.store = new Ext.data.ArrayStore({
'id': 0,
fields: ['value', 'text'],
data : d,
autoDestroy: true
});
this.valueField = 'value';
this.displayField = 'text';
}
s.name = Ext.id();
if(!this.lazyRender){
this.target = true;
this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
this.render(this.el.parentNode, s);
}
Ext.removeNode(s);
}
else if(this.store){
this.store = Ext.StoreMgr.lookup(this.store);
if(this.store.autoCreated){
this.displayField = this.valueField = 'field1';
if(!this.store.expandData){
this.displayField = 'field2';
}
this.mode = 'local';
}
}
this.selectedIndex = -1;
if(this.mode == 'local'){
if(!Ext.isDefined(this.initialConfig.queryDelay)){
this.queryDelay = 10;
}
if(!Ext.isDefined(this.initialConfig.minChars)){
this.minChars = 0;
}
}
},
onRender : function(ct, position){
if(this.hiddenName && !Ext.isDefined(this.submitValue)){
this.submitValue = false;
}
Ext.form.ClearComboBox.superclass.onRender.call(this, ct, position);
if(this.hiddenName){
this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
id: (this.hiddenId||this.hiddenName)}, 'before', true);
}
if(Ext.isGecko){
this.el.dom.setAttribute('autocomplete', 'off');
}
if(!this.lazyInit){
this.initList();
}else{
this.on('focus', this.initList, this, {single: true});
}
},
initValue : function(){
Ext.form.ClearComboBox.superclass.initValue.call(this);
if(this.hiddenField){
this.hiddenField.value =
Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, '- All -');
}
},
getParentZIndex : function(){
var zindex;
if (this.ownerCt){
this.findParentBy(function(ct){
zindex = parseInt(ct.getPositionEl().getStyle('z-index'), 10);
return !!zindex;
});
}
return zindex;
},
initList : function(){
if(!this.list){
var cls = 'x-combo-list',
listParent = Ext.getDom(this.getListParent() || Ext.getBody()),
zindex = parseInt(Ext.fly(listParent).getStyle('z-index'), 10);
if (!zindex) {
zindex = this.getParentZIndex();
}
this.list = new Ext.Layer({
parentEl: listParent,
shadow: this.shadow,
cls: [cls, this.listClass].join(' '),
constrain:false,
zindex: (zindex || 12000) + 5
});
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.syncFont !== false){
this.list.setStyle('font-size', this.el.getStyle('font-size'));
}
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.mon(this.innerList, 'mouseover', this.onViewOver, this);
this.mon(this.innerList, '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 = '{' + this.displayField + '}
';
}
this.view = new Ext.DataView({
applyTo: this.innerList,
tpl: this.tpl,
singleSelect: true,
selectedClass: this.selectedClass,
itemSelector: this.itemSelector || '.' + cls + '-item',
emptyText: this.listEmptyText,
deferEmptyText: false
});
this.mon(this.view, {
containerclick : this.onViewClick,
click : this.onViewClick,
scope :this
});
this.bindStore(this.store, true);
if(this.resizable){
this.resizer = new Ext.Resizable(this.list, {
pinned:true, handles:'se'
});
this.mon(this.resizer, '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');
}
}
},
getListParent : function() {
return document.body;
},
getStore : function(){
return this.store;
},
bindStore : function(store, initial){
if(this.store && !initial){
if(this.store !== store && this.store.autoDestroy){
this.store.destroy();
}else{
this.store.un('beforeload', this.onBeforeLoad, this);
this.store.un('load', this.onLoad, this);
this.store.un('exception', this.collapse, this);
}
if(!store){
this.store = null;
if(this.view){
this.view.bindStore(null);
}
if(this.pageTb){
this.pageTb.bindStore(null);
}
}
}
if(store){
if(!initial) {
this.lastQuery = null;
if(this.pageTb) {
this.pageTb.bindStore(store);
}
}
this.store = Ext.StoreMgr.lookup(store);
this.store.on({
scope: this,
beforeload: this.onBeforeLoad,
load: this.onLoad,
exception: this.collapse
});
if(this.view){
this.view.bindStore(store);
}
}
},
reset : function(){
Ext.form.ClearComboBox.superclass.reset.call(this);
if(this.clearFilterOnReset && this.mode == 'local'){
this.store.clearFilter();
}
},
initEvents : function(){
Ext.form.ClearComboBox.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.onTrigger2Click();
}else{
this.inKeyMode = true;
this.selectNext();
}
},
"enter" : function(e){
this.onViewClick();
},
"esc" : function(e){
this.collapse();
},
"tab" : function(e){
if (this.forceSelection === true) {
this.collapse();
} else {
this.onViewClick(false);
}
return true;
},
scope : this,
doRelay : function(e, h, hname){
if(hname == 'down' || this.scope.isExpanded()){
var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
if(!Ext.isIE && Ext.EventManager.useKeydown){
this.scope.fireKey(e);
}
return relay;
}
return true;
},
forceKeyDown : true,
defaultEventAction: 'stopEvent'
});
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.enableKeyEvents){
this.mon(this.el, 'keyup', this.onKeyUp, this);
}
},
onDestroy : function(){
if (this.dqTask){
this.dqTask.cancel();
this.dqTask = null;
}
this.bindStore(null);
Ext.destroy(
this.resizer,
this.view,
this.pageTb,
this.list
);
Ext.destroyMembers(this, 'hiddenField');
Ext.form.ClearComboBox.superclass.onDestroy.call(this);
},
fireKey : function(e){
if (!this.isExpanded()) {
Ext.form.ClearComboBox.superclass.fireKey.call(this, e);
}
},
onResize : function(w, h){
Ext.form.ClearComboBox.superclass.onResize.apply(this, arguments);
if(!isNaN(w) && this.isVisible() && this.list){
this.doResize(w);
}else{
this.bufferSize = w;
}
},
doResize: function(w){
if(!Ext.isDefined(this.listWidth)){
var lw = Math.max(w, this.minListWidth);
this.list.setWidth(lw);
this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
}
},
onEnable : function(){
Ext.form.ClearComboBox.superclass.onEnable.apply(this, arguments);
if(this.hiddenField){
this.hiddenField.disabled = false;
}
},
onDisable : function(){
Ext.form.ClearComboBox.superclass.onDisable.apply(this, arguments);
if(this.hiddenField){
this.hiddenField.disabled = true;
}
},
onBeforeLoad : function(){
if(!this.hasFocus){
return;
}
this.innerList.update(this.loadingText ?
'
'+this.loadingText+'
' : '');
this.restrictHeight();
this.selectedIndex = -1;
},
onLoad : function(){
if(!this.hasFocus){
return;
}
if(this.store.getCount() > 0 || this.listEmptyText){
this.expand();
this.restrictHeight();
if(this.lastQuery == this.allQuery){
if(this.editable){
this.el.dom.select();
}
if(this.autoSelect !== false && !this.selectByValue(this.value, true)){
this.select(0, true);
}
}else{
if(this.autoSelect !== false){
this.selectNext();
}
if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
this.taTask.delay(this.typeAheadDelay);
}
}
}else{
this.collapse();
}
},
onTypeAhead : function(){
if(this.store.getCount() > 0){
var r = this.store.getAt(0);
var newValue = r.data[this.displayField];
var len = newValue.length;
var selStart = this.getRawValue().length;
if(selStart != len){
this.setRawValue(newValue);
this.selectText(selStart, newValue.length);
}
}
},
assertValue : function(){
var val = this.getRawValue(),
rec = this.findRecord(this.displayField, val);
if(!rec && this.forceSelection){
if(val.length > 0 && val != this.emptyText){
this.el.dom.value = Ext.value(this.lastSelectionText, '');
this.applyEmptyText();
}else{
this.clearValue();
}
}else{
if(rec){
if (val == rec.get(this.displayField) && this.value == rec.get(this.valueField)){
return;
}
val = rec.get(this.valueField || this.displayField);
}
this.setValue(val);
}
},
onSelect : function(record, index){
if(this.fireEvent('beforeselect', this, record, index) !== false){
this.setValue(record.data[this.valueField || this.displayField]);
this.collapse();
this.fireEvent('select', this, record, index);
this.triggers[0].show();
}
},
getName: function(){
var hf = this.hiddenField;
return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ClearComboBox.superclass.getName.call(this);
},
getValue : function(){
if(this.valueField){
return Ext.isDefined(this.value) ? this.value : '- All -';
}else{
return Ext.form.ClearComboBox.superclass.getValue.call(this);
}
},
clearValue : function(){
if(this.hiddenField){
this.hiddenField.value = '';
}
this.setRawValue('- All -');
this.lastSelectionText = '';
this.applyEmptyText();
this.value = '- All -';
},
setValue : function(v){
var text = v;
if(this.valueField){
var r = this.findRecord(this.valueField, v);
if(r){
text = r.data[this.displayField];
}else if(Ext.isDefined(this.valueNotFoundText)){
text = this.valueNotFoundText;
}
}
this.lastSelectionText = text;
if(this.hiddenField){
this.hiddenField.value = Ext.value(v, '');
}
Ext.form.ClearComboBox.superclass.setValue.call(this, text);
this.value = v;
if (this.triggers) {
if (v == null || v == '- All -')
this.triggers[0].hide();
else
this.triggers[0].show();
}
return this;
},
findRecord : function(prop, value){
var record;
if(this.store.getCount() > 0){
this.store.each(function(r){
if(r.data[prop] == value){
record = r;
return false;
}
});
}
return record;
},
onViewMove : function(e, t){
this.inKeyMode = false;
},
onViewOver : function(e, t){
if(this.inKeyMode){
return;
}
var item = this.view.findItemFromChild(t);
if(item){
var index = this.view.indexOf(item);
this.select(index, false);
}
},
onViewClick : function(doFocus){
var index = this.view.getSelectedIndexes()[0],
s = this.store,
r = s.getAt(index);
if(r){
this.onSelect(r, index);
}else {
this.collapse();
}
if(doFocus !== false){
this.el.focus();
}
},
restrictHeight : function(){
this.innerList.dom.style.height = '';
var inner = this.innerList.dom,
pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
ha = this.getPosition()[1]-Ext.getBody().getScroll().top,
hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,
space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
h = Math.min(h, space, this.maxHeight);
this.innerList.setHeight(h);
this.list.beginUpdate();
this.list.setHeight(h+pad);
this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
this.list.endUpdate();
},
isExpanded : function(){
return this.list && this.list.isVisible();
},
selectByValue : function(v, scrollIntoView){
if(!Ext.isEmpty(v, true)){
var r = this.findRecord(this.valueField || this.displayField, v);
if(r){
this.select(this.store.indexOf(r), scrollIntoView);
return true;
}
}
return false;
},
select : function(index, scrollIntoView){
this.selectedIndex = index;
this.view.select(index);
if(scrollIntoView !== false){
var el = this.view.getNode(index);
if(el){
this.innerList.scrollChildIntoView(el, false);
}
}
},
selectNext : function(){
var ct = this.store.getCount();
if(ct > 0){
if(this.selectedIndex == -1){
this.select(0);
}else if(this.selectedIndex < ct-1){
this.select(this.selectedIndex+1);
}
}
},
selectPrev : function(){
var ct = this.store.getCount();
if(ct > 0){
if(this.selectedIndex == -1){
this.select(0);
}else if(this.selectedIndex !== 0){
this.select(this.selectedIndex-1);
}
}
},
onKeyUp : function(e){
var k = e.getKey();
if(this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())){
this.lastKey = k;
this.dqTask.delay(this.queryDelay);
}
Ext.form.ClearComboBox.superclass.onKeyUp.call(this, e);
},
validateBlur : function(){
return !this.list || !this.list.isVisible();
},
initQuery : function(){
this.doQuery(this.getRawValue());
},
beforeBlur : function(){
this.assertValue();
},
postBlur : function(){
Ext.form.ClearComboBox.superclass.postBlur.call(this);
this.collapse();
this.inKeyMode = false;
},
doQuery : function(q, forceAll){
q = Ext.isEmpty(q) ? '- All -' : 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){
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;
this.store.load({
params: this.getParams(q)
});
this.expand();
}
}else{
this.selectedIndex = -1;
this.onLoad();
}
}
},
getParams : function(q){
var p = {};
if(this.pageSize){
p.start = 0;
p.limit = this.pageSize;
}
return p;
},
collapse : function(){
if(!this.isExpanded()){
return;
}
this.list.hide();
Ext.getDoc().un('mousewheel', this.collapseIf, this);
Ext.getDoc().un('mousedown', this.collapseIf, this);
this.fireEvent('collapse', this);
},
collapseIf : function(e){
if(!this.isDestroyed && !e.within(this.wrap) && !e.within(this.list)){
this.collapse();
}
},
expand : function(){
if(this.isExpanded() || !this.hasFocus){
return;
}
if(this.title || this.pageSize){
this.assetHeight = 0;
if(this.title){
this.assetHeight += this.header.getHeight();
}
if(this.pageSize){
this.assetHeight += this.footer.getHeight();
}
}
if(this.bufferSize){
this.doResize(this.bufferSize);
delete this.bufferSize;
}
this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
var listParent = Ext.getDom(this.getListParent() || Ext.getBody()),
zindex = parseInt(Ext.fly(listParent).getStyle('z-index') ,10);
if (!zindex){
zindex = this.getParentZIndex();
}
if (zindex) {
this.list.setZIndex(zindex + 5);
}
this.list.show();
if(Ext.isGecko2){
this.innerList.setOverflow('auto');
}
this.mon(Ext.getDoc(), {
scope: this,
mousewheel: this.collapseIf,
mousedown: this.collapseIf
});
this.fireEvent('expand', this);
},
onTrigger1Click : function(){
this.setValue('- All -');
this.triggers[0].hide();
this.fireEvent('select', this, null);
},
onTrigger2Click : function(){
if(this.readOnly || this.disabled){
return;
}
if(this.isExpanded()){
this.collapse();
this.el.focus();
}else {
this.onFocus({});
if(this.triggerAction == 'all') {
this.doQuery(this.allQuery, true);
} else {
this.doQuery(this.getRawValue());
}
this.el.focus();
}
}
});
Ext.reg('clearcombo', Ext.form.ClearComboBox);