( function ( mw ) { /** * Quick links menu option widget * * @class * @extends OO.ui.Widget * @mixins OO.ui.mixin.LabelElement * @mixins OO.ui.mixin.IconElement * @mixins OO.ui.mixin.TitledElement * * @constructor * @param {mw.rcfilters.dm.SavedQueryItemModel} model View model * @param {Object} [config] Configuration object * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups */ mw.rcfilters.ui.SavedLinksListItemWidget = function MwRcfiltersUiSavedLinksListWidget( model, config ) { config = config || {}; this.model = model; // Parent mw.rcfilters.ui.SavedLinksListItemWidget.parent.call( this, $.extend( { data: this.model.getID() }, config ) ); // Mixin constructors OO.ui.mixin.LabelElement.call( this, $.extend( { label: this.model.getLabel() }, config ) ); OO.ui.mixin.IconElement.call( this, $.extend( { icon: '' }, config ) ); OO.ui.mixin.TitledElement.call( this, $.extend( { title: this.model.getLabel() }, config ) ); this.edit = false; this.$overlay = config.$overlay || this.$element; this.popupButton = new OO.ui.ButtonWidget( { classes: [ 'mw-rcfilters-ui-savedLinksListItemWidget-button' ], icon: 'ellipsis', framed: false } ); this.menu = new OO.ui.MenuSelectWidget( { classes: [ 'mw-rcfilters-ui-savedLinksListItemWidget-menu' ], widget: this.popupButton, width: 200, horizontalPosition: 'end', $floatableContainer: this.popupButton.$element, items: [ new OO.ui.MenuOptionWidget( { data: 'edit', icon: 'edit', label: mw.msg( 'rcfilters-savedqueries-rename' ) } ), new OO.ui.MenuOptionWidget( { data: 'delete', icon: 'close', label: mw.msg( 'rcfilters-savedqueries-remove' ) } ), new OO.ui.MenuOptionWidget( { data: 'default', icon: 'pushPin', label: mw.msg( 'rcfilters-savedqueries-setdefault' ) } ) ] } ); this.editInput = new OO.ui.TextInputWidget( { classes: [ 'mw-rcfilters-ui-savedLinksListItemWidget-input' ] } ); this.saveButton = new OO.ui.ButtonWidget( { icon: 'check', flags: [ 'primary', 'progressive' ] } ); this.toggleEdit( false ); // Events this.model.connect( this, { update: 'onModelUpdate' } ); this.popupButton.connect( this, { click: 'onPopupButtonClick' } ); this.menu.connect( this, { choose: 'onMenuChoose' } ); this.saveButton.connect( this, { click: 'save' } ); this.editInput.connect( this, { change: 'onInputChange', enter: 'save' } ); this.editInput.$input.on( { blur: this.onInputBlur.bind( this ), keyup: this.onInputKeyup.bind( this ) } ); this.$element.on( { click: this.onClick.bind( this ) } ); this.$label.on( { click: this.onClick.bind( this ) } ); this.$icon.on( { click: this.onDefaultIconClick.bind( this ) } ); // Prevent propagation on mousedown for the save button // so the menu doesn't close this.saveButton.$element.on( { mousedown: function () { return false; } } ); // Initialize this.toggleDefault( !!this.model.isDefault() ); this.$overlay.append( this.menu.$element ); this.$element .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget' ) .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-query-' + this.model.getID() ) .append( $( '
' ) .addClass( 'mw-rcfilters-ui-table' ) .append( $( '
' ) .addClass( 'mw-rcfilters-ui-row' ) .append( $( '
' ) .addClass( 'mw-rcfilters-ui-cell' ) .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-content' ) .append( this.$label .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-label' ), this.editInput.$element, this.saveButton.$element ), $( '
' ) .addClass( 'mw-rcfilters-ui-cell' ) .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-icon' ) .append( this.$icon ), this.popupButton.$element .addClass( 'mw-rcfilters-ui-cell' ) ) ) ); }; /* Initialization */ OO.inheritClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.Widget ); OO.mixinClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.mixin.LabelElement ); OO.mixinClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.mixin.IconElement ); OO.mixinClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.mixin.TitledElement ); /* Events */ /** * @event delete * * The delete option was selected for this item */ /** * @event default * @param {boolean} default Item is default * * The 'make default' option was selected for this item */ /** * @event edit * @param {string} newLabel New label for the query * * The label has been edited */ /* Methods */ /** * Respond to model update event */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onModelUpdate = function () { this.setLabel( this.model.getLabel() ); this.toggleDefault( this.model.isDefault() ); }; /** * Respond to click on the element or label * * @fires click */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onClick = function () { if ( !this.editing ) { this.emit( 'click' ); } }; /** * Respond to click on the 'default' icon. Open the submenu where the * default state can be changed. * * @return {boolean} false */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onDefaultIconClick = function () { this.menu.toggle(); return false; }; /** * Respond to popup button click event */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onPopupButtonClick = function () { this.menu.toggle(); }; /** * Respond to menu choose event * * @param {OO.ui.MenuOptionWidget} item Chosen item * @fires delete * @fires default */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onMenuChoose = function ( item ) { var action = item.getData(); if ( action === 'edit' ) { this.toggleEdit( true ); } else if ( action === 'delete' ) { this.emit( 'delete' ); } else if ( action === 'default' ) { this.emit( 'default', !this.default ); } // Reset selected this.menu.selectItem( null ); // Close the menu this.menu.toggle( false ); }; /** * Respond to input keyup event, this is the way to intercept 'escape' key * * @param {jQuery.Event} e Event data * @return {boolean} false */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onInputKeyup = function ( e ) { if ( e.which === OO.ui.Keys.ESCAPE ) { // Return the input to the original label this.editInput.setValue( this.getLabel() ); this.toggleEdit( false ); return false; } }; /** * Respond to blur event on the input */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onInputBlur = function () { this.save(); // Whether the save succeeded or not, the input-blur event // means we need to cancel editing mode this.toggleEdit( false ); }; /** * Respond to input change event * * @param {string} value Input value */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onInputChange = function ( value ) { value = value.trim(); this.saveButton.setDisabled( !value ); }; /** * Save the name of the query * * @param {string} [value] The value to save * @fires edit */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.save = function () { var value = this.editInput.getValue().trim(); if ( value ) { this.emit( 'edit', value ); this.toggleEdit( false ); } }; /** * Toggle edit mode on this widget * * @param {boolean} isEdit Widget is in edit mode */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.toggleEdit = function ( isEdit ) { isEdit = isEdit === undefined ? !this.editing : isEdit; if ( this.editing !== isEdit ) { this.$element.toggleClass( 'mw-rcfilters-ui-savedLinksListItemWidget-edit', isEdit ); this.editInput.setValue( this.getLabel() ); this.editInput.toggle( isEdit ); this.$label.toggleClass( 'oo-ui-element-hidden', isEdit ); this.$icon.toggleClass( 'oo-ui-element-hidden', isEdit ); this.popupButton.toggle( !isEdit ); this.saveButton.toggle( isEdit ); if ( isEdit ) { this.editInput.$input.focus(); } this.editing = isEdit; } }; /** * Toggle default this widget * * @param {boolean} isDefault This item is default */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.toggleDefault = function ( isDefault ) { isDefault = isDefault === undefined ? !this.default : isDefault; if ( this.default !== isDefault ) { this.default = isDefault; this.setIcon( this.default ? 'pushPin' : '' ); this.menu.findItemFromData( 'default' ).setLabel( this.default ? mw.msg( 'rcfilters-savedqueries-unsetdefault' ) : mw.msg( 'rcfilters-savedqueries-setdefault' ) ); } }; /** * Get item ID * * @return {string} Query identifier */ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.getID = function () { return this.model.getID(); }; }( mediaWiki ) );