Merge "Create IResultWrapper interface for type-hints"
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / dm / mw.rcfilters.dm.FilterGroup.js
index bc911f4..14a610b 100644 (file)
@@ -6,25 +6,31 @@
         * @mixins OO.EmitterList
         *
         * @constructor
+        * @param {string} name Group name
         * @param {Object} [config] Configuration options
         * @cfg {string} [type='send_unselected_if_any'] Group type
         * @cfg {string} [title] Group title
         * @cfg {string} [separator='|'] Value separator for 'string_options' groups
-        * @cfg {string} [exclusionType='default'] Group exclusion type
         * @cfg {boolean} [active] Group is active
+        * @cfg {boolean} [fullCoverage] This filters in this group collectively cover all results
         */
-       mw.rcfilters.dm.FilterGroup = function MwRcfiltersDmFilterGroup( config ) {
+       mw.rcfilters.dm.FilterGroup = function MwRcfiltersDmFilterGroup( name, config ) {
                config = config || {};
 
                // Mixin constructor
                OO.EventEmitter.call( this );
                OO.EmitterList.call( this );
 
+               this.name = name;
                this.type = config.type || 'send_unselected_if_any';
                this.title = config.title;
                this.separator = config.separator || '|';
-               this.exclusionType = config.exclusionType || 'default';
+
                this.active = !!config.active;
+               this.fullCoverage = !!config.fullCoverage;
+
+               this.aggregate( { update: 'filterItemUpdate' } );
+               this.connect( this, { filterItemUpdate: 'onFilterItemUpdate' } );
        };
 
        /* Initialization */
        /* Methods */
 
        /**
-        * Check the active status of the group and set it accordingly.
+        * Respond to filterItem update event
         *
         * @fires update
         */
-       mw.rcfilters.dm.FilterGroup.prototype.checkActive = function () {
-               var active,
-                       count = 0;
-
-               // Recheck group activity
-               this.getItems().forEach( function ( filterItem ) {
-                       count += Number( filterItem.isSelected() );
-               } );
-
-               active = (
-                       count > 0 &&
-                       count < this.getItemCount()
-               );
+       mw.rcfilters.dm.FilterGroup.prototype.onFilterItemUpdate = function () {
+               // Update state
+               var active = this.areAnySelected();
 
                if ( this.active !== active ) {
                        this.active = active;
                return this.active;
        };
 
+       /**
+        * Get group name
+        *
+        * @return {string} Group name
+        */
+       mw.rcfilters.dm.FilterGroup.prototype.getName = function () {
+               return this.name;
+       };
+
+       /**
+        * Check whether there are any items selected
+        *
+        * @return {boolean} Any items in the group are selected
+        */
+       mw.rcfilters.dm.FilterGroup.prototype.areAnySelected = function () {
+               return this.getItems().some( function ( filterItem ) {
+                       return filterItem.isSelected();
+               } );
+       };
+
+       /**
+        * Check whether all items selected
+        *
+        * @return {boolean} All items are selected
+        */
+       mw.rcfilters.dm.FilterGroup.prototype.areAllSelected = function () {
+               return this.getItems().every( function ( filterItem ) {
+                       return filterItem.isSelected();
+               } );
+       };
+
+       /**
+        * Get all selected items in this group
+        *
+        * @param {mw.rcfilters.dm.FilterItem} [excludeItem] Item to exclude from the list
+        * @return {mw.rcfilters.dm.FilterItem[]} Selected items
+        */
+       mw.rcfilters.dm.FilterGroup.prototype.getSelectedItems = function ( excludeItem ) {
+               var excludeName = ( excludeItem && excludeItem.getName() ) || '';
+
+               return this.getItems().filter( function ( item ) {
+                       return item.getName() !== excludeName && item.isSelected();
+               } );
+       };
+
+       /**
+        * Check whether all selected items are in conflict with the given item
+        *
+        * @param {mw.rcfilters.dm.FilterItem} filterItem Filter item to test
+        * @return {boolean} All selected items are in conflict with this item
+        */
+       mw.rcfilters.dm.FilterGroup.prototype.areAllSelectedInConflictWith = function ( filterItem ) {
+               var selectedItems = this.getSelectedItems( filterItem );
+
+               return selectedItems.length > 0 && selectedItems.every( function ( selectedFilter ) {
+                       return selectedFilter.existsInConflicts( filterItem );
+               } );
+       };
+
+       /**
+        * Check whether any of the selected items are in conflict with the given item
+        *
+        * @param {mw.rcfilters.dm.FilterItem} filterItem Filter item to test
+        * @return {boolean} Any of the selected items are in conflict with this item
+        */
+       mw.rcfilters.dm.FilterGroup.prototype.areAnySelectedInConflictWith = function ( filterItem ) {
+               var selectedItems = this.getSelectedItems( filterItem );
+
+               return selectedItems.length > 0 && selectedItems.some( function ( selectedFilter ) {
+                       return selectedFilter.existsInConflicts( filterItem );
+               } );
+       };
+
        /**
         * Get group type
         *
        };
 
        /**
-        * Get group exclusion type
+        * Check whether the group is defined as full coverage
         *
-        * @return {string} Exclusion type
+        * @return {boolean} Group is full coverage
         */
-       mw.rcfilters.dm.FilterGroup.prototype.getExclusionType = function () {
-               return this.exclusionType;
+       mw.rcfilters.dm.FilterGroup.prototype.isFullCoverage = function () {
+               return this.fullCoverage;
        };
 }( mediaWiki ) );