3 * Quick links menu option widget
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
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
16 var SavedLinksListItemWidget
= function MwRcfiltersUiSavedLinksListWidget( model
, config
) {
17 config
= config
|| {};
22 SavedLinksListItemWidget
.parent
.call( this, $.extend( {
23 data
: this.model
.getID()
27 OO
.ui
.mixin
.LabelElement
.call( this, $.extend( {
28 label
: this.model
.getLabel()
30 OO
.ui
.mixin
.IconElement
.call( this, $.extend( {
33 OO
.ui
.mixin
.TitledElement
.call( this, $.extend( {
34 title
: this.model
.getLabel()
38 this.$overlay
= config
.$overlay
|| this.$element
;
40 this.popupButton
= new OO
.ui
.ButtonWidget( {
41 classes
: [ 'mw-rcfilters-ui-savedLinksListItemWidget-button' ],
45 this.menu
= new OO
.ui
.MenuSelectWidget( {
46 classes
: [ 'mw-rcfilters-ui-savedLinksListItemWidget-menu' ],
47 widget
: this.popupButton
,
49 horizontalPosition
: 'end',
50 $floatableContainer
: this.popupButton
.$element
,
52 new OO
.ui
.MenuOptionWidget( {
55 label
: mw
.msg( 'rcfilters-savedqueries-rename' )
57 new OO
.ui
.MenuOptionWidget( {
60 label
: mw
.msg( 'rcfilters-savedqueries-remove' )
62 new OO
.ui
.MenuOptionWidget( {
65 label
: mw
.msg( 'rcfilters-savedqueries-setdefault' )
70 this.editInput
= new OO
.ui
.TextInputWidget( {
71 classes
: [ 'mw-rcfilters-ui-savedLinksListItemWidget-input' ]
73 this.saveButton
= new OO
.ui
.ButtonWidget( {
75 flags
: [ 'primary', 'progressive' ]
77 this.toggleEdit( false );
80 this.model
.connect( this, { update
: 'onModelUpdate' } );
81 this.popupButton
.connect( this, { click
: 'onPopupButtonClick' } );
82 this.menu
.connect( this, {
83 choose
: 'onMenuChoose'
85 this.saveButton
.connect( this, { click
: 'save' } );
86 this.editInput
.connect( this, {
87 change
: 'onInputChange',
90 this.editInput
.$input
.on( {
91 blur
: this.onInputBlur
.bind( this ),
92 keyup
: this.onInputKeyup
.bind( this )
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 () {
104 this.toggleDefault( !!this.model
.isDefault() );
105 this.$overlay
.append( this.menu
.$element
);
107 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget' )
108 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-query-' + this.model
.getID() )
111 .addClass( 'mw-rcfilters-ui-table' )
114 .addClass( 'mw-rcfilters-ui-row' )
117 .addClass( 'mw-rcfilters-ui-cell' )
118 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-content' )
121 .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-label' ),
122 this.editInput
.$element
,
123 this.saveButton
.$element
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' )
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
);
147 * The delete option was selected for this item
152 * @param {boolean} default Item is default
154 * The 'make default' option was selected for this item
159 * @param {string} newLabel New label for the query
161 * The label has been edited
167 * Respond to model update event
169 SavedLinksListItemWidget
.prototype.onModelUpdate = function () {
170 this.setLabel( this.model
.getLabel() );
171 this.toggleDefault( this.model
.isDefault() );
175 * Respond to click on the element or label
179 SavedLinksListItemWidget
.prototype.onClick = function () {
180 if ( !this.editing
) {
181 this.emit( 'click' );
186 * Respond to click on the 'default' icon. Open the submenu where the
187 * default state can be changed.
189 * @return {boolean} false
191 SavedLinksListItemWidget
.prototype.onDefaultIconClick = function () {
197 * Respond to popup button click event
199 SavedLinksListItemWidget
.prototype.onPopupButtonClick = function () {
204 * Respond to menu choose event
206 * @param {OO.ui.MenuOptionWidget} item Chosen item
210 SavedLinksListItemWidget
.prototype.onMenuChoose = function ( item
) {
211 var action
= item
.getData();
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 );
221 this.menu
.selectItem( null );
223 this.menu
.toggle( false );
227 * Respond to input keyup event, this is the way to intercept 'escape' key
229 * @param {jQuery.Event} e Event data
230 * @return {boolean} false
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 );
242 * Respond to blur event on the input
244 SavedLinksListItemWidget
.prototype.onInputBlur = function () {
247 // Whether the save succeeded or not, the input-blur event
248 // means we need to cancel editing mode
249 this.toggleEdit( false );
253 * Respond to input change event
255 * @param {string} value Input value
257 SavedLinksListItemWidget
.prototype.onInputChange = function ( value
) {
258 value
= value
.trim();
260 this.saveButton
.setDisabled( !value
);
264 * Save the name of the query
266 * @param {string} [value] The value to save
269 SavedLinksListItemWidget
.prototype.save = function () {
270 var value
= this.editInput
.getValue().trim();
273 this.emit( 'edit', value
);
274 this.toggleEdit( false );
279 * Toggle edit mode on this widget
281 * @param {boolean} isEdit Widget is in edit mode
283 SavedLinksListItemWidget
.prototype.toggleEdit = function ( isEdit
) {
284 isEdit
= isEdit
=== undefined ? !this.editing
: isEdit
;
286 if ( this.editing
!== isEdit
) {
287 this.$element
.toggleClass( 'mw-rcfilters-ui-savedLinksListItemWidget-edit', isEdit
);
288 this.editInput
.setValue( this.getLabel() );
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
);
297 this.editInput
.$input
.trigger( 'focus' );
299 this.editing
= isEdit
;
304 * Toggle default this widget
306 * @param {boolean} isDefault This item is default
308 SavedLinksListItemWidget
.prototype.toggleDefault = function ( isDefault
) {
309 isDefault
= isDefault
=== undefined ? !this.default : isDefault
;
311 if ( this.default !== isDefault
) {
312 this.default = isDefault
;
313 this.setIcon( this.default ? 'pushPin' : '' );
314 this.menu
.findItemFromData( 'default' ).setLabel(
316 mw
.msg( 'rcfilters-savedqueries-unsetdefault' ) :
317 mw
.msg( 'rcfilters-savedqueries-setdefault' )
325 * @return {string} Query identifier
327 SavedLinksListItemWidget
.prototype.getID = function () {
328 return this.model
.getID();
331 module
.exports
= SavedLinksListItemWidget
;