在Ext的应用中,我们常用到要按照日期区间进行查询,通常的做法是写两个日期组件进行成布局来实现,我觉得这样做虽然功能是实现了,但是用户体验不够好,与是编写了如下的日期区间选择组件,代码如下:
/** * 日期区间查询组件 * @class Ext.form.uxDateAreaField * @extends Ext.Container */ Ext.form.uxDateAreaField = Ext.extend(Ext.Container,{ single : true,//是否只提交一个参数 paramName : [null,null], format : 'Y-m-d',//日期格式化 separator : ',',//是一个参数提交时,两个日期之间扮隔符 allowBlank : true, disabled : false, blankText : '开始日期与结束日期不能为空', msgTarget : 'qtip',//提示信息的样式 invalidText : '开始日期不能大于结束日期', invalidClass : 'x-form-invalid', disabledClass : 'x-item-disabled', preventMark : false,//true阻止组件被标记为不可用 //private cls : 'x-form-text x-form-field', //private isFormField : true, //private activeField : null, initComponent : function(){ Ext.form.uxDateAreaField.superclass.initComponent.call(this); this.startName = this.single?null:(this.paramName[0] || (this.name + 'Start')); this.endName = this.single?null:(this.paramName[1] || (this.name + 'End')); this.menu = new Ext.menu.DateMenu({ scope : this, handler : function(picker,date){ if(!Ext.isEmpty(this.activeField)){ this.activeField.setValue(date.format(this.format)); var b = this.validateValue(); if(b && !Ext.isEmpty(this.hiddenField)){ this.hiddenField.setValue(this.getValue()); } } } }); //起始日期 this.startField = new Ext.form.TextField({ style : 'border:none;text-align:center;margin-left:-3px;', cls : 'ux-datearea-field', name : this.startName, disabled : this.disabled, listeners : { scope : this, 'focus' : function(field){ this.activeField = field; this.addClass('x-form-focus'); this.menu.show(field.el, "tl-bl?"); }, 'blur' : function(){ this.removeClass('x-form-focus'); this.validateValue(); }, 'render' : function(field){ field.removeClass('x-form-text'); if(this.single/* || Ext.isEmpty(this.name)*/){ field.el.dom.name = null; }else{ this.remove(this.hiddenField); } } } }); //显示的分隔符 this.displayField = new Ext.form.DisplayField({ cls : 'ux-datearea-field', style : 'padding-top: 3px;line-height:normal;', width : 16, value : '到' }); this.endField = this.startField.cloneConfig({ name : this.endName }); this.hiddenField = new Ext.form.Hidden({ ref : 'containerField', name : this.name, disabled : this.disabled }); this.add(this.startField,this.displayField,this.endField,this.hiddenField); this.setDisabled(this.disabled); this.on('resize',function(){ this.fixWidth(); this.el.setStyle({ 'padding-top' : '0px', 'height' : Ext.isIE?'22px':'21px' }); },this); }, disable : function(){ if(this.rendered){ this.addClass(this.disabledClass); this.startField.disable(); this.endField.disable(); } this.disabled = true; return this; }, enable : function(){ if(this.rendered){ this.removeClass(this.disabledClass); this.startField.enable(); this.endField.enable(); } this.disabled = false; return this; }, //private validateValue : function(){ var startValue = this.startField.getValue(); var endValue = this.endField.getValue(); if(!Ext.isEmpty(startValue) && !Ext.isEmpty(endValue)){ if(startValue > endValue){ this.markInvalid(); return false; }else{ this.clearInvalid(); return true; } }else if(!this.allowBlank){ this.markInvalid(this.blankText); return false; } return true; }, validate : function(){ if(!this.disabled){ return this.validateValue(); } return true; }, //private fixWidth : function(){ var calcWidth = (this.el.getComputedWidth() - 24)/2; this.startField.setWidth(calcWidth + 3); this.endField.setWidth(calcWidth + 3); }, //private getMessageHandler : function(){ return Ext.form.MessageTargets[this.msgTarget]; }, //设置值 getValue : function(){ var start = this.startField.getValue(); var end = this.endField.getValue(); if(this.single){ return start + this.separator + end; }else{ return [start,end]; } }, //取值 setValue : function(v){ this.value = v; if(this.rendered){ if(Ext.isEmpty(v)){ this.startField.setValue(''); this.endField.setValue(''); if(!this.allowBlank){ this.validateValue(); } }else{ if(Ext.isString(v)){ var valueArray = v.split(this.separator); this.startField.setValue(valueArray[0]); this.endField.setValue(valueArray[1]); } if(Ext.isArray(v)){ this.startField.setValue(v[0]); this.endField.setValue(v[1]); } if(Ext.isObject(v)){ this.startField.setValue(v[this.startName]); this.endField.setValue(v[this.endName]); } } this.validateValue(); } return this; }, markInvalid : function(msg){ if (this.rendered && !this.preventMark) { msg = msg || this.invalidText; var mt = this.getMessageHandler(); if(mt){ mt.mark(this, msg); this.startField.addClass('ux-dataarea-invalid'); this.endField.addClass('ux-dataarea-invalid'); this.displayField.addClass('ux-dataarea-invalid'); }else if(this.msgTarget){ this.el.addClass(this.invalidClass); this.startField.addClass('ux-dataarea-invalid'); this.endField.addClass('ux-dataarea-invalid'); this.displayField.addClass('ux-dataarea-invalid'); var t = Ext.getDom(this.msgTarget); if(t){ t.innerHTML = msg; t.style.display = this.msgDisplay; } } } }, afterRender : function(){ Ext.form.uxDateAreaField.superclass.afterRender.call(this); // this.initEvents(); this.initValue(); if(!this.single){ this.remove(this.hiddenField); } }, initValue : function(){ if(this.value !== undefined){ this.setValue(this.value); }else /*if(!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText)*/{ this.setValue(''); } this.originalValue = this.getValue(); }, reset : function(){ this.setValue(this.originalValue); this.clearInvalid(); }, clearInvalid : function(){ if (this.rendered && !this.preventMark) { this.el.removeClass(this.invalidClass); this.startField.removeClass('ux-dataarea-invalid'); this.endField.removeClass('ux-dataarea-invalid'); this.displayField.removeClass('ux-dataarea-invalid'); var mt = this.getMessageHandler(); if(mt){ mt.clear(this); }else if(this.msgTarget){ this.el.removeClass(this.invalidClass); this.startField.removeClass('ux-dataarea-invalid'); this.endField.removeClass('ux-dataarea-invalid'); this.displayField.removeClass('ux-dataarea-invalid'); var t = Ext.getDom(this.msgTarget); if(t){ t.innerHTML = ''; t.style.display = 'none'; } } } }, getName : function(){ return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || ''; }, getErrorCt : function(){ return this.el.findParent('.x-form-element', 5, true) || this.el.findParent('.x-form-field-wrap', 5, true); }, // Alignment for 'under' target alignErrorEl : function(){ this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20); }, // Alignment for 'side' target alignErrorIcon : function(){ this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]); } }); Ext.reg('dateareafield',Ext.form.uxDateAreaField);
要用到的样式为:
.ux-datearea-field{
float:left;
background-color: #FFFFFF;
text-align:center;
padding-top: 4px;
background-image: url("../js/ext/resources/images/default/form/text-bg.gif");
}
.ux-dataarea-invalid{
background-color:#fbeced;
background-image: url("");
}
图片文件在附件中
实现的效果请参考附件中的图片
说明:大家可以把组件进行提取,再此基础上再进行扩展,可以实现几乎所有的区间类查询
为了便于操作,有一个配置项single,这个配置项的作用是控制提交表单时是提交一个参数还是提交两个参数,当提交一个参数时,这两个日期的值以一个分隔符分隔,当以两个参数提交时就如同其它组件一样