( function () {
/**
* @classdesc DateTimeInputWidgets can be used to input a date, a time, or
* a date and time, in either UTC or the user's local timezone.
* Please see the [OOUI documentation on MediaWiki](https://www.mediawiki.org/wiki/OOUI/Widgets/Inputs)
* for more information and examples.
*
* This widget can be used inside a HTML form, such as a OO.ui.FormLayout.
*
* @example
* // Example of a text input widget
* var dateTimeInput = new mw.widgets.datetime.DateTimeInputWidget( {} )
* $( document.body ).append( dateTimeInput.$element );
*
* @class
* @extends OO.ui.InputWidget
* @mixes OO.ui.mixin.IconElement
* @mixes OO.ui.mixin.IndicatorElement
* @mixes OO.ui.mixin.PendingElement
* @mixes OO.ui.mixin.FlaggedElement
*
* @constructor
* @description Create an instance of `mw.widgets.datetime.DateTimeInputWidget`.
* @param {Object} [config] Configuration options
* @param {string} [config.type='datetime'] Whether to act like a 'date', 'time', or 'datetime' input.
* Affects values stored in the relevant `<input>` and the formatting and
* interpretation of values passed to/from
* {@link https://doc.wikimedia.org/oojs-ui/master/js/OO.ui.InputWidget.html#getValue getValue()} and
* {@link https://doc.wikimedia.org/oojs-ui/master/js/OO.ui.InputWidget.html#setValue setValue()}.
* It's up to the user to configure the DateTimeFormatter correctly.
* @param {Object|mw.widgets.datetime.DateTimeFormatter} [config.formatter={}] Configuration options for
* {@link mw.widgets.datetime.ProlepticGregorianDateTimeFormatter} (with 'format' defaulting to
* '@date', '@time', or '@datetime' depending on 'type'), or an
* {@link mw.widgets.datetime.DateTimeFormatter} instance to use.
* @param {Object|null} [config.calendar={}] Configuration options for
* {@link mw.widgets.datetime.CalendarWidget}; note certain settings will be forced based on the
* settings passed to this widget. Set null to disable the calendar.
* @param {boolean} [config.required=false] Whether a value is required.
* @param {boolean} [config.clearable=true] Whether to provide for blanking the value.
* @param {Date|null} [config.value=null] Default value for the widget
* @param {Date|string|null} [config.min=null] Minimum allowed date
* @param {Date|string|null} [config.max=null] Maximum allowed date
*/
mw.widgets.datetime.DateTimeInputWidget = function MwWidgetsDatetimeDateTimeInputWidget( config ) {
// Configuration initialization
config = Object.assign( {
type: 'datetime',
clearable: true,
required: false,
min: null,
max: null,
formatter: {},
calendar: {}
}, config );
// See InputWidget#reusePreInfuseDOM about config.$input
if ( config.$input ) {
// Hide unused <input> from PHP after infusion is done
config.$input.addClass( 'oo-ui-element-hidden' );
}
if ( $.isPlainObject( config.formatter ) && config.formatter.format === undefined ) {
config.formatter.format = '@' + config.type;
}
// Early properties
this.type = config.type;
// Parent constructor
mw.widgets.datetime.DateTimeInputWidget.super.call( this, config );
// Mixin constructors
OO.ui.mixin.IconElement.call( this, config );
OO.ui.mixin.IndicatorElement.call( this, config );
OO.ui.mixin.PendingElement.call( this, config );
OO.ui.mixin.FlaggedElement.call( this, config );
// Properties
this.$handle = $( '<span>' );
this.$fields = $( '<span>' );
this.fields = [];
this.clearable = !!config.clearable;
this.required = !!config.required;
if ( typeof config.min === 'string' ) {
config.min = this.parseDateValue( config.min );
}
if ( config.min instanceof Date && config.min.getTime() >= -62167219200000 ) {
this.min = config.min;
} else {
this.min = new Date( -62167219200000 ); // 0000-01-01T00:00:00.000Z
}
if ( typeof config.max === 'string' ) {
config.max = this.parseDateValue( config.max );
}
if ( config.max instanceof Date && config.max.getTime() <= 253402300799999 ) {
this.max = config.max;
} else {
this.max = new Date( 253402300799999 ); // 9999-12-31T12:59:59.999Z
}
switch ( this.type ) {
case 'date':
this.min.setUTCHours( 0, 0, 0, 0 );
this.max.setUTCHours( 23, 59, 59, 999 );
break;
case 'time':
this.min.setUTCFullYear( 1970, 0, 1 );
this.max.setUTCFullYear( 1970, 0, 1 );
break;
}
if ( this.min > this.max ) {
throw new Error(
'"min" (' + this.min.toISOString() + ') must not be greater than ' +
'"max" (' + this.max.toISOString() + ')'
);
}
if ( config.formatter instanceof mw.widgets.datetime.DateTimeFormatter ) {
this.formatter = config.formatter;
} else if ( $.isPlainObject( config.formatter ) ) {
this.formatter = new mw.widgets.datetime.ProlepticGregorianDateTimeFormatter( config.formatter );
} else {
throw new Error( '"formatter" must be an mw.widgets.datetime.DateTimeFormatter or a plain object' );
}
if ( this.type === 'time' || config.calendar === null ) {
this.calendar = null;
} else {
config.calendar = Object.assign( {}, config.calendar, {
formatter: this.formatter,
widget: this,
min: this.min,
max: this.max
} );
this.calendar = new mw.widgets.datetime.CalendarWidget( config.calendar );
}
// Events
this.$handle.on( {
click: this.onHandleClick.bind( this )
} );
this.connect( this, {
change: 'onChange'
} );
this.formatter.connect( this, {
local: 'onChange'
} );
if ( this.calendar ) {
this.calendar.connect( this, {
change: 'onCalendarChange'
} );
}
// Initialization
this.setTabIndex( -1 );
this.$fields.addClass( 'mw-widgets-datetime-dateTimeInputWidget-fields' );
this.setupFields();
this.$handle
.addClass( 'mw-widgets-datetime-dateTimeInputWidget-handle' )
.append( this.$icon, this.$indicator, this.$fields );
this.$element
.addClass( 'mw-widgets-datetime-dateTimeInputWidget' )
.append( this.$handle );
if ( this.calendar ) {
const date = this.getValueAsDate();
this.calendar.setSelected( date );
if ( date ) {
this.calendar.setFocusedDate( date );
}
this.$element.append( this.calendar.$element );
}
};
/* Setup */
OO.inheritClass( mw.widgets.datetime.DateTimeInputWidget, OO.ui.InputWidget );
OO.mixinClass( mw.widgets.datetime.DateTimeInputWidget, OO.ui.mixin.IconElement );
OO.mixinClass( mw.widgets.datetime.DateTimeInputWidget, OO.ui.mixin.IndicatorElement );
OO.mixinClass( mw.widgets.datetime.DateTimeInputWidget, OO.ui.mixin.PendingElement );
OO.mixinClass( mw.widgets.datetime.DateTimeInputWidget, OO.ui.mixin.FlaggedElement );
/* Static properties */
mw.widgets.datetime.DateTimeInputWidget.static.supportsSimpleLabel = false;
/* Events */
/* Static Methods */
/**
* @inheritdoc
*/
mw.widgets.datetime.DateTimeInputWidget.static.reusePreInfuseDOM = function ( node, config ) {
config = mw.widgets.datetime.DateTimeInputWidget.super.static.reusePreInfuseDOM( node, config );
if ( config.$input ) {
// Ignore the extra field from PendingTextInputWidget (T382344)
config.$input = config.$input.first();
}
return config;
};
/* Methods */
/**
* Get the currently focused field, if any.
*
* @private
* @return {jQuery}
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.getFocusedField = function () {
return this.$fields.find( this.getElementDocument().activeElement );
};
/**
* Convert a date string to a Date.
*
* @private
* @param {string} value
* @return {Date|null}
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.parseDateValue = function ( value ) {
value = String( value );
switch ( this.type ) {
case 'date':
value = value + 'T00:00:00Z';
break;
case 'time':
value = '1970-01-01T' + value + 'Z';
break;
}
let date;
const m = /^(\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?Z$/.exec( value );
if ( m ) {
if ( m[ 7 ] ) {
while ( m[ 7 ].length < 3 ) {
m[ 7 ] += '0';
}
} else {
m[ 7 ] = 0;
}
date = new Date();
date.setUTCFullYear( m[ 1 ], m[ 2 ] - 1, m[ 3 ] );
date.setUTCHours( m[ 4 ], m[ 5 ], m[ 6 ], m[ 7 ] );
if ( date.getTime() < -62167219200000 || date.getTime() > 253402300799999 ||
date.getUTCFullYear() !== +m[ 1 ] ||
date.getUTCMonth() + 1 !== +m[ 2 ] ||
date.getUTCDate() !== +m[ 3 ] ||
date.getUTCHours() !== +m[ 4 ] ||
date.getUTCMinutes() !== +m[ 5 ] ||
date.getUTCSeconds() !== +m[ 6 ] ||
date.getUTCMilliseconds() !== +m[ 7 ]
) {
date = null;
}
} else {
date = null;
}
return date;
};
/**
* @inheritdoc
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.cleanUpValue = function ( value ) {
let date, pad;
if ( value === '' ) {
return '';
}
if ( value instanceof Date ) {
date = value;
} else {
date = this.parseDateValue( value );
}
if ( date instanceof Date ) {
pad = function ( v, l ) {
v = String( v );
while ( v.length < l ) {
v = '0' + v;
}
return v;
};
switch ( this.type ) {
case 'date':
value = pad( date.getUTCFullYear(), 4 ) +
'-' + pad( date.getUTCMonth() + 1, 2 ) +
'-' + pad( date.getUTCDate(), 2 );
break;
case 'time':
value = pad( date.getUTCHours(), 2 ) +
':' + pad( date.getUTCMinutes(), 2 ) +
':' + pad( date.getUTCSeconds(), 2 ) +
'.' + pad( date.getUTCMilliseconds(), 3 );
value = value.replace( /\.?0+$/, '' );
break;
default:
value = date.toISOString();
break;
}
} else {
value = '';
}
return value;
};
/**
* Get the value of the input as a Date object.
*
* @return {Date|null}
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.getValueAsDate = function () {
return this.parseDateValue( this.getValue() );
};
/**
* Set up the UI fields.
*
* @private
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.setupFields = function () {
let i, $field, spec, placeholder, sz, maxlength;
const
spanValFunc = function ( v ) {
if ( v === undefined ) {
return this.data( 'mw-widgets-datetime-dateTimeInputWidget-value' );
} else {
v = String( v );
this.data( 'mw-widgets-datetime-dateTimeInputWidget-value', v );
if ( v === '' ) {
v = this.data( 'mw-widgets-datetime-dateTimeInputWidget-placeholder' );
}
this.text( v );
return this;
}
},
reduceFunc = function ( k, v ) {
maxlength = Math.max( maxlength, v );
},
disabled = this.isDisabled(),
specs = this.formatter.getFieldSpec();
this.$fields.empty();
this.clearButton = null;
this.fields = [];
for ( i = 0; i < specs.length; i++ ) {
spec = specs[ i ];
if ( typeof spec === 'string' ) {
$( '<span>' )
.addClass( 'mw-widgets-datetime-dateTimeInputWidget-field' )
.text( spec )
.appendTo( this.$fields );
continue;
}
placeholder = '';
while ( placeholder.length < spec.size ) {
placeholder += '_';
}
if ( spec.type === 'number' ) {
sz = spec.size + 'ch';
} else {
// Add a little for padding
sz = ( spec.size * 1.25 ) + 'ch';
}
if ( spec.editable && spec.type !== 'static' ) {
if ( spec.type === 'boolean' || spec.type === 'toggleLocal' ) {
$field = $( '<span>' )
.attr( {
tabindex: disabled ? -1 : 0
} )
.width( sz )
.data( 'mw-widgets-datetime-dateTimeInputWidget-placeholder', placeholder );
$field.on( {
keydown: this.onFieldKeyDown.bind( this, $field ),
focus: this.onFieldFocus.bind( this, $field ),
click: this.onFieldClick.bind( this, $field ),
'wheel mousewheel DOMMouseScroll': this.onFieldWheel.bind( this, $field )
} );
$field.val = spanValFunc;
} else {
maxlength = spec.size;
if ( spec.intercalarySize ) {
// eslint-disable-next-line no-jquery/no-each-util
$.each( spec.intercalarySize, reduceFunc );
}
$field = $( '<input>' ).attr( 'type', 'text' )
.attr( {
tabindex: disabled ? -1 : 0,
size: spec.size,
maxlength: maxlength
} )
.prop( {
disabled: disabled,
placeholder: placeholder
} )
.width( sz );
$field.on( {
keydown: this.onFieldKeyDown.bind( this, $field ),
click: this.onFieldClick.bind( this, $field ),
focus: this.onFieldFocus.bind( this, $field ),
blur: this.onFieldBlur.bind( this, $field ),
change: this.onFieldChange.bind( this, $field ),
'wheel mousewheel DOMMouseScroll': this.onFieldWheel.bind( this, $field )
} );
}
$field.addClass( 'mw-widgets-datetime-dateTimeInputWidget-editField' );
} else {
$field = $( '<span>' )
.width( sz )
.data( 'mw-widgets-datetime-dateTimeInputWidget-placeholder', placeholder );
if ( spec.type !== 'static' ) {
$field.prop( 'tabIndex', -1 );
$field.on( 'focus', this.onFieldFocus.bind( this, $field ) );
}
if ( spec.type === 'static' ) {
$field.text( spec.value );
} else {
$field.val = spanValFunc;
}
}
this.fields.push( $field );
$field
.addClass( 'mw-widgets-datetime-dateTimeInputWidget-field' )
.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec', spec )
.appendTo( this.$fields );
}
if ( this.clearable ) {
this.clearButton = new OO.ui.ButtonWidget( {
classes: [ 'mw-widgets-datetime-dateTimeInputWidget-field', 'mw-widgets-datetime-dateTimeInputWidget-clearButton' ],
framed: false,
icon: 'clear',
disabled: disabled
} ).connect( this, {
click: 'onClearClick'
} );
this.$fields.append( this.clearButton.$element );
}
this.updateFieldsFromValue();
};
/**
* Update the UI fields from the current value.
*
* @private
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.updateFieldsFromValue = function () {
let i, $field, spec, intercalary, sz;
const date = this.getValueAsDate();
if ( date === null ) {
this.components = null;
for ( i = 0; i < this.fields.length; i++ ) {
$field = this.fields[ i ];
spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
$field
.removeClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid oo-ui-element-hidden' )
.val( '' );
if ( spec.intercalarySize ) {
if ( spec.type === 'number' ) {
$field.width( spec.size + 'ch' );
} else {
// Add a little for padding
$field.width( ( spec.size * 1.25 ) + 'ch' );
}
}
}
this.setFlags( { invalid: this.required } );
} else {
this.components = this.formatter.getComponentsFromDate( date );
intercalary = this.components.intercalary;
for ( i = 0; i < this.fields.length; i++ ) {
$field = this.fields[ i ];
$field.removeClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid' );
spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
if ( spec.type !== 'static' ) {
$field.val( spec.formatValue( this.components[ spec.component ] ) );
}
if ( spec.intercalarySize ) {
if ( intercalary && spec.intercalarySize[ intercalary ] !== undefined ) {
sz = spec.intercalarySize[ intercalary ];
} else {
sz = spec.size;
}
$field.toggleClass( 'oo-ui-element-hidden', sz <= 0 );
if ( spec.type === 'number' ) {
this.fields[ i ].width( sz + 'ch' );
} else {
// Add a little for padding
this.fields[ i ].width( ( sz * 1.25 ) + 'ch' );
}
}
}
this.setFlags( { invalid: date < this.min || date > this.max } );
}
this.$element.toggleClass( 'mw-widgets-datetime-dateTimeInputWidget-empty', date === null );
};
/**
* Update the value with data from the UI fields.
*
* @private
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.updateValueFromFields = function () {
let i, v, $field, spec, curDate, newDate,
anyInvalid = false,
anyEmpty = false,
allEmpty = true;
const components = {};
for ( i = 0; i < this.fields.length; i++ ) {
$field = this.fields[ i ];
spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
if ( spec.editable ) {
$field.removeClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid' );
v = $field.val();
if ( v === '' ) {
$field.addClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid' );
anyEmpty = true;
} else {
allEmpty = false;
v = spec.parseValue( v );
if ( v === undefined ) {
$field.addClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid' );
anyInvalid = true;
} else {
components[ spec.component ] = v;
}
}
}
}
if ( allEmpty ) {
for ( i = 0; i < this.fields.length; i++ ) {
this.fields[ i ].removeClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid' );
}
} else if ( anyEmpty ) {
anyInvalid = true;
}
if ( !anyInvalid ) {
curDate = this.getValueAsDate();
newDate = this.formatter.getDateFromComponents( components );
if ( !curDate || !newDate || curDate.getTime() !== newDate.getTime() ) {
this.setValue( newDate );
}
}
};
/**
* Handle change event.
*
* @private
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onChange = function () {
let date;
this.updateFieldsFromValue();
if ( this.calendar ) {
date = this.getValueAsDate();
this.calendar.setSelected( date );
if ( date ) {
this.calendar.setFocusedDate( date );
}
}
};
/**
* Handle clear button click event.
*
* @private
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onClearClick = function () {
this.blur().setValue( '' );
};
/**
* Handle click on the widget background.
*
* @private
* @param {jQuery.Event} e Click event
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onHandleClick = function () {
this.focus();
};
/**
* Handle key down events on our field inputs.
*
* @private
* @param {jQuery} $field
* @param {jQuery.Event} e Key down event
* @return {boolean|undefined} False to cancel the default event
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldKeyDown = function ( $field, e ) {
const spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
if ( !this.isDisabled() ) {
switch ( e.which ) {
case OO.ui.Keys.ENTER:
case OO.ui.Keys.SPACE:
if ( spec.type === 'boolean' ) {
this.setValue(
this.formatter.adjustComponent( this.getValueAsDate(), spec.component, 1, 'wrap' )
);
return false;
} else if ( spec.type === 'toggleLocal' ) {
this.formatter.toggleLocal();
}
break;
case OO.ui.Keys.UP:
case OO.ui.Keys.DOWN:
if ( spec.type === 'toggleLocal' ) {
this.formatter.toggleLocal();
} else {
this.setValue(
this.formatter.adjustComponent( this.getValueAsDate(), spec.component,
e.keyCode === OO.ui.Keys.UP ? -1 : 1, 'wrap' )
);
}
if ( $field.is( 'input' ) ) {
$field.trigger( 'select' );
}
return false;
}
}
};
/**
* Handle focus events on our field inputs.
*
* @private
* @param {jQuery} $field
* @param {jQuery.Event} e Focus event
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldFocus = function ( $field ) {
const spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
if ( !this.isDisabled() ) {
if ( this.getValueAsDate() === null ) {
this.setValue( this.formatter.getDefaultDate() );
}
if ( $field.is( 'input' ) ) {
$field.trigger( 'select' );
}
if ( this.calendar ) {
this.calendar.toggle( !!spec.calendarComponent );
}
}
};
/**
* Handle click events on our field inputs.
*
* @private
* @param {jQuery} $field
* @param {jQuery.Event} e Click event
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldClick = function ( $field ) {
const spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
if ( !this.isDisabled() ) {
if ( spec.type === 'boolean' ) {
this.setValue(
this.formatter.adjustComponent( this.getValueAsDate(), spec.component, 1, 'wrap' )
);
} else if ( spec.type === 'toggleLocal' ) {
this.formatter.toggleLocal();
}
}
};
/**
* Handle blur events on our field inputs.
*
* @private
* @param {jQuery} $field
* @param {jQuery.Event} e Blur event
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldBlur = function ( $field ) {
let v;
const spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
this.updateValueFromFields();
// Normalize
const date = this.getValueAsDate();
if ( !date ) {
$field.val( '' );
} else {
v = spec.formatValue( this.formatter.getComponentsFromDate( date )[ spec.component ] );
if ( v !== $field.val() ) {
$field.val( v );
}
}
};
/**
* Handle change events on our field inputs.
*
* @private
* @param {jQuery} $field
* @param {jQuery.Event} e Change event
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldChange = function () {
this.updateValueFromFields();
};
/**
* Handle wheel events on our field inputs.
*
* @private
* @param {jQuery} $field
* @param {jQuery.Event} e Change event
* @return {boolean|undefined} False to cancel the default event
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldWheel = function ( $field, e ) {
let delta = 0;
const spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
if ( this.isDisabled() || !this.getFocusedField().length ) {
return;
}
// Standard 'wheel' event
if ( e.originalEvent.deltaMode !== undefined ) {
this.sawWheelEvent = true;
}
if ( e.originalEvent.deltaY ) {
delta = -e.originalEvent.deltaY;
} else if ( e.originalEvent.deltaX ) {
delta = e.originalEvent.deltaX;
}
// Non-standard events
if ( !this.sawWheelEvent ) {
if ( e.originalEvent.wheelDeltaX ) {
delta = -e.originalEvent.wheelDeltaX;
} else if ( e.originalEvent.wheelDeltaY ) {
delta = e.originalEvent.wheelDeltaY;
} else if ( e.originalEvent.wheelDelta ) {
delta = e.originalEvent.wheelDelta;
} else if ( e.originalEvent.detail ) {
delta = -e.originalEvent.detail;
}
}
if ( delta && spec ) {
if ( spec.type === 'toggleLocal' ) {
this.formatter.toggleLocal();
} else {
this.setValue(
this.formatter.adjustComponent( this.getValueAsDate(), spec.component, delta < 0 ? -1 : 1, 'wrap' )
);
}
return false;
}
};
/**
* Handle calendar change event.
*
* @private
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.onCalendarChange = function () {
const curDate = this.getValueAsDate(),
newDate = this.calendar.getSelected()[ 0 ];
if ( newDate ) {
if ( !curDate || newDate.getTime() !== curDate.getTime() ) {
this.setValue( newDate );
}
}
};
/**
* @inheritdoc
* @private
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.getInputElement = function () {
return $( '<input>' ).attr( 'type', 'hidden' );
};
/**
* @inheritdoc
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.setDisabled = function ( disabled ) {
mw.widgets.datetime.DateTimeInputWidget.super.prototype.setDisabled.call( this, disabled );
// Flag all our fields as disabled
if ( this.$fields ) {
this.$fields.find( 'input' ).prop( 'disabled', this.isDisabled() );
this.$fields.find( '[tabindex]' ).attr( 'tabindex', this.isDisabled() ? -1 : 0 );
}
if ( this.clearButton ) {
this.clearButton.setDisabled( disabled );
}
return this;
};
/**
* @inheritdoc
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.focus = function () {
if ( !this.getFocusedField().length ) {
this.$fields.find( '.mw-widgets-datetime-dateTimeInputWidget-editField' ).first().trigger( 'focus' );
}
return this;
};
/**
* @inheritdoc
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.blur = function () {
this.getFocusedField().blur();
return this;
};
/**
* @inheritdoc
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.simulateLabelClick = function () {
this.focus();
};
}() );