messengercustom-servicesmacoslinuxwindowsinboxwhatsappicloudtweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscord
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1330 lines
40 KiB
1330 lines
40 KiB
9 years ago
|
/**
|
||
|
* A date picker. This class is used by the Ext.form.field.Date field to allow browsing and selection of valid
|
||
|
* dates in a popup next to the field, but may also be used with other components.
|
||
|
*
|
||
|
* Typically you will need to implement a handler function to be notified when the user chooses a date from the picker;
|
||
|
* you can register the handler using the {@link #select} event, or by implementing the {@link #handler} method.
|
||
|
*
|
||
|
* By default the user will be allowed to pick any date; this can be changed by using the {@link #minDate},
|
||
|
* {@link #maxDate}, {@link #disabledDays}, {@link #disabledDatesRE}, and/or {@link #disabledDates} configs.
|
||
|
*
|
||
|
* All the string values documented below may be overridden by including an Ext locale file in your page.
|
||
|
*
|
||
|
* @example
|
||
|
* Ext.create('Ext.panel.Panel', {
|
||
|
* title: 'Choose a future date:',
|
||
|
* width: 200,
|
||
|
* bodyPadding: 10,
|
||
|
* renderTo: Ext.getBody(),
|
||
|
* items: [{
|
||
|
* xtype: 'datepicker',
|
||
|
* minDate: new Date(),
|
||
|
* handler: function(picker, date) {
|
||
|
* // do something with the selected date
|
||
|
* }
|
||
|
* }]
|
||
|
* });
|
||
|
*/
|
||
|
Ext.define('Ext.picker.Date', {
|
||
|
extend: 'Ext.Component',
|
||
|
requires: [
|
||
|
'Ext.XTemplate',
|
||
|
'Ext.button.Button',
|
||
|
'Ext.button.Split',
|
||
|
'Ext.util.ClickRepeater',
|
||
|
'Ext.util.KeyNav',
|
||
|
'Ext.fx.Manager',
|
||
|
'Ext.picker.Month'
|
||
|
],
|
||
|
alias: 'widget.datepicker',
|
||
|
alternateClassName: 'Ext.DatePicker',
|
||
|
|
||
|
isDatePicker: true,
|
||
|
|
||
|
focusable: true,
|
||
|
|
||
|
childEls: [
|
||
|
'innerEl', 'eventEl', 'prevEl', 'nextEl', 'middleBtnEl', 'footerEl'
|
||
|
],
|
||
|
|
||
|
border: true,
|
||
|
|
||
|
/**
|
||
|
* @cfg
|
||
|
* @inheritdoc
|
||
|
*/
|
||
|
renderTpl: [
|
||
|
'<div id="{id}-innerEl" data-ref="innerEl">',
|
||
|
'<div class="{baseCls}-header">',
|
||
|
'<div id="{id}-prevEl" data-ref="prevEl" class="{baseCls}-prev {baseCls}-arrow" role="button" title="{prevText}"></div>',
|
||
|
'<div id="{id}-middleBtnEl" data-ref="middleBtnEl" class="{baseCls}-month" role="heading">{%this.renderMonthBtn(values, out)%}</div>',
|
||
|
'<div id="{id}-nextEl" data-ref="nextEl" class="{baseCls}-next {baseCls}-arrow" role="button" title="{nextText}"></div>',
|
||
|
'</div>',
|
||
|
'<table role="grid" id="{id}-eventEl" data-ref="eventEl" class="{baseCls}-inner" {%',
|
||
|
// If the DatePicker is focusable, make its eventEl tabbable.
|
||
|
// Note that we're looking at the `focusable` property because
|
||
|
// calling `isFocusable()` will always return false at that point
|
||
|
// as the picker is not yet rendered.
|
||
|
'if (values.$comp.focusable) {out.push("tabindex=\\\"0\\\"");}',
|
||
|
'%} cellspacing="0">',
|
||
|
'<thead><tr role="row">',
|
||
|
'<tpl for="dayNames">',
|
||
|
'<th role="columnheader" class="{parent.baseCls}-column-header" aria-label="{.}">',
|
||
|
'<div role="presentation" class="{parent.baseCls}-column-header-inner">{.:this.firstInitial}</div>',
|
||
|
'</th>',
|
||
|
'</tpl>',
|
||
|
'</tr></thead>',
|
||
|
'<tbody><tr role="row">',
|
||
|
'<tpl for="days">',
|
||
|
'{#:this.isEndOfWeek}',
|
||
|
'<td role="gridcell">',
|
||
|
'<div hidefocus="on" class="{parent.baseCls}-date"></div>',
|
||
|
'</td>',
|
||
|
'</tpl>',
|
||
|
'</tr></tbody>',
|
||
|
'</table>',
|
||
|
'<tpl if="showToday">',
|
||
|
'<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer">{%this.renderTodayBtn(values, out)%}</div>',
|
||
|
'</tpl>',
|
||
|
'</div>',
|
||
|
{
|
||
|
firstInitial: function(value) {
|
||
|
return Ext.picker.Date.prototype.getDayInitial(value);
|
||
|
},
|
||
|
isEndOfWeek: function(value) {
|
||
|
// convert from 1 based index to 0 based
|
||
|
// by decrementing value once.
|
||
|
value--;
|
||
|
var end = value % 7 === 0 && value !== 0;
|
||
|
return end ? '</tr><tr role="row">' : '';
|
||
|
},
|
||
|
renderTodayBtn: function(values, out) {
|
||
|
Ext.DomHelper.generateMarkup(values.$comp.todayBtn.getRenderTree(), out);
|
||
|
},
|
||
|
renderMonthBtn: function(values, out) {
|
||
|
Ext.DomHelper.generateMarkup(values.$comp.monthBtn.getRenderTree(), out);
|
||
|
}
|
||
|
}
|
||
|
],
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} todayText
|
||
|
* The text to display on the button that selects the current date
|
||
|
*/
|
||
|
todayText: 'Today',
|
||
|
//</locale>
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} ariaTitle
|
||
|
* The text to display for the aria title
|
||
|
*/
|
||
|
ariaTitle: 'Date Picker: {0}',
|
||
|
//</locale>
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} ariaTitleDateFormat
|
||
|
* The date format to display for the current value in the {@link #ariaTitle}
|
||
|
*/
|
||
|
ariaTitleDateFormat: 'F d',
|
||
|
//</locale>
|
||
|
|
||
|
/**
|
||
|
* @cfg {Function} handler
|
||
|
* Optional. A function that will handle the select event of this picker. The handler is passed the following
|
||
|
* parameters:
|
||
|
*
|
||
|
* - `picker` : Ext.picker.Date
|
||
|
*
|
||
|
* This Date picker.
|
||
|
*
|
||
|
* - `date` : Date
|
||
|
*
|
||
|
* The selected date.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @cfg {Object} scope
|
||
|
* The scope (`this` reference) in which the `{@link #handler}` function will be called.
|
||
|
*
|
||
|
* Defaults to this DatePicker instance.
|
||
|
*/
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} todayTip
|
||
|
* A string used to format the message for displaying in a tooltip over the button that selects the current date.
|
||
|
* The `{0}` token in string is replaced by today's date.
|
||
|
*/
|
||
|
todayTip: '{0} (Spacebar)',
|
||
|
//</locale>
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} minText
|
||
|
* The error text to display if the minDate validation fails.
|
||
|
*/
|
||
|
minText: 'This date is before the minimum date',
|
||
|
//</locale>
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} maxText
|
||
|
* The error text to display if the maxDate validation fails.
|
||
|
*/
|
||
|
maxText: 'This date is after the maximum date',
|
||
|
//</locale>
|
||
|
|
||
|
/**
|
||
|
* @cfg {String} format
|
||
|
* The default date format string which can be overriden for localization support. The format must be valid
|
||
|
* according to {@link Ext.Date#parse} (defaults to {@link Ext.Date#defaultFormat}).
|
||
|
*/
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} disabledDaysText
|
||
|
* The tooltip to display when the date falls on a disabled day.
|
||
|
*/
|
||
|
disabledDaysText: 'Disabled',
|
||
|
//</locale>
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} disabledDatesText
|
||
|
* The tooltip text to display when the date falls on a disabled date.
|
||
|
*/
|
||
|
disabledDatesText: 'Disabled',
|
||
|
//</locale>
|
||
|
|
||
|
/**
|
||
|
* @cfg {String[]} monthNames
|
||
|
* An array of textual month names which can be overriden for localization support (defaults to Ext.Date.monthNames)
|
||
|
* @deprecated This config is deprecated. In future the month names will be retrieved from {@link Ext.Date}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @cfg {String[]} dayNames
|
||
|
* An array of textual day names which can be overriden for localization support (defaults to Ext.Date.dayNames)
|
||
|
* @deprecated This config is deprecated. In future the day names will be retrieved from {@link Ext.Date}
|
||
|
*/
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} nextText
|
||
|
* The next month navigation button tooltip
|
||
|
*/
|
||
|
nextText: 'Next Month (Control+Right)',
|
||
|
//</locale>
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} prevText
|
||
|
* The previous month navigation button tooltip
|
||
|
*/
|
||
|
prevText: 'Previous Month (Control+Left)',
|
||
|
//</locale>
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} monthYearText
|
||
|
* The header month selector tooltip
|
||
|
*/
|
||
|
monthYearText: 'Choose a month (Control+Up/Down to move years)',
|
||
|
//</locale>
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} monthYearFormat
|
||
|
* The date format for the header month
|
||
|
*/
|
||
|
monthYearFormat: 'F Y',
|
||
|
//</locale>
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {Number} [startDay=undefined]
|
||
|
* Day index at which the week should begin, 0-based.
|
||
|
*
|
||
|
* Defaults to `0` (Sunday).
|
||
|
*/
|
||
|
startDay: 0,
|
||
|
//</locale>
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {Boolean} showToday
|
||
|
* False to hide the footer area containing the Today button and disable the keyboard handler for spacebar that
|
||
|
* selects the current date.
|
||
|
*/
|
||
|
showToday: true,
|
||
|
//</locale>
|
||
|
|
||
|
/**
|
||
|
* @cfg {Date} [minDate=null]
|
||
|
* Minimum allowable date (JavaScript date object)
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @cfg {Date} [maxDate=null]
|
||
|
* Maximum allowable date (JavaScript date object)
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @cfg {Number[]} [disabledDays=null]
|
||
|
* An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @cfg {RegExp} [disabledDatesRE=null]
|
||
|
* JavaScript regular expression used to disable a pattern of dates. The {@link #disabledDates}
|
||
|
* config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
|
||
|
* disabledDates value.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @cfg {String[]} disabledDates
|
||
|
* An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular expression so
|
||
|
* they are very powerful. Some examples:
|
||
|
*
|
||
|
* - ['03/08/2003', '09/16/2003'] would disable those exact dates
|
||
|
* - ['03/08', '09/16'] would disable those days for every year
|
||
|
* - ['^03/08'] would only match the beginning (useful if you are using short years)
|
||
|
* - ['03/../2006'] would disable every day in March 2006
|
||
|
* - ['^03'] would disable every day in every March
|
||
|
*
|
||
|
* Note that the format of the dates included in the array should exactly match the {@link #format} config. In order
|
||
|
* to support regular expressions, if you are using a date format that has '.' in it, you will have to escape the
|
||
|
* dot when restricting dates. For example: ['03\\.08\\.03'].
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @cfg {Boolean} disableAnim
|
||
|
* True to disable animations when showing the month picker.
|
||
|
*/
|
||
|
disableAnim: false,
|
||
|
|
||
|
/**
|
||
|
* @cfg {String} [baseCls='x-datepicker']
|
||
|
* The base CSS class to apply to this components element.
|
||
|
*/
|
||
|
baseCls: Ext.baseCSSPrefix + 'datepicker',
|
||
|
|
||
|
/**
|
||
|
* @cfg {String} [selectedCls='x-datepicker-selected']
|
||
|
* The class to apply to the selected cell.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @cfg {String} [disabledCellCls='x-datepicker-disabled']
|
||
|
* The class to apply to disabled cells.
|
||
|
*/
|
||
|
|
||
|
//<locale>
|
||
|
/**
|
||
|
* @cfg {String} longDayFormat
|
||
|
* The format for displaying a date in a longer format.
|
||
|
*/
|
||
|
longDayFormat: 'F d, Y',
|
||
|
//</locale>
|
||
|
|
||
|
/**
|
||
|
* @cfg {Object} keyNavConfig
|
||
|
* Specifies optional custom key event handlers for the {@link Ext.util.KeyNav} attached to this date picker. Must
|
||
|
* conform to the config format recognized by the {@link Ext.util.KeyNav} constructor. Handlers specified in this
|
||
|
* object will replace default handlers of the same name.
|
||
|
*/
|
||
|
|
||
|
// Default value used to initialise each date in the DatePicker.
|
||
|
// __Note:__ 12 noon was chosen because it steers well clear of all DST timezone changes.
|
||
|
initHour: 12, // 24-hour format
|
||
|
|
||
|
numDays: 42,
|
||
|
|
||
|
/**
|
||
|
* @event select
|
||
|
* Fires when a date is selected
|
||
|
* @param {Ext.picker.Date} this DatePicker
|
||
|
* @param {Date} date The selected date
|
||
|
*/
|
||
|
|
||
|
// private, inherit docs
|
||
|
initComponent: function() {
|
||
|
var me = this,
|
||
|
clearTime = Ext.Date.clearTime;
|
||
|
|
||
|
me.selectedCls = me.baseCls + '-selected';
|
||
|
me.disabledCellCls = me.baseCls + '-disabled';
|
||
|
me.prevCls = me.baseCls + '-prevday';
|
||
|
me.activeCls = me.baseCls + '-active';
|
||
|
me.cellCls = me.baseCls + '-cell';
|
||
|
me.nextCls = me.baseCls + '-prevday';
|
||
|
me.todayCls = me.baseCls + '-today';
|
||
|
|
||
|
|
||
|
if (!me.format) {
|
||
|
me.format = Ext.Date.defaultFormat;
|
||
|
}
|
||
|
if (!me.dayNames) {
|
||
|
me.dayNames = Ext.Date.dayNames;
|
||
|
}
|
||
|
me.dayNames = me.dayNames.slice(me.startDay).concat(me.dayNames.slice(0, me.startDay));
|
||
|
|
||
|
me.callParent();
|
||
|
|
||
|
me.value = me.value ? clearTime(me.value, true) : clearTime(new Date());
|
||
|
|
||
|
me.initDisabledDays();
|
||
|
},
|
||
|
|
||
|
// Keep the tree structure correct for Ext.form.field.Picker input fields which poke a 'pickerField' reference down into their pop-up pickers.
|
||
|
getRefOwner: function() {
|
||
|
return this.pickerField || this.callParent();
|
||
|
},
|
||
|
|
||
|
getRefItems: function() {
|
||
|
var results = [],
|
||
|
monthBtn = this.monthBtn,
|
||
|
todayBtn = this.todayBtn;
|
||
|
|
||
|
if (monthBtn) {
|
||
|
results.push(monthBtn);
|
||
|
}
|
||
|
|
||
|
if (todayBtn) {
|
||
|
results.push(todayBtn);
|
||
|
}
|
||
|
return results;
|
||
|
},
|
||
|
|
||
|
beforeRender: function() {
|
||
|
/*
|
||
|
* days array for looping through 6 full weeks (6 weeks * 7 days)
|
||
|
* Note that we explicitly force the size here so the template creates
|
||
|
* all the appropriate cells.
|
||
|
*/
|
||
|
var me = this,
|
||
|
days = new Array(me.numDays),
|
||
|
today = Ext.Date.format(new Date(), me.format);
|
||
|
|
||
|
if (me.padding && !me.width) {
|
||
|
me.cacheWidth();
|
||
|
}
|
||
|
|
||
|
me.monthBtn = new Ext.button.Split({
|
||
|
ownerCt: me,
|
||
|
ownerLayout: me.getComponentLayout(),
|
||
|
text: '',
|
||
|
tooltip: me.monthYearText,
|
||
|
listeners: {
|
||
|
click: me.doShowMonthPicker,
|
||
|
arrowclick: me.doShowMonthPicker,
|
||
|
scope: me
|
||
|
}
|
||
|
});
|
||
|
|
||
|
if (me.showToday) {
|
||
|
me.todayBtn = new Ext.button.Button({
|
||
|
ownerCt: me,
|
||
|
ownerLayout: me.getComponentLayout(),
|
||
|
text: Ext.String.format(me.todayText, today),
|
||
|
tooltip: Ext.String.format(me.todayTip, today),
|
||
|
tooltipType: 'title',
|
||
|
handler: me.selectToday,
|
||
|
scope: me
|
||
|
});
|
||
|
}
|
||
|
|
||
|
me.callParent();
|
||
|
|
||
|
Ext.applyIf(me, {
|
||
|
renderData: {}
|
||
|
});
|
||
|
|
||
|
Ext.apply(me.renderData, {
|
||
|
dayNames: me.dayNames,
|
||
|
showToday: me.showToday,
|
||
|
prevText: me.prevText,
|
||
|
nextText: me.nextText,
|
||
|
days: days
|
||
|
});
|
||
|
|
||
|
me.protoEl.unselectable();
|
||
|
},
|
||
|
|
||
|
cacheWidth: function() {
|
||
|
var me = this,
|
||
|
padding = me.parseBox(me.padding),
|
||
|
widthEl = Ext.getBody().createChild({
|
||
|
cls: me.baseCls + ' ' + me.borderBoxCls,
|
||
|
style: 'position:absolute;top:-1000px;left:-1000px;'
|
||
|
});
|
||
|
|
||
|
me.self.prototype.width = widthEl.getWidth() + padding.left + padding.right;
|
||
|
widthEl.destroy();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @inheritdoc
|
||
|
* @private
|
||
|
*/
|
||
|
onRender: function(container, position) {
|
||
|
var me = this;
|
||
|
|
||
|
me.callParent(arguments);
|
||
|
|
||
|
me.cells = me.eventEl.select('tbody td');
|
||
|
me.textNodes = me.eventEl.query('tbody td div');
|
||
|
|
||
|
me.eventEl.set({ 'aria-labelledby': me.monthBtn.id });
|
||
|
|
||
|
me.mon(me.eventEl, {
|
||
|
scope: me,
|
||
|
mousewheel: me.handleMouseWheel,
|
||
|
click: {
|
||
|
fn: me.handleDateClick,
|
||
|
delegate: 'div.' + me.baseCls + '-date'
|
||
|
}
|
||
|
});
|
||
|
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @inheritdoc
|
||
|
* @private
|
||
|
*/
|
||
|
initEvents: function(){
|
||
|
var me = this,
|
||
|
pickerField = me.pickerField,
|
||
|
eDate = Ext.Date,
|
||
|
day = eDate.DAY;
|
||
|
|
||
|
me.callParent();
|
||
|
|
||
|
// If this is not focusable (eg being used as the picker of a DateField)
|
||
|
// then prevent mousedown from blurring the input field.
|
||
|
if (!me.focusable) {
|
||
|
me.el.on({
|
||
|
mousedown: me.onMouseDown
|
||
|
});
|
||
|
}
|
||
|
|
||
|
me.prevRepeater = new Ext.util.ClickRepeater(me.prevEl, {
|
||
|
handler: me.showPrevMonth,
|
||
|
scope: me,
|
||
|
preventDefault: true,
|
||
|
stopDefault: true
|
||
|
});
|
||
|
|
||
|
me.nextRepeater = new Ext.util.ClickRepeater(me.nextEl, {
|
||
|
handler: me.showNextMonth,
|
||
|
scope: me,
|
||
|
preventDefault: true,
|
||
|
stopDefault: true
|
||
|
});
|
||
|
|
||
|
// Read key events through our pickerField if we are bound to one
|
||
|
me.keyNav = new Ext.util.KeyNav(pickerField ? pickerField.inputEl : me.eventEl, Ext.apply({
|
||
|
scope: me,
|
||
|
|
||
|
// Must capture event so that the Picker sees it before the Field.
|
||
|
capture: true,
|
||
|
|
||
|
left: function(e) {
|
||
|
if (e.ctrlKey) {
|
||
|
me.showPrevMonth();
|
||
|
} else {
|
||
|
me.update(eDate.add(me.activeDate, day, -1));
|
||
|
}
|
||
|
},
|
||
|
|
||
|
right: function(e){
|
||
|
if (e.ctrlKey) {
|
||
|
me.showNextMonth();
|
||
|
} else {
|
||
|
me.update(eDate.add(me.activeDate, day, 1));
|
||
|
}
|
||
|
},
|
||
|
|
||
|
up: function(e) {
|
||
|
if (e.ctrlKey) {
|
||
|
me.showNextYear();
|
||
|
} else {
|
||
|
me.update(eDate.add(me.activeDate, day, -7));
|
||
|
}
|
||
|
},
|
||
|
|
||
|
down: function(e) {
|
||
|
if (e.ctrlKey) {
|
||
|
me.showPrevYear();
|
||
|
} else {
|
||
|
me.update(eDate.add(me.activeDate, day, 7));
|
||
|
}
|
||
|
},
|
||
|
|
||
|
pageUp: function(e) {
|
||
|
if (e.ctrlKey) {
|
||
|
me.showPrevYear();
|
||
|
} else {
|
||
|
me.showPrevMonth();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
pageDown: function(e) {
|
||
|
if (e.ctrlKey) {
|
||
|
me.showNextYear();
|
||
|
} else {
|
||
|
me.showNextMonth();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
tab: function (e) {
|
||
|
me.handleTabClick(e);
|
||
|
|
||
|
// Allow default behaviour of TAB - it MUST be allowed to navigate.
|
||
|
return true;
|
||
|
},
|
||
|
|
||
|
enter: function(e) {
|
||
|
me.handleDateClick(e, me.activeCell.firstChild);
|
||
|
},
|
||
|
|
||
|
space: function() {
|
||
|
me.setValue(new Date(me.activeCell.firstChild.dateValue));
|
||
|
var startValue = me.startValue,
|
||
|
value = me.value,
|
||
|
pickerValue;
|
||
|
|
||
|
if (pickerField) {
|
||
|
pickerValue = pickerField.getValue();
|
||
|
if (pickerValue && startValue && pickerValue.getTime() === value.getTime()) {
|
||
|
pickerField.setValue(startValue);
|
||
|
} else {
|
||
|
pickerField.setValue(value);
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
home: function(e) {
|
||
|
me.update(eDate.getFirstDateOfMonth(me.activeDate));
|
||
|
},
|
||
|
|
||
|
end: function(e) {
|
||
|
me.update(eDate.getLastDateOfMonth(me.activeDate));
|
||
|
}
|
||
|
}, me.keyNavConfig));
|
||
|
|
||
|
if (me.disabled) {
|
||
|
me.syncDisabled(true);
|
||
|
}
|
||
|
me.update(me.value);
|
||
|
},
|
||
|
|
||
|
onMouseDown: function(e) {
|
||
|
e.preventDefault();
|
||
|
},
|
||
|
|
||
|
handleTabClick: function (e) {
|
||
|
var me = this,
|
||
|
t = me.getSelectedDate(me.activeDate),
|
||
|
handler = me.handler;
|
||
|
|
||
|
// The following code is like handleDateClick without the e.stopEvent()
|
||
|
if (!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)) {
|
||
|
me.setValue(new Date(t.dateValue));
|
||
|
me.fireEvent('select', me, me.value);
|
||
|
if (handler) {
|
||
|
handler.call(me.scope || me, me, me.value);
|
||
|
}
|
||
|
me.onSelect();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
getSelectedDate: function (date) {
|
||
|
var me = this,
|
||
|
t = date.getTime(),
|
||
|
cells = me.cells,
|
||
|
cls = me.selectedCls,
|
||
|
cellItems = cells.elements,
|
||
|
cLen = cellItems.length,
|
||
|
cell, c;
|
||
|
|
||
|
cells.removeCls(cls);
|
||
|
|
||
|
for (c = 0; c < cLen; c++) {
|
||
|
cell = cellItems[c].firstChild;
|
||
|
if (cell.dateValue === t) {
|
||
|
return cell;
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Setup the disabled dates regex based on config options
|
||
|
* @private
|
||
|
*/
|
||
|
initDisabledDays: function() {
|
||
|
var me = this,
|
||
|
dd = me.disabledDates,
|
||
|
re = '(?:',
|
||
|
len,
|
||
|
d, dLen, dI;
|
||
|
|
||
|
if(!me.disabledDatesRE && dd){
|
||
|
len = dd.length - 1;
|
||
|
|
||
|
dLen = dd.length;
|
||
|
|
||
|
for (d = 0; d < dLen; d++) {
|
||
|
dI = dd[d];
|
||
|
|
||
|
re += Ext.isDate(dI) ? '^' + Ext.String.escapeRegex(Ext.Date.dateFormat(dI, me.format)) + '$' : dI;
|
||
|
if (d !== len) {
|
||
|
re += '|';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
me.disabledDatesRE = new RegExp(re + ')');
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Replaces any existing disabled dates with new values and refreshes the DatePicker.
|
||
|
* @param {String[]/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config for
|
||
|
* details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
setDisabledDates: function(dd) {
|
||
|
var me = this;
|
||
|
|
||
|
if (Ext.isArray(dd)) {
|
||
|
me.disabledDates = dd;
|
||
|
me.disabledDatesRE = null;
|
||
|
} else {
|
||
|
me.disabledDatesRE = dd;
|
||
|
}
|
||
|
me.initDisabledDays();
|
||
|
me.update(me.value, true);
|
||
|
return me;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
|
||
|
* @param {Number[]} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config for details
|
||
|
* on supported values.
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
setDisabledDays: function(dd) {
|
||
|
this.disabledDays = dd;
|
||
|
return this.update(this.value, true);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
|
||
|
* @param {Date} value The minimum date that can be selected
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
setMinDate: function(dt) {
|
||
|
this.minDate = dt;
|
||
|
return this.update(this.value, true);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
|
||
|
* @param {Date} value The maximum date that can be selected
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
setMaxDate: function(dt) {
|
||
|
this.maxDate = dt;
|
||
|
return this.update(this.value, true);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Sets the value of the date field
|
||
|
* @param {Date} value The date to set
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
setValue: function(value) {
|
||
|
// If passed a null value just pass in a new date object.
|
||
|
this.value = Ext.Date.clearTime(value || new Date(), true);
|
||
|
return this.update(this.value);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Gets the current selected value of the date field
|
||
|
* @return {Date} The selected date
|
||
|
*/
|
||
|
getValue: function() {
|
||
|
return this.value;
|
||
|
},
|
||
|
|
||
|
//<locale type="function">
|
||
|
/**
|
||
|
* Gets a single character to represent the day of the week
|
||
|
* @return {String} The character
|
||
|
*/
|
||
|
getDayInitial: function(value) {
|
||
|
return value.substr(0,1);
|
||
|
},
|
||
|
//</locale>
|
||
|
|
||
|
/**
|
||
|
* @inheritdoc
|
||
|
* @private
|
||
|
*/
|
||
|
onEnable: function() {
|
||
|
var me = this;
|
||
|
|
||
|
me.callParent();
|
||
|
me.syncDisabled(false);
|
||
|
me.update(me.activeDate);
|
||
|
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @inheritdoc
|
||
|
* @private
|
||
|
*/
|
||
|
onShow: function() {
|
||
|
var me = this;
|
||
|
|
||
|
me.callParent();
|
||
|
me.syncDisabled(false);
|
||
|
if (me.pickerField) {
|
||
|
me.startValue = me.pickerField.getValue();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @inheritdoc
|
||
|
* @private
|
||
|
*/
|
||
|
onHide: function() {
|
||
|
this.callParent();
|
||
|
this.syncDisabled(true);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @inheritdoc
|
||
|
* @private
|
||
|
*/
|
||
|
onDisable: function() {
|
||
|
this.callParent();
|
||
|
this.syncDisabled(true);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Get the current active date.
|
||
|
* @private
|
||
|
* @return {Date} The active date
|
||
|
*/
|
||
|
getActive: function(){
|
||
|
return this.activeDate || this.value;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Run any animation required to hide/show the month picker.
|
||
|
* @private
|
||
|
* @param {Boolean} isHide True if it's a hide operation
|
||
|
*/
|
||
|
runAnimation: function(isHide){
|
||
|
var picker = this.monthPicker,
|
||
|
options = {
|
||
|
duration: 200,
|
||
|
callback: function() {
|
||
|
picker.setVisible(!isHide);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if (isHide) {
|
||
|
picker.el.slideOut('t', options);
|
||
|
} else {
|
||
|
picker.el.slideIn('t', options);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Hides the month picker, if it's visible.
|
||
|
* @param {Boolean} [animate] Indicates whether to animate this action. If the animate
|
||
|
* parameter is not specified, the behavior will use {@link #disableAnim} to determine
|
||
|
* whether to animate or not.
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
hideMonthPicker: function(animate){
|
||
|
var me = this,
|
||
|
picker = me.monthPicker;
|
||
|
|
||
|
if (picker && picker.isVisible()) {
|
||
|
if (me.shouldAnimate(animate)) {
|
||
|
me.runAnimation(true);
|
||
|
} else {
|
||
|
picker.hide();
|
||
|
}
|
||
|
}
|
||
|
return me;
|
||
|
},
|
||
|
|
||
|
doShowMonthPicker: function(){
|
||
|
// Wrap in an extra call so we can prevent the button
|
||
|
// being passed as an animation parameter.
|
||
|
this.showMonthPicker();
|
||
|
},
|
||
|
|
||
|
doHideMonthPicker: function() {
|
||
|
// Wrap in an extra call so we can prevent this
|
||
|
// being passed as an animation parameter
|
||
|
this.hideMonthPicker();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Show the month picker
|
||
|
* @param {Boolean} [animate] Indicates whether to animate this action. If the animate
|
||
|
* parameter is not specified, the behavior will use {@link #disableAnim} to determine
|
||
|
* whether to animate or not.
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
showMonthPicker: function(animate) {
|
||
|
var me = this,
|
||
|
el = me.el,
|
||
|
picker;
|
||
|
|
||
|
if (me.rendered && !me.disabled) {
|
||
|
picker = me.createMonthPicker();
|
||
|
if (!picker.isVisible()) {
|
||
|
picker.setValue(me.getActive());
|
||
|
picker.setSize(el.getSize());
|
||
|
|
||
|
// Null out floatParent so that the [-1, -1] position is not made relative to this
|
||
|
picker.floatParent = null;
|
||
|
picker.setPosition(-el.getBorderWidth('l'), -el.getBorderWidth('t'));
|
||
|
if (me.shouldAnimate(animate)) {
|
||
|
me.runAnimation(false);
|
||
|
} else {
|
||
|
picker.show();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return me;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Checks whether a hide/show action should animate
|
||
|
* @private
|
||
|
* @param {Boolean} [animate] A possible animation value
|
||
|
* @return {Boolean} Whether to animate the action
|
||
|
*/
|
||
|
shouldAnimate: function(animate) {
|
||
|
return Ext.isDefined(animate) ? animate : !this.disableAnim;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Create the month picker instance
|
||
|
* @private
|
||
|
* @return {Ext.picker.Month} picker
|
||
|
*/
|
||
|
createMonthPicker: function() {
|
||
|
var me = this,
|
||
|
picker = me.monthPicker;
|
||
|
|
||
|
if (!picker) {
|
||
|
me.monthPicker = picker = new Ext.picker.Month({
|
||
|
renderTo: me.el,
|
||
|
// We need to set the ownerCmp so that owns() can correctly
|
||
|
// match up the component hierarchy so that focus does not leave
|
||
|
// an owning picker field if/when this gets focus.
|
||
|
ownerCmp: me,
|
||
|
floating: true,
|
||
|
padding: me.padding,
|
||
|
shadow: false,
|
||
|
small: me.showToday === false,
|
||
|
listeners: {
|
||
|
scope: me,
|
||
|
cancelclick: me.onCancelClick,
|
||
|
okclick: me.onOkClick,
|
||
|
yeardblclick: me.onOkClick,
|
||
|
monthdblclick: me.onOkClick
|
||
|
}
|
||
|
});
|
||
|
if (!me.disableAnim) {
|
||
|
// hide the element if we're animating to prevent an initial flicker
|
||
|
picker.el.setStyle('display', 'none');
|
||
|
}
|
||
|
picker.hide();
|
||
|
me.on('beforehide', me.doHideMonthPicker, me);
|
||
|
}
|
||
|
return picker;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Respond to an ok click on the month picker
|
||
|
* @private
|
||
|
*/
|
||
|
onOkClick: function(picker, value) {
|
||
|
var me = this,
|
||
|
month = value[0],
|
||
|
year = value[1],
|
||
|
date = new Date(year, month, me.getActive().getDate());
|
||
|
|
||
|
if (date.getMonth() !== month) {
|
||
|
// 'fix' the JS rolling date conversion if needed
|
||
|
date = Ext.Date.getLastDateOfMonth(new Date(year, month, 1));
|
||
|
}
|
||
|
me.setValue(date);
|
||
|
me.hideMonthPicker();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Respond to a cancel click on the month picker
|
||
|
* @private
|
||
|
*/
|
||
|
onCancelClick: function() {
|
||
|
this.selectedUpdate(this.activeDate);
|
||
|
this.hideMonthPicker();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Show the previous month.
|
||
|
* @param {Object} e
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
showPrevMonth: function(e) {
|
||
|
return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.MONTH, -1));
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Show the next month.
|
||
|
* @param {Object} e
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
showNextMonth: function(e) {
|
||
|
return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.MONTH, 1));
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Show the previous year.
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
showPrevYear: function() {
|
||
|
return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.YEAR, -1));
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Show the next year.
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
showNextYear: function() {
|
||
|
return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.YEAR, 1));
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Respond to the mouse wheel event
|
||
|
* @private
|
||
|
* @param {Ext.event.Event} e
|
||
|
*/
|
||
|
handleMouseWheel: function(e) {
|
||
|
e.stopEvent();
|
||
|
if(!this.disabled){
|
||
|
var delta = e.getWheelDelta();
|
||
|
if(delta > 0){
|
||
|
this.showPrevMonth();
|
||
|
} else if(delta < 0){
|
||
|
this.showNextMonth();
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Respond to a date being clicked in the picker
|
||
|
* @private
|
||
|
* @param {Ext.event.Event} e
|
||
|
* @param {HTMLElement} t
|
||
|
*/
|
||
|
handleDateClick: function(e, t) {
|
||
|
var me = this,
|
||
|
handler = me.handler;
|
||
|
|
||
|
e.stopEvent();
|
||
|
if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)){
|
||
|
me.setValue(new Date(t.dateValue));
|
||
|
me.fireEvent('select', me, me.value);
|
||
|
if (handler) {
|
||
|
handler.call(me.scope || me, me, me.value);
|
||
|
}
|
||
|
// event handling is turned off on hide
|
||
|
// when we are using the picker in a field
|
||
|
// therefore onSelect comes AFTER the select
|
||
|
// event.
|
||
|
me.onSelect();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Perform any post-select actions
|
||
|
* @private
|
||
|
*/
|
||
|
onSelect: function() {
|
||
|
if (this.hideOnSelect) {
|
||
|
this.hide();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Sets the current value to today.
|
||
|
* @return {Ext.picker.Date} this
|
||
|
*/
|
||
|
selectToday: function() {
|
||
|
var me = this,
|
||
|
btn = me.todayBtn,
|
||
|
handler = me.handler;
|
||
|
|
||
|
if (btn && !btn.disabled) {
|
||
|
me.setValue(Ext.Date.clearTime(new Date()));
|
||
|
me.fireEvent('select', me, me.value);
|
||
|
if (handler) {
|
||
|
handler.call(me.scope || me, me, me.value);
|
||
|
}
|
||
|
me.onSelect();
|
||
|
}
|
||
|
return me;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Update the selected cell
|
||
|
* @private
|
||
|
* @param {Date} date The new date
|
||
|
*/
|
||
|
selectedUpdate: function(date) {
|
||
|
var me = this,
|
||
|
t = date.getTime(),
|
||
|
cells = me.cells,
|
||
|
cls = me.selectedCls,
|
||
|
c,
|
||
|
cLen = cells.getCount(),
|
||
|
cell;
|
||
|
|
||
|
cell = me.activeCell;
|
||
|
if (cell) {
|
||
|
Ext.fly(cell).removeCls(cls);
|
||
|
cell.setAttribute('aria-selected', false);
|
||
|
}
|
||
|
|
||
|
for (c = 0; c < cLen; c++) {
|
||
|
cell = cells.item(c);
|
||
|
|
||
|
if (me.textNodes[c].dateValue === t) {
|
||
|
me.activeCell = cell.dom;
|
||
|
me.eventEl.dom.setAttribute('aria-activedescendant', cell.dom.id);
|
||
|
cell.dom.setAttribute('aria-selected', true);
|
||
|
cell.addCls(cls);
|
||
|
me.fireEvent('highlightitem', me, cell);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Update the contents of the picker for a new month
|
||
|
* @private
|
||
|
* @param {Date} date The new date
|
||
|
*/
|
||
|
fullUpdate: function(date) {
|
||
|
var me = this,
|
||
|
cells = me.cells.elements,
|
||
|
textNodes = me.textNodes,
|
||
|
disabledCls = me.disabledCellCls,
|
||
|
eDate = Ext.Date,
|
||
|
i = 0,
|
||
|
extraDays = 0,
|
||
|
newDate = +eDate.clearTime(date, true),
|
||
|
today = +eDate.clearTime(new Date()),
|
||
|
min = me.minDate ? eDate.clearTime(me.minDate, true) : Number.NEGATIVE_INFINITY,
|
||
|
max = me.maxDate ? eDate.clearTime(me.maxDate, true) : Number.POSITIVE_INFINITY,
|
||
|
ddMatch = me.disabledDatesRE,
|
||
|
ddText = me.disabledDatesText,
|
||
|
ddays = me.disabledDays ? me.disabledDays.join('') : false,
|
||
|
ddaysText = me.disabledDaysText,
|
||
|
format = me.format,
|
||
|
days = eDate.getDaysInMonth(date),
|
||
|
firstOfMonth = eDate.getFirstDateOfMonth(date),
|
||
|
startingPos = firstOfMonth.getDay() - me.startDay,
|
||
|
previousMonth = eDate.add(date, eDate.MONTH, -1),
|
||
|
ariaTitleDateFormat = me.ariaTitleDateFormat,
|
||
|
prevStart, current, disableToday, tempDate, setCellClass, html, cls,
|
||
|
formatValue, value;
|
||
|
|
||
|
if (startingPos < 0) {
|
||
|
startingPos += 7;
|
||
|
}
|
||
|
|
||
|
days += startingPos;
|
||
|
prevStart = eDate.getDaysInMonth(previousMonth) - startingPos;
|
||
|
current = new Date(previousMonth.getFullYear(), previousMonth.getMonth(), prevStart, me.initHour);
|
||
|
|
||
|
if (me.showToday) {
|
||
|
tempDate = eDate.clearTime(new Date());
|
||
|
disableToday = (tempDate < min || tempDate > max ||
|
||
|
(ddMatch && format && ddMatch.test(eDate.dateFormat(tempDate, format))) ||
|
||
|
(ddays && ddays.indexOf(tempDate.getDay()) !== -1));
|
||
|
|
||
|
if (!me.disabled) {
|
||
|
me.todayBtn.setDisabled(disableToday);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
setCellClass = function(cellIndex, cls){
|
||
|
var cell = cells[cellIndex];
|
||
|
|
||
|
value = +eDate.clearTime(current, true);
|
||
|
cell.setAttribute('aria-label', eDate.format(current, ariaTitleDateFormat));
|
||
|
// store dateValue number as an expando
|
||
|
cell.firstChild.dateValue = value;
|
||
|
if (value === today) {
|
||
|
cls += ' ' + me.todayCls;
|
||
|
cell.firstChild.title = me.todayText;
|
||
|
|
||
|
// Extra element for ARIA purposes
|
||
|
me.todayElSpan = Ext.DomHelper.append(cell.firstChild, {
|
||
|
tag: 'span',
|
||
|
cls: Ext.baseCSSPrefix + 'hidden-clip',
|
||
|
html: me.todayText
|
||
|
}, true);
|
||
|
}
|
||
|
if (value === newDate) {
|
||
|
me.activeCell = cell;
|
||
|
me.eventEl.dom.setAttribute('aria-activedescendant', cell.id);
|
||
|
cell.setAttribute('aria-selected', true);
|
||
|
cls += ' ' + me.selectedCls;
|
||
|
me.fireEvent('highlightitem', me, cell);
|
||
|
} else {
|
||
|
cell.setAttribute('aria-selected', false);
|
||
|
}
|
||
|
|
||
|
if (value < min) {
|
||
|
cls += ' ' + disabledCls;
|
||
|
cell.setAttribute('aria-label', me.minText);
|
||
|
}
|
||
|
else if (value > max) {
|
||
|
cls += ' ' + disabledCls;
|
||
|
cell.setAttribute('aria-label', me.maxText);
|
||
|
}
|
||
|
else if (ddays && ddays.indexOf(current.getDay()) !== -1){
|
||
|
cell.setAttribute('aria-label', ddaysText);
|
||
|
cls += ' ' + disabledCls;
|
||
|
}
|
||
|
else if (ddMatch && format){
|
||
|
formatValue = eDate.dateFormat(current, format);
|
||
|
if(ddMatch.test(formatValue)){
|
||
|
cell.setAttribute('aria-label', ddText.replace('%0', formatValue));
|
||
|
cls += ' ' + disabledCls;
|
||
|
}
|
||
|
}
|
||
|
cell.className = cls + ' ' + me.cellCls;
|
||
|
};
|
||
|
|
||
|
for(; i < me.numDays; ++i) {
|
||
|
if (i < startingPos) {
|
||
|
html = (++prevStart);
|
||
|
cls = me.prevCls;
|
||
|
} else if (i >= days) {
|
||
|
html = (++extraDays);
|
||
|
cls = me.nextCls;
|
||
|
} else {
|
||
|
html = i - startingPos + 1;
|
||
|
cls = me.activeCls;
|
||
|
}
|
||
|
textNodes[i].innerHTML = html;
|
||
|
current.setDate(current.getDate() + 1);
|
||
|
setCellClass(i, cls);
|
||
|
}
|
||
|
|
||
|
me.monthBtn.setText(Ext.Date.format(date, me.monthYearFormat));
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Update the contents of the picker
|
||
|
* @private
|
||
|
* @param {Date} date The new date
|
||
|
* @param {Boolean} forceRefresh True to force a full refresh
|
||
|
*/
|
||
|
update: function(date, forceRefresh) {
|
||
|
var me = this,
|
||
|
active = me.activeDate;
|
||
|
|
||
|
if (me.rendered) {
|
||
|
me.activeDate = date;
|
||
|
if (!forceRefresh && active && me.el &&
|
||
|
active.getMonth() === date.getMonth() &&
|
||
|
active.getFullYear() === date.getFullYear()) {
|
||
|
me.selectedUpdate(date, active);
|
||
|
} else {
|
||
|
me.fullUpdate(date, active);
|
||
|
}
|
||
|
}
|
||
|
return me;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @private
|
||
|
* @inheritdoc
|
||
|
*/
|
||
|
beforeDestroy: function() {
|
||
|
var me = this;
|
||
|
|
||
|
if (me.rendered) {
|
||
|
Ext.destroy(
|
||
|
me.keyNav,
|
||
|
me.monthPicker,
|
||
|
me.monthBtn,
|
||
|
me.nextRepeater,
|
||
|
me.prevRepeater,
|
||
|
me.todayBtn,
|
||
|
me.todayElSpan
|
||
|
);
|
||
|
delete me.textNodes;
|
||
|
delete me.cells.elements;
|
||
|
}
|
||
|
me.callParent();
|
||
|
},
|
||
|
|
||
|
privates: {
|
||
|
// Do the job of a container layout at this point even though we are not a Container.
|
||
|
// TODO: Refactor as a Container.
|
||
|
finishRenderChildren: function () {
|
||
|
var me = this;
|
||
|
|
||
|
me.callParent();
|
||
|
me.monthBtn.finishRender();
|
||
|
if (me.showToday) {
|
||
|
me.todayBtn.finishRender();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
getFocusEl: function() {
|
||
|
return this.eventEl;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Set the disabled state of various internal components
|
||
|
* @param {Boolean} disabled
|
||
|
* @private
|
||
|
*/
|
||
|
syncDisabled: function (disabled) {
|
||
|
var me = this,
|
||
|
keyNav = me.keyNav;
|
||
|
|
||
|
// If we have one, we have all
|
||
|
if (keyNav) {
|
||
|
keyNav.setDisabled(disabled);
|
||
|
me.prevRepeater.setDisabled(disabled);
|
||
|
me.nextRepeater.setDisabled(disabled);
|
||
|
if (me.todayBtn) {
|
||
|
me.todayBtn.setDisabled(disabled);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|