Localisation updates from https://translatewiki.net.
[mediawiki.git] / resources / src / mediawiki.widgets / mw.widgets.ExpiryInputWidget.js
blob56dfa790a4dc19189a920442e6b63803fc23ebd5
1 /*!
2  * MediaWiki Widgets - ExpiryWidget class.
3  *
4  * @copyright 2018 MediaWiki Widgets Team and others; see AUTHORS.txt
5  * @license The MIT License (MIT); see LICENSE.txt
6  */
7 /* global moment */
8 ( function () {
10         /**
11          * @classdesc Expiry widget.
12          *
13          * @class mw.widgets.ExpiryWidget
14          * @extends OO.ui.Widget
15          *
16          * @constructor
17          * @description Create a mw.widgets.ExpiryWidget object.
18          * @param {Object} [config] Configuration options
19          */
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' );
29                 // Parent constructor
30                 mw.widgets.ExpiryWidget.super.call( this, config );
32                 // Properties
33                 this.inputSwitch = new OO.ui.ButtonSelectWidget( {
34                         tabIndex: -1,
35                         items: [
36                                 new OO.ui.ButtonOptionWidget( {
37                                         data: 'relative',
38                                         icon: 'edit'
39                                 } ),
40                                 new OO.ui.ButtonOptionWidget( {
41                                         data: 'date',
42                                         icon: 'calendar'
43                                 } )
44                         ]
45                 } );
46                 this.dateTimeField = new mw.widgets.datetime.DateTimeInputWidget( {
47                         min: new Date(), // The selected date must at least be now.
48                         required: config.required
49                 } );
51                 // Initially hide the dateTime field.
52                 this.dateTimeField.toggle( false );
53                 // Initially set the relative input.
54                 this.inputSwitch.selectItemByData( 'relative' );
56                 // Events
58                 // Toggle the visible inputs.
59                 this.inputSwitch.on( 'choose', ( event ) => {
60                         switch ( event.getData() ) {
61                                 case 'date':
62                                         this.dateTimeField.toggle( true );
63                                         this.relativeField.toggle( false );
64                                         break;
65                                 case 'relative':
66                                         this.dateTimeField.toggle( false );
67                                         this.relativeField.toggle( true );
68                                         break;
69                         }
70                 } );
72                 // When the date time field update, update the relative
73                 // field.
74                 this.dateTimeField.on( 'change', ( value ) => {
75                         // Do not alter the visible input.
76                         if ( this.relativeField.isVisible() ) {
77                                 return;
78                         }
80                         // If the value was cleared, do not attempt to parse it.
81                         if ( !value ) {
82                                 this.relativeField.setValue( value );
83                                 return;
84                         }
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 );
91                         }
93                         // Set the relative field value. The field only accepts English strings.
94                         this.relativeField.setValue( datetime.utc().locale( 'en' ).format( RFC2822 ) );
95                 } );
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() ) {
105                                 return;
106                         }
108                         // Parsing of free text field may fail, so always check if the date is
109                         // valid.
110                         const datetime = moment( event );
112                         if ( datetime.isValid() ) {
113                                 this.dateTimeField.setValue( datetime.utc().toISOString() );
114                         } else {
115                                 this.dateTimeField.setValue( undefined );
116                         }
117                 } );
119                 // Initialization
120                 this.$element
121                         .addClass( 'mw-widget-ExpiryWidget' )
122                         .addClass( 'mw-widget-ExpiryWidget-hasDatePicker' )
123                         .append(
124                                 this.inputSwitch.$element,
125                                 this.dateTimeField.$element,
126                                 this.relativeField.$element
127                         );
129                 // Trigger an initial onChange.
130                 this.relativeField.emit( 'change', this.relativeField.getValue() );
131         };
133         /* Inheritance */
135         OO.inheritClass( mw.widgets.ExpiryWidget, OO.ui.Widget );
137         /**
138          * @inheritdoc
139          */
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;
151                 }
153                 config.relativeInput = config.RelativeInputClass.static.reusePreInfuseDOM(
154                         $relativeElement,
155                         config.relativeInput
156                 );
158                 return config;
159         };
161         /**
162          * @inheritdoc
163          */
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' ),
169                         config.relativeInput
170                 );
172                 return state;
173         };
175         /**
176          * @inheritdoc
177          */
178         mw.widgets.ExpiryWidget.prototype.restorePreInfuseState = function ( state ) {
179                 mw.widgets.ExpiryWidget.super.prototype.restorePreInfuseState.call( this, state );
180                 this.relativeField.restorePreInfuseState( state.relativeInput );
181         };
183         /**
184          * @inheritdoc
185          */
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 );
192                 }
194                 if ( this.dateTimeField ) {
195                         this.dateTimeField.setDisabled( disabled );
196                 }
197         };
199         /**
200          * Gets the value of the widget.
201          *
202          * @return {string}
203          */
204         mw.widgets.ExpiryWidget.prototype.getValue = function () {
205                 return this.relativeField.getValue();
206         };
208 }() );