2 * MediaWiki Widgets - ExpiryWidget class.
4 * @copyright 2018 MediaWiki Widgets Team and others; see AUTHORS.txt
5 * @license The MIT License (MIT); see LICENSE.txt
11 * @classdesc Expiry widget.
13 * @class mw.widgets.ExpiryWidget
14 * @extends OO.ui.Widget
17 * @description Create a mw.widgets.ExpiryWidget object.
18 * @param {Object} [config] Configuration options
20 mw.widgets.ExpiryWidget = function ( config ) {
21 const RFC2822 = 'ddd, DD MMM YYYY HH:mm:ss [GMT]';
23 // Config initialization
24 config = Object.assign( {}, config );
26 this.relativeField = new config.RelativeInputClass( config.relativeInput );
27 this.relativeField.$element.addClass( 'mw-widget-ExpiryWidget-relative' );
30 mw.widgets.ExpiryWidget.super.call( this, config );
33 this.inputSwitch = new OO.ui.ButtonSelectWidget( {
36 new OO.ui.ButtonOptionWidget( {
40 new OO.ui.ButtonOptionWidget( {
46 this.dateTimeField = new mw.widgets.datetime.DateTimeInputWidget( {
47 min: new Date(), // The selected date must at least be now.
48 required: config.required
51 // Initially hide the dateTime field.
52 this.dateTimeField.toggle( false );
53 // Initially set the relative input.
54 this.inputSwitch.selectItemByData( 'relative' );
58 // Toggle the visible inputs.
59 this.inputSwitch.on( 'choose', ( event ) => {
60 switch ( event.getData() ) {
62 this.dateTimeField.toggle( true );
63 this.relativeField.toggle( false );
66 this.dateTimeField.toggle( false );
67 this.relativeField.toggle( true );
72 // When the date time field update, update the relative
74 this.dateTimeField.on( 'change', ( value ) => {
75 // Do not alter the visible input.
76 if ( this.relativeField.isVisible() ) {
80 // If the value was cleared, do not attempt to parse it.
82 this.relativeField.setValue( value );
86 const datetime = moment( value );
88 // If the datetime is invlaid for some reason, reset the relative field.
89 if ( !datetime.isValid() ) {
90 this.relativeField.setValue( undefined );
93 // Set the relative field value. The field only accepts English strings.
94 this.relativeField.setValue( datetime.utc().locale( 'en' ).format( RFC2822 ) );
97 // When the relative field update, update the date time field if it's a
98 // value that moment understands.
99 this.relativeField.on( 'change', ( event ) => {
100 // Emit a change event for this widget.
101 this.emit( 'change', event );
103 // Do not alter the visible input.
104 if ( this.dateTimeField.isVisible() ) {
108 // Parsing of free text field may fail, so always check if the date is
110 const datetime = moment( event );
112 if ( datetime.isValid() ) {
113 this.dateTimeField.setValue( datetime.utc().toISOString() );
115 this.dateTimeField.setValue( undefined );
121 .addClass( 'mw-widget-ExpiryWidget' )
122 .addClass( 'mw-widget-ExpiryWidget-hasDatePicker' )
124 this.inputSwitch.$element,
125 this.dateTimeField.$element,
126 this.relativeField.$element
129 // Trigger an initial onChange.
130 this.relativeField.emit( 'change', this.relativeField.getValue() );
135 OO.inheritClass( mw.widgets.ExpiryWidget, OO.ui.Widget );
140 mw.widgets.ExpiryWidget.static.reusePreInfuseDOM = function ( node, config ) {
141 const $relativeElement = $( node ).find( '.mw-widget-ExpiryWidget-relative' );
143 config = mw.widgets.ExpiryWidget.super.static.reusePreInfuseDOM( node, config );
145 // eslint-disable-next-line no-jquery/no-class-state
146 if ( $relativeElement.hasClass( 'oo-ui-textInputWidget' ) ) {
147 config.RelativeInputClass = OO.ui.TextInputWidget;
148 // eslint-disable-next-line no-jquery/no-class-state
149 } else if ( $relativeElement.hasClass( 'mw-widget-selectWithInputWidget' ) ) {
150 config.RelativeInputClass = mw.widgets.SelectWithInputWidget;
153 config.relativeInput = config.RelativeInputClass.static.reusePreInfuseDOM(
164 mw.widgets.ExpiryWidget.static.gatherPreInfuseState = function ( node, config ) {
165 const state = mw.widgets.ExpiryWidget.super.static.gatherPreInfuseState( node, config );
167 state.relativeInput = config.RelativeInputClass.static.gatherPreInfuseState(
168 $( node ).find( '.mw-widget-ExpiryWidget-relative' ),
178 mw.widgets.ExpiryWidget.prototype.restorePreInfuseState = function ( state ) {
179 mw.widgets.ExpiryWidget.super.prototype.restorePreInfuseState.call( this, state );
180 this.relativeField.restorePreInfuseState( state.relativeInput );
186 mw.widgets.ExpiryWidget.prototype.setDisabled = function ( disabled ) {
187 mw.widgets.ExpiryWidget.super.prototype.setDisabled.call( this, disabled );
188 this.relativeField.setDisabled( disabled );
190 if ( this.inputSwitch ) {
191 this.inputSwitch.setDisabled( disabled );
194 if ( this.dateTimeField ) {
195 this.dateTimeField.setDisabled( disabled );
200 * Gets the value of the widget.
204 mw.widgets.ExpiryWidget.prototype.getValue = function () {
205 return this.relativeField.getValue();