/*! * Ext JS Library 3.3.1 * Copyright(c) 2006-2010 Sencha Inc. * licensing@sencha.com * http://www.sencha.com/license */ /** * @class Ext.form.TwoDateField * @extends Ext.form.TriggerField * Provides a date input field with a {@link Ext.DatePicker} dropdown and automatic date validation. * @constructor * Create a new DateField * @param {Object} config * @xtype datefield */ Ext.form.TwoDateField = Ext.extend(Ext.form.TriggerField, { format : "Y-m-d", /** * @cfg {String} altFormats * Multiple date formats separated by "|" to try when parsing a user input value and it * does not match the defined format (defaults to * 'm/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j'). */ altFormats : "", /** * @cfg {String} disabledDaysText * The tooltip to display when the date falls on a disabled day (defaults to 'Disabled') */ disabledDaysText : "Disabled", /** * @cfg {String} disabledDatesText * The tooltip text to display when the date falls on a disabled date (defaults to 'Disabled') */ disabledDatesText : "Disabled", /** * @cfg {String} minText * The error text to display when the date in the cell is before {@link #minValue} (defaults to * 'The date in this field must be after {minValue}'). */ minText : "The date in this field must be equal to or after {0}", /** * @cfg {String} maxText * The error text to display when the date in the cell is after {@link #maxValue} (defaults to * 'The date in this field must be before {maxValue}'). */ maxText : "The date in this field must be equal to or before {0}", /** * @cfg {String} invalidText * The error text to display when the date in the field is invalid (defaults to * '{value} is not a valid date - it must be in the format {format}'). */ invalidText : "{0} 无效数据,格式必须是 Y-m-d -- Y-m-d", /** * @cfg {String} triggerClass * An additional CSS class used to style the trigger button. The trigger will always get the * class 'x-form-trigger' and triggerClass will be appended if specified * (defaults to 'x-form-date-trigger' which displays a calendar icon). */ triggerClass : 'x-form-date-trigger', /** * @cfg {Boolean} showToday * false to hide the footer area of the DatePicker containing the Today button and disable * the keyboard handler for spacebar that selects the current date (defaults to true). */ showToday : false, /** * @cfg {Number} startDay * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday) */ startDay : 0, // private defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"}, // in the absence of a time value, a default value of 12 noon will be used // (note: 12 noon was chosen because it steers well clear of all DST timezone changes) initTime: '12', // 24 hour format initTimeFormat: 'H', // start date value: {String} startDate: null, // end date value: {String} endDate: null, // select start date value: {Date} selectStartDate: null, // select end date value: {Date} selectEndDate: null, // Separator separator: ' -- ', initComponent : function(){ Ext.form.TwoDateField.superclass.initComponent.call(this); this.addEvents( /** * @event select * Fires when a date is selected via the date picker. * @param {Ext.form.TwoDateField} this * @param {Date} date The date that was selected */ 'select' ); this.disabledDatesRE = null; this.initDisabledDays(); }, initEvents: function() { Ext.form.TwoDateField.superclass.initEvents.call(this); this.keyNav = new Ext.KeyNav(this.el, { "down": function(e) { this.onTriggerClick(); }, scope: this, forceKeyDown: true }); }, // private initDisabledDays : function(){ if(this.disabledDates){ var dd = this.disabledDates, len = dd.length - 1, re = "(?:"; Ext.each(dd, function(d, i){ re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i]; if(i != len){ re += '|'; } }, this); this.disabledDatesRE = new RegExp(re + ')'); } }, /** * Replaces any existing disabled dates with new values and refreshes the DatePicker. * @param {Array} disabledDates An array of date strings (see the {@link #disabledDates} config * for details on supported values) used to disable a pattern of dates. */ setDisabledDates : function(dd){ this.disabledDates = dd; this.initDisabledDays(); if(this.menu){ this.menu.picker.setDisabledDates(this.disabledDatesRE); } }, /** * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker. * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} * config for details on supported values. */ setDisabledDays : function(dd){ this.disabledDays = dd; if(this.menu){ this.menu.picker.setDisabledDays(dd); } }, getErrors: function(value) { var errors = Ext.form.TwoDateField.superclass.getErrors.apply(this, arguments); if (value.length == 0) { return errors; } if (!this.validTwoDate(value)) { errors.push(String.format(this.invalidText, value)); return errors; } return errors; }, // private // Provides logic to override the default TriggerField.validateBlur which just returns true validateBlur : function(){ return !this.menu || !this.menu.isVisible(); }, getValue : function(){ var start = this.formatDate(this.getStartValue()); var end = this.formatDate(this.getEndValue()); this.value = start + this.separator + end; if (start.length == 0 && end.length == 0) { this.value = ''; } return this.value;//--需要改造 }, setValue : function(text){ //清空开始、结束日期值 if (!text || text.length == 0) { this.startDate = null; this.endDate = null; } //校验数据格式合法性 [Y-m-d] -- [Y-m-d] this.originalValue = text; return Ext.form.TwoDateField.superclass.setValue.call(this, text);//--需要改造 }, getStartValue: function(){ return this.parseDate(this.startDate); }, getEndValue: function(){ return this.parseDate(this.endDate); }, // private parseDate : function(value) { if(!value || Ext.isDate(value)){ return value; } var v = this.safeParse(value, this.format), af = this.altFormats, afa = this.altFormatsArray; if (!v && af) { afa = afa || af.split("|"); for (var i = 0, len = afa.length; i < len && !v; i++) { v = this.safeParse(value, afa[i]); } } return v; }, safeParse : function(value, format) { if (/[gGhH]/.test(format.replace(/(\\.)/g, ''))) { // if parse format contains hour information, no DST adjustment is necessary return Date.parseDate(value, format); } else { // set time to 12 noon, then clear the time var parsedDate = Date.parseDate(value + ' ' + this.initTime, format + ' ' + this.initTimeFormat); if (parsedDate) { return parsedDate.clearTime(); } } }, // private onDestroy : function(){ Ext.destroy(this.menu, this.keyNav); Ext.form.TwoDateField.superclass.onDestroy.call(this); }, // private formatDate : function(date){ if (!date) return ''; return Ext.isDate(date) ? date.dateFormat(this.format) : date; }, /** * @method onTriggerClick * @hide */ onTriggerClick : function(){ if(this.disabled){ return; } if(this.menu == null){ this.menu = new Ext.menu.TwoDateMenu({ hideOnClick: false, focusOnSelect: false }); } this.onFocus(); Ext.apply(this.menu.picker, { minDate : this.minValue, maxDate : this.maxValue, disabledDatesRE : this.disabledDatesRE, disabledDatesText : this.disabledDatesText, disabledDays : this.disabledDays, disabledDaysText : this.disabledDaysText, format : this.format, showToday : this.showToday, startDay: this.startDay, minText : String.format(this.minText, this.formatDate(this.minValue)), maxText : String.format(this.maxText, this.formatDate(this.maxValue)) }); Ext.apply(this.menu.two_picker, { minDate : this.minValue, maxDate : this.maxValue, disabledDatesRE : this.disabledDatesRE, disabledDatesText : this.disabledDatesText, disabledDays : this.disabledDays, disabledDaysText : this.disabledDaysText, format : this.format, showToday : this.showToday, startDay: this.startDay, minText : String.format(this.minText, this.formatDate(this.minValue)), maxText : String.format(this.maxText, this.formatDate(this.maxValue)) }); //每次打开选择区时,都清空选择日期值 this.selectStartDate = null; this.selectEndDate = null; //给开始控件与结束控件赋值 this.initTwoDate(); //给日期范围设置背景色 this.styleTwoDate(); this.menu.show(this.el, "tl-bl?"); this.menuEvents('on'); }, //private 初始化2个日期控件的值 // 如果两个日期是同一个月,则都显示在第一个日期控件;否则分开显示 initTwoDate: function() { var startDate = this.getStartValue(); if (!startDate) startDate = new Date(); var endDate = this.getEndValue(); //如果是同月,就显示在一个日期控件中 if (endDate && startDate.format('Y-m') == endDate.format('Y-m')) { this.menu.picker.setValue(startDate); this.menu.picker.setTwoValue(endDate); //清空选择日期标记 this.menu.two_picker.cells.removeClass('x-date-selected'); } else { if (startDate) this.menu.picker.setValue(startDate); if (!endDate) { endDate = (new Date()).add(Date.MONTH, 1); this.menu.two_picker.setValue(endDate);//设定为第二个月,但不显示标记 JxUtil.delay(20, function(){this.menu.two_picker.cells.removeClass('x-date-selected');}, this); } else { this.menu.two_picker.setValue(endDate); } } }, //private menuEvents: function(method){ this.menu[method]('select', this.onSelect, this); this.menu[method]('hide', this.onMenuHide, this); this.menu[method]('show', this.onFocus, this); }, //private 给日期范围设置背景色 styleTwoDate: function(){ if (this.menu.picker.cells) this.menu.picker.cells.removeClass('x-date-seltwo'); if (this.menu.two_picker.cells) this.menu.two_picker.cells.removeClass('x-date-seltwo'); var startDate = this.getStartValue(); var endDate = this.getEndValue(); if (!startDate || !endDate) return; //给一个日期添加背景色 var addcss = function(cells, t){ cells.each(function(c){ if(c.dom.firstChild.dateValue == t){ c.addClass('x-date-seltwo'); return false; } }); }; if (startDate.format('Y-m') == endDate.format('Y-m')) { //第一个日期控件添加背景色 var sd = startDate.add(Date.DAY, 1); while (sd.getTime() < endDate.getTime()) { addcss(this.menu.picker.cells, sd.getTime()); sd = sd.add(Date.DAY, 1); } } else { //显示第一个日期控件的背景色 var next = JxUtil.getNextMonth(startDate.format('Y-m'), 1); var ed = this.parseDate(next + '-01'); var sd = startDate.add(Date.DAY, 1); while (sd.getTime() < ed.getTime()) { addcss(this.menu.picker.cells, sd.getTime()); sd = sd.add(Date.DAY, 1); } //显示第二个日期控件的背景色 sd = this.parseDate(endDate.format('Y-m') + '-01'); while (sd.getTime() < endDate.getTime()) { addcss(this.menu.two_picker.cells, sd.getTime()); sd = sd.add(Date.DAY, 1); } } }, //private 点击范围按钮时,自动设置开始、结束日期 setTwoDate: function(btntype){ if (btntype == 'week') {//本周 var wd = JxUtil.getWeekDates(); this.startDate = wd[0]; this.endDate = wd[1]; } else if (btntype == 'month') {//本月 var md = JxUtil.getMonthDates(); this.startDate = md[0]; this.endDate = md[1]; } else if (btntype == 'quarter') {//3个月 var smonth = JxUtil.getMonth(); var sd = JxUtil.getNextMonth(smonth, -2) + '-01'; this.startDate = sd; this.endDate = JxUtil.getToday(); } else if (btntype == 'year') {//本年 var y = (new Date()).format('Y'); this.startDate = y+'-01'+'-01'; this.endDate = JxUtil.getToday(); } else if (btntype == 'preweek') {//上周 var md = JxUtil.getPreWeekDates(); this.startDate = md[0]; this.endDate = md[1]; } else if (btntype == 'premonth') {//上月 var md = JxUtil.getPreMonthDates(); this.startDate = md[0]; this.endDate = md[1]; } var text = this.startDate + this.separator + this.endDate; this.setValue(text); this.menu.hide(); }, onSelect: function(m, d){ //点击按钮选择日期范围 if (m.getXType() == 'button') { var btntype = m.getItemId(); this.setTwoDate(btntype); return; } if (this.menu.picker.cells) this.menu.picker.cells.removeClass('x-date-seltwo'); if (this.menu.two_picker.cells) this.menu.two_picker.cells.removeClass('x-date-seltwo'); if (!this.selectStartDate) { this.selectStartDate = d; //第1次点选时,要清空另一个选择日期标记 if (m.id == this.menu.picker.id) { this.menu.two_picker.cells.removeClass('x-date-selected'); } else { this.menu.picker.cells.removeClass('x-date-selected'); } } else { //第二次选择日期时,则赋值并隐藏选择块 //小的日期值放在start,大的日期值放在end if (d.getTime() < this.selectStartDate.getTime()) { this.selectEndDate = this.selectStartDate; this.selectStartDate = d; } else { this.selectEndDate = d; } this.startDate = this.formatDate(this.selectStartDate); this.endDate = this.formatDate(this.selectEndDate); var text = this.startDate + this.separator + this.endDate; this.setValue(text); this.fireEvent('select', this, d); this.menu.hide(); } }, onMenuHide: function(){ this.focus(false, 60); this.menuEvents('un'); }, // private 格式化2个日期值,格式不对清空 validTwoDate: function(value){ if (value == null || value.length == 0) return true; if (value && value.length > 0) { var values = value.split(this.separator); if (values && values.length == 2) { this.startDate = this.formatDate(this.parseDate(values[0].trim())); this.endDate = this.formatDate(this.parseDate(values[1].trim())); if (this.startDate.length > 0 && this.endDate.length > 0) { return true; } } } return false; }, // private beforeBlur : function(){ var value = this.getRawValue(); if (this.validTwoDate(value)) { this.setValue(value); } else { this.setValue(this.originalValue); } } }); Ext.reg('twodatefield', Ext.form.TwoDateField);