Merge "RCFilters UI: Add popup footer with feedback link"
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / ui / mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js
index bf80cd6..8e0b259 100644 (file)
         * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
         */
        mw.rcfilters.ui.FilterCapsuleMultiselectWidget = function MwRcfiltersUiFilterCapsuleMultiselectWidget( controller, model, filterInput, config ) {
+               var title = new OO.ui.LabelWidget( {
+                               label: mw.msg( 'rcfilters-activefilters' ),
+                               classes: [ 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-wrapper-content-title' ]
+                       } ),
+                       $contentWrapper = $( '<div>' )
+                               .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-wrapper' );
+
+               this.$overlay = config.$overlay || this.$element;
+
                // Parent
-               mw.rcfilters.ui.FilterCapsuleMultiselectWidget.parent.call( this, $.extend( {
-                       $autoCloseIgnore: filterInput.$element
+               mw.rcfilters.ui.FilterCapsuleMultiselectWidget.parent.call( this, $.extend( true, {
+                       popup: { $autoCloseIgnore: filterInput.$element.add( this.$overlay ) }
                }, config ) );
 
                this.controller = controller;
                this.model = model;
-               this.$overlay = config.$overlay || this.$element;
-
                this.filterInput = filterInput;
-
-               this.$content.prepend(
-                       $( '<div>' )
-                               .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-content-title' )
-                               .text( mw.msg( 'rcfilters-activefilters' ) )
-               );
+               this.isSelecting = false;
 
                this.resetButton = new OO.ui.ButtonWidget( {
                        icon: 'trash',
                        label: mw.msg( 'rcfilters-empty-filter' ),
                        classes: [ 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-emptyFilters' ]
                } );
+               this.$content.append( this.emptyFilterMessage.$element );
 
                // Events
                this.resetButton.connect( this, { click: 'onResetButtonClick' } );
-               this.model.connect( this, { itemUpdate: 'onModelItemUpdate' } );
+               this.model.connect( this, {
+                       itemUpdate: 'onModelItemUpdate',
+                       highlightChange: 'onModelHighlightChange'
+               } );
+               this.aggregate( { click: 'capsuleItemClick' } );
+
                // Add the filterInput as trigger
                this.filterInput.$input
                        .on( 'focus', this.focus.bind( this ) );
 
+               // Build the content
+               $contentWrapper.append(
+                       title.$element,
+                       $( '<div>' )
+                               .addClass( 'mw-rcfilters-ui-table' )
+                               .append(
+                                       // The filter list and button should appear side by side regardless of how
+                                       // wide the button is; the button also changes its width depending
+                                       // on language and its state, so the safest way to present both side
+                                       // by side is with a table layout
+                                       $( '<div>' )
+                                               .addClass( 'mw-rcfilters-ui-row' )
+                                               .append(
+                                                       this.$content
+                                                               .addClass( 'mw-rcfilters-ui-cell' )
+                                                               .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell-filters' ),
+                                                       $( '<div>' )
+                                                               .addClass( 'mw-rcfilters-ui-cell' )
+                                                               .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell-reset' )
+                                                               .append( this.resetButton.$element )
+                                               )
+                               )
+               );
+
                // Initialize
-               this.$content.append( this.emptyFilterMessage.$element );
-               this.$handle
-                       .append(
-                               // The content and button should appear side by side regardless of how
-                               // wide the button is; the button also changes its width depending
-                               // on language and its state, so the safest way to present both side
-                               // by side is with a table layout
-                               $( '<div>' )
-                                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-table' )
-                                       .append(
-                                               $( '<div>' )
-                                                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-row' )
-                                                       .append(
-                                                               $( '<div>' )
-                                                                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-content' )
-                                                                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell' )
-                                                                       .append( this.$content ),
-                                                               $( '<div>' )
-                                                                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell' )
-                                                                       .append( this.resetButton.$element )
-                                                       )
-                                       )
-                       );
+               this.$handle.append( $contentWrapper );
 
                this.$element
                        .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget' );
         * @param {mw.rcfilters.dm.FilterItem} item Filter item model
         */
        mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.onModelItemUpdate = function ( item ) {
-               if ( item.isSelected() ) {
+               if (
+                       item.isSelected() ||
+                       (
+                               this.model.isHighlightEnabled() &&
+                               item.isHighlightSupported() &&
+                               item.getHighlightColor()
+                       )
+               ) {
                        this.addItemByName( item.getName() );
                } else {
                        this.removeItemByName( item.getName() );
                this.reevaluateResetRestoreState();
        };
 
+       /**
+        * Respond to highlightChange event
+        *
+        * @param {boolean} isHighlightEnabled Highlight is enabled
+        */
+       mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.onModelHighlightChange = function ( isHighlightEnabled ) {
+               var highlightedItems = this.model.getHighlightedItems();
+
+               if ( isHighlightEnabled ) {
+                       // Add capsule widgets
+                       highlightedItems.forEach( function ( filterItem ) {
+                               this.addItemByName( filterItem.getName() );
+                       }.bind( this ) );
+               } else {
+                       // Remove capsule widgets if they're not selected
+                       highlightedItems.forEach( function ( filterItem ) {
+                               if ( !filterItem.isSelected() ) {
+                                       this.removeItemByName( filterItem.getName() );
+                               }
+                       }.bind( this ) );
+               }
+       };
+
        /**
         * Respond to click event on the reset button
         */
                        return;
                }
 
-               return new mw.rcfilters.ui.CapsuleItemWidget( item, { $overlay: this.$overlay } );
+               return new mw.rcfilters.ui.CapsuleItemWidget(
+                       this.controller,
+                       item,
+                       { $overlay: this.$overlay }
+               );
        };
 
        /**
                this.focus();
        };
 
-       /**
-        * @inheritdoc
-        */
-       mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.removeItems = function ( items ) {
-               var filterData = {};
-
-               // Parent
-               mw.rcfilters.ui.FilterCapsuleMultiselectWidget.parent.prototype.removeItems.call( this, items );
-
-               items.forEach( function ( itemWidget ) {
-                       filterData[ itemWidget.getData() ] = false;
-               } );
-
-               // Update the model
-               this.model.updateFilters( filterData );
-       };
-
        /**
         * @inheritdoc
         */
                this.menu.selectItem();
                this.menu.highlightItem();
        };
+
+       /**
+        * @inheritdoc
+        */
+       mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.removeItems = function ( items ) {
+               // Parent call
+               mw.rcfilters.ui.FilterCapsuleMultiselectWidget.parent.prototype.removeItems.call( this, items );
+
+               // Destroy the item widget when it is removed
+               // This is done because we re-add items by recreating them, rather than hiding them
+               // and items include popups, that will just continue to be created and appended
+               // unnecessarily.
+               items.forEach( function ( widget ) {
+                       widget.destroy();
+               } );
+       };
+
+       /**
+        * Override 'editItem' since it tries to use $input which does
+        * not exist when a popup is available.
+        */
+       mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.editItem = function () {};
 }( mediaWiki, jQuery ) );