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