build: Bump eslint-config-wikimedia from 0.4.0 to 0.5.0
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / ui / mw.rcfilters.ui.SavedLinksListItemWidget.js
1 ( function ( mw ) {
2 /**
3 * Quick links menu option widget
4 *
5 * @class
6 * @extends OO.ui.Widget
7 * @mixins OO.ui.mixin.LabelElement
8 * @mixins OO.ui.mixin.IconElement
9 * @mixins OO.ui.mixin.TitledElement
10 *
11 * @constructor
12 * @param {mw.rcfilters.dm.SavedQueryItemModel} model View model
13 * @param {Object} [config] Configuration object
14 * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
15 */
16 mw.rcfilters.ui.SavedLinksListItemWidget = function MwRcfiltersUiSavedLinksListWidget( model, config ) {
17 config = config || {};
18
19 this.model = model;
20
21 // Parent
22 mw.rcfilters.ui.SavedLinksListItemWidget.parent.call( this, $.extend( {
23 data: this.model.getID()
24 }, config ) );
25
26 // Mixin constructors
27 OO.ui.mixin.LabelElement.call( this, $.extend( {
28 label: this.model.getLabel()
29 }, config ) );
30 OO.ui.mixin.IconElement.call( this, $.extend( {
31 icon: ''
32 }, config ) );
33 OO.ui.mixin.TitledElement.call( this, $.extend( {
34 title: this.model.getLabel()
35 }, config ) );
36
37 this.edit = false;
38 this.$overlay = config.$overlay || this.$element;
39
40 this.popupButton = new OO.ui.ButtonWidget( {
41 classes: [ 'mw-rcfilters-ui-savedLinksListItemWidget-button' ],
42 icon: 'ellipsis',
43 framed: false
44 } );
45 this.menu = new OO.ui.MenuSelectWidget( {
46 classes: [ 'mw-rcfilters-ui-savedLinksListItemWidget-menu' ],
47 widget: this.popupButton,
48 width: 200,
49 horizontalPosition: 'end',
50 $floatableContainer: this.popupButton.$element,
51 items: [
52 new OO.ui.MenuOptionWidget( {
53 data: 'edit',
54 icon: 'edit',
55 label: mw.msg( 'rcfilters-savedqueries-rename' )
56 } ),
57 new OO.ui.MenuOptionWidget( {
58 data: 'delete',
59 icon: 'close',
60 label: mw.msg( 'rcfilters-savedqueries-remove' )
61 } ),
62 new OO.ui.MenuOptionWidget( {
63 data: 'default',
64 icon: 'pushPin',
65 label: mw.msg( 'rcfilters-savedqueries-setdefault' )
66 } )
67 ]
68 } );
69
70 this.editInput = new OO.ui.TextInputWidget( {
71 classes: [ 'mw-rcfilters-ui-savedLinksListItemWidget-input' ]
72 } );
73 this.saveButton = new OO.ui.ButtonWidget( {
74 icon: 'check',
75 flags: [ 'primary', 'progressive' ]
76 } );
77 this.toggleEdit( false );
78
79 // Events
80 this.model.connect( this, { update: 'onModelUpdate' } );
81 this.popupButton.connect( this, { click: 'onPopupButtonClick' } );
82 this.menu.connect( this, {
83 choose: 'onMenuChoose'
84 } );
85 this.saveButton.connect( this, { click: 'save' } );
86 this.editInput.connect( this, {
87 change: 'onInputChange',
88 enter: 'save'
89 } );
90 this.editInput.$input.on( {
91 blur: this.onInputBlur.bind( this ),
92 keyup: this.onInputKeyup.bind( this )
93 } );
94 this.$element.on( { click: this.onClick.bind( this ) } );
95 this.$label.on( { click: this.onClick.bind( this ) } );
96 // Prevent propagation on mousedown for the save button
97 // so the menu doesn't close
98 this.saveButton.$element.on( { mousedown: function () { return false; } } );
99
100 // Initialize
101 this.toggleDefault( !!this.model.isDefault() );
102 this.$overlay.append( this.menu.$element );
103 this.$element
104 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget' )
105 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-query-' + this.model.getID() )
106 .append(
107 $( '<div>' )
108 .addClass( 'mw-rcfilters-ui-table' )
109 .append(
110 $( '<div>' )
111 .addClass( 'mw-rcfilters-ui-row' )
112 .append(
113 $( '<div>' )
114 .addClass( 'mw-rcfilters-ui-cell' )
115 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-content' )
116 .append(
117 this.$label
118 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-label' ),
119 this.editInput.$element,
120 this.saveButton.$element
121 ),
122 $( '<div>' )
123 .addClass( 'mw-rcfilters-ui-cell' )
124 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-icon' )
125 .append( this.$icon ),
126 this.popupButton.$element
127 .addClass( 'mw-rcfilters-ui-cell' )
128 )
129 )
130 );
131 };
132
133 /* Initialization */
134 OO.inheritClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.Widget );
135 OO.mixinClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.mixin.LabelElement );
136 OO.mixinClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.mixin.IconElement );
137 OO.mixinClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.mixin.TitledElement );
138
139 /* Events */
140
141 /**
142 * @event delete
143 *
144 * The delete option was selected for this item
145 */
146
147 /**
148 * @event default
149 * @param {boolean} default Item is default
150 *
151 * The 'make default' option was selected for this item
152 */
153
154 /**
155 * @event edit
156 * @param {string} newLabel New label for the query
157 *
158 * The label has been edited
159 */
160
161 /* Methods */
162
163 /**
164 * Respond to model update event
165 */
166 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onModelUpdate = function () {
167 this.setLabel( this.model.getLabel() );
168 this.toggleDefault( this.model.isDefault() );
169 };
170
171 /**
172 * Respond to click on the element or label
173 *
174 * @fires click
175 */
176 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onClick = function () {
177 if ( !this.editing ) {
178 this.emit( 'click' );
179 }
180 };
181 /**
182 * Respond to popup button click event
183 */
184 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onPopupButtonClick = function () {
185 this.menu.toggle();
186 };
187
188 /**
189 * Respond to menu choose event
190 *
191 * @param {OO.ui.MenuOptionWidget} item Chosen item
192 * @fires delete
193 * @fires default
194 */
195 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onMenuChoose = function ( item ) {
196 var action = item.getData();
197
198 if ( action === 'edit' ) {
199 this.toggleEdit( true );
200 } else if ( action === 'delete' ) {
201 this.emit( 'delete' );
202 } else if ( action === 'default' ) {
203 this.emit( 'default', !this.default );
204 }
205 // Reset selected
206 this.menu.selectItem( null );
207 // Close the menu
208 this.menu.toggle( false );
209 };
210
211 /**
212 * Respond to input keyup event, this is the way to intercept 'escape' key
213 *
214 * @param {jQuery.Event} e Event data
215 * @return {boolean} false
216 */
217 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onInputKeyup = function ( e ) {
218 if ( e.which === OO.ui.Keys.ESCAPE ) {
219 // Return the input to the original label
220 this.editInput.setValue( this.getLabel() );
221 this.toggleEdit( false );
222 return false;
223 }
224 };
225
226 /**
227 * Respond to blur event on the input
228 */
229 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onInputBlur = function () {
230 this.save();
231
232 // Whether the save succeeded or not, the input-blur event
233 // means we need to cancel editing mode
234 this.toggleEdit( false );
235 };
236
237 /**
238 * Respond to input change event
239 *
240 * @param {string} value Input value
241 */
242 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onInputChange = function ( value ) {
243 value = value.trim();
244
245 this.saveButton.setDisabled( !value );
246 };
247
248 /**
249 * Save the name of the query
250 *
251 * @param {string} [value] The value to save
252 * @fires edit
253 */
254 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.save = function () {
255 var value = this.editInput.getValue().trim();
256
257 if ( value ) {
258 this.emit( 'edit', value );
259 this.toggleEdit( false );
260 }
261 };
262
263 /**
264 * Toggle edit mode on this widget
265 *
266 * @param {boolean} isEdit Widget is in edit mode
267 */
268 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.toggleEdit = function ( isEdit ) {
269 isEdit = isEdit === undefined ? !this.editing : isEdit;
270
271 if ( this.editing !== isEdit ) {
272 this.$element.toggleClass( 'mw-rcfilters-ui-savedLinksListItemWidget-edit', isEdit );
273 this.editInput.setValue( this.getLabel() );
274
275 this.editInput.toggle( isEdit );
276 this.$label.toggleClass( 'oo-ui-element-hidden', isEdit );
277 this.$icon.toggleClass( 'oo-ui-element-hidden', isEdit );
278 this.popupButton.toggle( !isEdit );
279 this.saveButton.toggle( isEdit );
280
281 if ( isEdit ) {
282 this.editInput.$input.focus();
283 }
284 this.editing = isEdit;
285 }
286 };
287
288 /**
289 * Toggle default this widget
290 *
291 * @param {boolean} isDefault This item is default
292 */
293 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.toggleDefault = function ( isDefault ) {
294 isDefault = isDefault === undefined ? !this.default : isDefault;
295
296 if ( this.default !== isDefault ) {
297 this.default = isDefault;
298 this.setIcon( this.default ? 'pushPin' : '' );
299 this.menu.getItemFromData( 'default' ).setLabel(
300 this.default ?
301 mw.msg( 'rcfilters-savedqueries-unsetdefault' ) :
302 mw.msg( 'rcfilters-savedqueries-setdefault' )
303 );
304 }
305 };
306
307 /**
308 * Get item ID
309 *
310 * @return {string} Query identifier
311 */
312 mw.rcfilters.ui.SavedLinksListItemWidget.prototype.getID = function () {
313 return this.model.getID();
314 };
315
316 }( mediaWiki ) );