* @mixins OO.EventEmitter
*
* @constructor
- * @param {string} name Filter name
+ * @param {string} param Filter param name
* @param {mw.rcfilters.dm.FilterGroup} groupModel Filter group model
* @param {Object} config Configuration object
* @cfg {string} [group] The group this item belongs to
* selected, makes inactive.
* @cfg {boolean} [selected] The item is selected
* @cfg {string[]} [subset] Defining the names of filters that are a subset of this filter
- * @cfg {string[]} [conflictsWith] Defining the names of filters that conflict with this item
+ * @cfg {Object} [conflicts] Defines the conflicts for this filter
* @cfg {string} [cssClass] The class identifying the results that match this filter
*/
- mw.rcfilters.dm.FilterItem = function MwRcfiltersDmFilterItem( name, groupModel, config ) {
+ mw.rcfilters.dm.FilterItem = function MwRcfiltersDmFilterItem( param, groupModel, config ) {
config = config || {};
// Mixin constructor
OO.EventEmitter.call( this );
- this.name = name;
+ this.param = param;
this.groupModel = groupModel;
+ this.name = this.groupModel.getNamePrefix() + param;
this.label = config.label || this.name;
this.description = config.description;
// Interaction definitions
this.subset = config.subset || [];
- this.conflicts = config.conflicts || [];
+ this.conflicts = config.conflicts || {};
this.superset = [];
// Interaction states
return this.name;
};
+ /**
+ * Get the param name or value of this filter
+ *
+ * @return {string} Filter param name
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getParamName = function () {
+ return this.param;
+ };
+
+ /**
+ * Get the message for the display area for the currently active conflict
+ *
+ * @return {string} Conflict result message key
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getCurrentConflictResultMessage = function () {
+ var details = {};
+
+ // First look in filter's own conflicts
+ details = this.getConflictDetails( this.getOwnConflicts(), 'globalDescription' );
+ if ( !details.message ) {
+ // Fall back onto conflicts in the group
+ details = this.getConflictDetails( this.getGroupModel().getConflicts(), 'globalDescription' );
+ }
+
+ return details.message;
+ };
+
+ /**
+ * Get the details of the active conflict on this filter
+ *
+ * @param {Object} conflicts Conflicts to examine
+ * @param {string} [key='contextDescription'] Message key
+ * @return {Object} Object with conflict message and conflict items
+ * @return {string} return.message Conflict message
+ * @return {string[]} return.names Conflicting item labels
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getConflictDetails = function ( conflicts, key ) {
+ var group,
+ conflictMessage = '',
+ itemLabels = [];
+
+ key = key || 'contextDescription';
+
+ $.each( conflicts, function ( filterName, conflict ) {
+ if ( !conflict.item.isSelected() ) {
+ return;
+ }
+
+ if ( !conflictMessage ) {
+ conflictMessage = conflict[ key ];
+ group = conflict.group;
+ }
+
+ if ( group === conflict.group ) {
+ itemLabels.push( mw.msg( 'quotation-marks', conflict.item.getLabel() ) );
+ }
+ } );
+
+ return {
+ message: conflictMessage,
+ names: itemLabels
+ };
+
+ };
+
+ /**
+ * Get the message representing the state of this model.
+ *
+ * @return {string} State message
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getStateMessage = function () {
+ var messageKey, details, superset,
+ affectingItems = [];
+
+ if ( this.isConflicted() ) {
+ // First look in filter's own conflicts
+ details = this.getConflictDetails( this.getOwnConflicts() );
+ if ( !details.message ) {
+ // Fall back onto conflicts in the group
+ details = this.getConflictDetails( this.getGroupModel().getConflicts() );
+ }
+
+ messageKey = details.message;
+ affectingItems = details.names;
+ } else if ( this.isIncluded() ) {
+ superset = this.getSuperset();
+ // For this message we need to collect the affecting superset
+ affectingItems = this.getGroupModel().getSelectedItems( this )
+ .filter( function ( item ) {
+ return superset.indexOf( item.getName() ) !== -1;
+ } )
+ .map( function ( item ) {
+ return mw.msg( 'quotation-marks', item.getLabel() );
+ } );
+
+ messageKey = 'rcfilters-state-message-subset';
+ } else if ( this.isFullyCovered() ) {
+ affectingItems = this.getGroupModel().getSelectedItems( this )
+ .map( function ( item ) {
+ return mw.msg( 'quotation-marks', item.getLabel() );
+ } );
+
+ messageKey = 'rcfilters-state-message-fullcoverage';
+ }
+
+ if ( messageKey ) {
+ // Build message
+ return mw.msg(
+ messageKey,
+ mw.language.listToText( affectingItems ),
+ affectingItems.length
+ );
+ }
+
+ // Display description
+ return this.getDescription();
+ };
+
/**
* Get the model of the group this filter belongs to
*
};
/**
- * Get filter conflicts
- *
- * @return {string[]} Filter conflicts
+ * Get all conflicts associated with this filter or its group
+ *
+ * Conflict object is set up by filter name keys and conflict
+ * definition. For example:
+ * {
+ * filterName: {
+ * filter: filterName,
+ * group: group1,
+ * label: itemLabel,
+ * item: itemModel
+ * }
+ * filterName2: {
+ * filter: filterName2,
+ * group: group2
+ * label: itemLabel2,
+ * item: itemModel2
+ * }
+ * }
+ *
+ * @return {Object} Filter conflicts
*/
mw.rcfilters.dm.FilterItem.prototype.getConflicts = function () {
+ return $.extend( {}, this.conflicts, this.getGroupModel().getConflicts() );
+ };
+
+ /**
+ * Get the conflicts associated with this filter
+ *
+ * @return {Object} Filter conflicts
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getOwnConflicts = function () {
return this.conflicts;
};
/**
- * Set filter conflicts
+ * Set conflicts for this filter. See #getConflicts for the expected
+ * structure of the definition.
*
- * @param {string[]} conflicts Filter conflicts
+ * @param {Object} conflicts Conflicts for this filter
*/
mw.rcfilters.dm.FilterItem.prototype.setConflicts = function ( conflicts ) {
- this.conflicts = conflicts || [];
+ this.conflicts = conflicts || {};
};
/**
this.superset = superset || [];
};
+ /**
+ * Set filter subset
+ *
+ * @param {string[]} subset Filter subset
+ */
+ mw.rcfilters.dm.FilterItem.prototype.setSubset = function ( subset ) {
+ this.subset = subset || [];
+ };
+
/**
* Check whether a filter exists in the subset list for this filter
*
* @return {boolean} This item has a conflict with the given item
*/
mw.rcfilters.dm.FilterItem.prototype.existsInConflicts = function ( filterItem ) {
- return this.conflicts.indexOf( filterItem.getName() ) > -1;
+ return Object.prototype.hasOwnProperty.call( this.getConflicts(), filterItem.getName() );
};
/**
mw.rcfilters.dm.FilterItem.prototype.isHighlightSupported = function () {
return !!this.getCssClass();
};
+
+ /**
+ * Check if the filter is currently highlighted
+ *
+ * @return {boolean}
+ */
+ mw.rcfilters.dm.FilterItem.prototype.isHighlighted = function () {
+ return this.isHighlightEnabled() && !!this.getHighlightColor();
+ };
}( mediaWiki ) );