Fix order of @var parameter in PHP
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / ui / SavedLinksListItemWidget.js
1 ( function () {
2 /**
3 * Quick links menu option widget
4 *
5 * @class mw.rcfilters.ui.SavedLinksListItemWidget
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 var SavedLinksListItemWidget = function MwRcfiltersUiSavedLinksListWidget( model, config ) {
17 config = config || {};
18
19 this.model = model;
20
21 // Parent
22 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: 'trash',
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 this.$icon.on( { click: this.onDefaultIconClick.bind( this ) } );
97 // Prevent propagation on mousedown for the save button
98 // so the menu doesn't close
99 this.saveButton.$element.on( { mousedown: function () {
100 return false;
101 } } );
102
103 // Initialize
104 this.toggleDefault( !!this.model.isDefault() );
105 this.$overlay.append( this.menu.$element );
106 this.$element
107 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget' )
108 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-query-' + this.model.getID() )
109 .append(
110 $( '<div>' )
111 .addClass( 'mw-rcfilters-ui-table' )
112 .append(
113 $( '<div>' )
114 .addClass( 'mw-rcfilters-ui-row' )
115 .append(
116 $( '<div>' )
117 .addClass( 'mw-rcfilters-ui-cell' )
118 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-content' )
119 .append(
120 this.$label
121 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-label' ),
122 this.editInput.$element,
123 this.saveButton.$element
124 ),
125 $( '<div>' )
126 .addClass( 'mw-rcfilters-ui-cell' )
127 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-icon' )
128 .append( this.$icon ),
129 this.popupButton.$element
130 .addClass( 'mw-rcfilters-ui-cell' )
131 )
132 )
133 );
134 };
135
136 /* Initialization */
137 OO.inheritClass( SavedLinksListItemWidget, OO.ui.Widget );
138 OO.mixinClass( SavedLinksListItemWidget, OO.ui.mixin.LabelElement );
139 OO.mixinClass( SavedLinksListItemWidget, OO.ui.mixin.IconElement );
140 OO.mixinClass( SavedLinksListItemWidget, OO.ui.mixin.TitledElement );
141
142 /* Events */
143
144 /**
145 * @event delete
146 *
147 * The delete option was selected for this item
148 */
149
150 /**
151 * @event default
152 * @param {boolean} default Item is default
153 *
154 * The 'make default' option was selected for this item
155 */
156
157 /**
158 * @event edit
159 * @param {string} newLabel New label for the query
160 *
161 * The label has been edited
162 */
163
164 /* Methods */
165
166 /**
167 * Respond to model update event
168 */
169 SavedLinksListItemWidget.prototype.onModelUpdate = function () {
170 this.setLabel( this.model.getLabel() );
171 this.toggleDefault( this.model.isDefault() );
172 };
173
174 /**
175 * Respond to click on the element or label
176 *
177 * @fires click
178 */
179 SavedLinksListItemWidget.prototype.onClick = function () {
180 if ( !this.editing ) {
181 this.emit( 'click' );
182 }
183 };
184
185 /**
186 * Respond to click on the 'default' icon. Open the submenu where the
187 * default state can be changed.
188 *
189 * @return {boolean} false
190 */
191 SavedLinksListItemWidget.prototype.onDefaultIconClick = function () {
192 this.menu.toggle();
193 return false;
194 };
195
196 /**
197 * Respond to popup button click event
198 */
199 SavedLinksListItemWidget.prototype.onPopupButtonClick = function () {
200 this.menu.toggle();
201 };
202
203 /**
204 * Respond to menu choose event
205 *
206 * @param {OO.ui.MenuOptionWidget} item Chosen item
207 * @fires delete
208 * @fires default
209 */
210 SavedLinksListItemWidget.prototype.onMenuChoose = function ( item ) {
211 var action = item.getData();
212
213 if ( action === 'edit' ) {
214 this.toggleEdit( true );
215 } else if ( action === 'delete' ) {
216 this.emit( 'delete' );
217 } else if ( action === 'default' ) {
218 this.emit( 'default', !this.default );
219 }
220 // Reset selected
221 this.menu.selectItem( null );
222 // Close the menu
223 this.menu.toggle( false );
224 };
225
226 /**
227 * Respond to input keyup event, this is the way to intercept 'escape' key
228 *
229 * @param {jQuery.Event} e Event data
230 * @return {boolean} false
231 */
232 SavedLinksListItemWidget.prototype.onInputKeyup = function ( e ) {
233 if ( e.which === OO.ui.Keys.ESCAPE ) {
234 // Return the input to the original label
235 this.editInput.setValue( this.getLabel() );
236 this.toggleEdit( false );
237 return false;
238 }
239 };
240
241 /**
242 * Respond to blur event on the input
243 */
244 SavedLinksListItemWidget.prototype.onInputBlur = function () {
245 this.save();
246
247 // Whether the save succeeded or not, the input-blur event
248 // means we need to cancel editing mode
249 this.toggleEdit( false );
250 };
251
252 /**
253 * Respond to input change event
254 *
255 * @param {string} value Input value
256 */
257 SavedLinksListItemWidget.prototype.onInputChange = function ( value ) {
258 value = value.trim();
259
260 this.saveButton.setDisabled( !value );
261 };
262
263 /**
264 * Save the name of the query
265 *
266 * @param {string} [value] The value to save
267 * @fires edit
268 */
269 SavedLinksListItemWidget.prototype.save = function () {
270 var value = this.editInput.getValue().trim();
271
272 if ( value ) {
273 this.emit( 'edit', value );
274 this.toggleEdit( false );
275 }
276 };
277
278 /**
279 * Toggle edit mode on this widget
280 *
281 * @param {boolean} isEdit Widget is in edit mode
282 */
283 SavedLinksListItemWidget.prototype.toggleEdit = function ( isEdit ) {
284 isEdit = isEdit === undefined ? !this.editing : isEdit;
285
286 if ( this.editing !== isEdit ) {
287 this.$element.toggleClass( 'mw-rcfilters-ui-savedLinksListItemWidget-edit', isEdit );
288 this.editInput.setValue( this.getLabel() );
289
290 this.editInput.toggle( isEdit );
291 this.$label.toggleClass( 'oo-ui-element-hidden', isEdit );
292 this.$icon.toggleClass( 'oo-ui-element-hidden', isEdit );
293 this.popupButton.toggle( !isEdit );
294 this.saveButton.toggle( isEdit );
295
296 if ( isEdit ) {
297 this.editInput.$input.trigger( 'focus' );
298 }
299 this.editing = isEdit;
300 }
301 };
302
303 /**
304 * Toggle default this widget
305 *
306 * @param {boolean} isDefault This item is default
307 */
308 SavedLinksListItemWidget.prototype.toggleDefault = function ( isDefault ) {
309 isDefault = isDefault === undefined ? !this.default : isDefault;
310
311 if ( this.default !== isDefault ) {
312 this.default = isDefault;
313 this.setIcon( this.default ? 'pushPin' : '' );
314 this.menu.findItemFromData( 'default' ).setLabel(
315 this.default ?
316 mw.msg( 'rcfilters-savedqueries-unsetdefault' ) :
317 mw.msg( 'rcfilters-savedqueries-setdefault' )
318 );
319 }
320 };
321
322 /**
323 * Get item ID
324 *
325 * @return {string} Query identifier
326 */
327 SavedLinksListItemWidget.prototype.getID = function () {
328 return this.model.getID();
329 };
330
331 module.exports = SavedLinksListItemWidget;
332
333 }() );