Merge "resources: Strip '$' and 'mw' from file closures"
[lhc/web/wiklou.git] / resources / src / mediawiki.widgets / mw.widgets.ExpiryInputWidget.js
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 () {
9
10 /**
11 * Creates a mw.widgets.ExpiryWidget object.
12 *
13 * @class mw.widgets.ExpiryWidget
14 * @extends OO.ui.Widget
15 *
16 * @constructor
17 * @param {Object} [config] Configuration options
18 */
19 mw.widgets.ExpiryWidget = function ( config ) {
20 var RFC2822 = 'ddd, DD MMM YYYY HH:mm:ss [GMT]';
21
22 // Config initialization
23 config = $.extend( {}, config );
24
25 this.relativeField = new config.RelativeInputClass( config.relativeInput );
26 this.relativeField.$element.addClass( 'mw-widget-ExpiryWidget-relative' );
27
28 // Parent constructor
29 mw.widgets.ExpiryWidget.parent.call( this, config );
30
31 // If the wiki does not want the date picker, then initialize the relative
32 // field and exit.
33 if ( config.noDatePicker ) {
34 this.relativeField.on( 'change', function ( event ) {
35 // Emit a change event for this widget.
36 this.emit( 'change', event );
37 }.bind( this ) );
38
39 // Initialization
40 this.$element
41 .addClass( 'mw-widget-ExpiryWidget' )
42 .append(
43 this.relativeField.$element
44 );
45
46 return;
47 }
48
49 // Properties
50 this.inputSwitch = new OO.ui.ButtonSelectWidget( {
51 tabIndex: -1,
52 items: [
53 new OO.ui.ButtonOptionWidget( {
54 data: 'relative',
55 icon: 'edit'
56 } ),
57 new OO.ui.ButtonOptionWidget( {
58 data: 'date',
59 icon: 'calendar'
60 } )
61 ]
62 } );
63 this.dateTimeField = new mw.widgets.datetime.DateTimeInputWidget( {
64 min: new Date(), // The selected date must at least be now.
65 required: config.required
66 } );
67
68 // Initially hide the dateTime field.
69 this.dateTimeField.toggle( false );
70 // Initially set the relative input.
71 this.inputSwitch.selectItemByData( 'relative' );
72
73 // Events
74
75 // Toggle the visible inputs.
76 this.inputSwitch.on( 'choose', function ( event ) {
77 switch ( event.getData() ) {
78 case 'date':
79 this.dateTimeField.toggle( true );
80 this.relativeField.toggle( false );
81 break;
82 case 'relative':
83 this.dateTimeField.toggle( false );
84 this.relativeField.toggle( true );
85 break;
86 }
87 }.bind( this ) );
88
89 // When the date time field update, update the relative
90 // field.
91 this.dateTimeField.on( 'change', function ( value ) {
92 var datetime;
93
94 // Do not alter the visible input.
95 if ( this.relativeField.isVisible() ) {
96 return;
97 }
98
99 // If the value was cleared, do not attempt to parse it.
100 if ( !value ) {
101 this.relativeField.setValue( value );
102 return;
103 }
104
105 datetime = moment( value );
106
107 // If the datetime is invlaid for some reason, reset the relative field.
108 if ( !datetime.isValid() ) {
109 this.relativeField.setValue( undefined );
110 }
111
112 // Set the relative field value. The field only accepts English strings.
113 this.relativeField.setValue( datetime.utc().locale( 'en' ).format( RFC2822 ) );
114 }.bind( this ) );
115
116 // When the relative field update, update the date time field if it's a
117 // value that moment understands.
118 this.relativeField.on( 'change', function ( event ) {
119 var datetime;
120
121 // Emit a change event for this widget.
122 this.emit( 'change', event );
123
124 // Do not alter the visible input.
125 if ( this.dateTimeField.isVisible() ) {
126 return;
127 }
128
129 // Parsing of free text field may fail, so always check if the date is
130 // valid.
131 datetime = moment( event );
132
133 if ( datetime.isValid() ) {
134 this.dateTimeField.setValue( datetime.utc().toISOString() );
135 } else {
136 this.dateTimeField.setValue( undefined );
137 }
138 }.bind( this ) );
139
140 // Initialization
141 this.$element
142 .addClass( 'mw-widget-ExpiryWidget' )
143 .addClass( 'mw-widget-ExpiryWidget-hasDatePicker' )
144 .append(
145 this.inputSwitch.$element,
146 this.dateTimeField.$element,
147 this.relativeField.$element
148 );
149
150 // Trigger an initial onChange.
151 this.relativeField.emit( 'change', this.relativeField.getValue() );
152 };
153
154 /* Inheritance */
155
156 OO.inheritClass( mw.widgets.ExpiryWidget, OO.ui.Widget );
157
158 /**
159 * @inheritdoc
160 */
161 mw.widgets.ExpiryWidget.static.reusePreInfuseDOM = function ( node, config ) {
162 var relativeElement = $( node ).find( '.mw-widget-ExpiryWidget-relative' );
163
164 config = mw.widgets.ExpiryWidget.parent.static.reusePreInfuseDOM( node, config );
165
166 if ( relativeElement.hasClass( 'oo-ui-textInputWidget' ) ) {
167 config.RelativeInputClass = OO.ui.TextInputWidget;
168 } else if ( relativeElement.hasClass( 'mw-widget-selectWithInputWidget' ) ) {
169 config.RelativeInputClass = mw.widgets.SelectWithInputWidget;
170 }
171
172 config.relativeInput = config.RelativeInputClass.static.reusePreInfuseDOM(
173 relativeElement,
174 config.relativeInput
175 );
176
177 return config;
178 };
179
180 /**
181 * @inheritdoc
182 */
183 mw.widgets.ExpiryWidget.static.gatherPreInfuseState = function ( node, config ) {
184 var state = mw.widgets.ExpiryWidget.parent.static.gatherPreInfuseState( node, config );
185
186 state.relativeInput = config.RelativeInputClass.static.gatherPreInfuseState(
187 $( node ).find( '.mw-widget-ExpiryWidget-relative' ),
188 config.relativeInput
189 );
190
191 return state;
192 };
193
194 /**
195 * @inheritdoc
196 */
197 mw.widgets.ExpiryWidget.prototype.restorePreInfuseState = function ( state ) {
198 mw.widgets.ExpiryWidget.parent.prototype.restorePreInfuseState.call( this, state );
199 this.relativeField.restorePreInfuseState( state.relativeInput );
200 };
201
202 /**
203 * @inheritdoc
204 */
205 mw.widgets.ExpiryWidget.prototype.setDisabled = function ( disabled ) {
206 mw.widgets.ExpiryWidget.parent.prototype.setDisabled.call( this, disabled );
207 this.relativeField.setDisabled( disabled );
208
209 if ( this.inputSwitch ) {
210 this.inputSwitch.setDisabled( disabled );
211 }
212
213 if ( this.dateTimeField ) {
214 this.dateTimeField.setDisabled( disabled );
215 }
216 };
217
218 /**
219 * Gets the value of the widget.
220 *
221 * @return {string}
222 */
223 mw.widgets.ExpiryWidget.prototype.getValue = function () {
224 return this.relativeField.getValue();
225 };
226
227 }() );