this.defaultParams = {};
this.defaultFiltersEmpty = null;
this.highlightEnabled = false;
+ this.parameterMap = {};
// Events
this.aggregate( { update: 'filterItemUpdate' } );
* @param {Array} filters Filter group definition
*/
mw.rcfilters.dm.FiltersViewModel.prototype.initializeFilters = function ( filters ) {
- var i, filterItem, selectedFilterNames, filterConflictResult, groupConflictResult,
+ var i, filterItem, selectedFilterNames, filterConflictResult, groupConflictResult, subsetNames,
model = this,
items = [],
supersetMap = {},
expandConflictDefinitions = function ( obj ) {
var result = {};
- $.each( obj, function ( group, conflicts ) {
- var adjustedConflicts = {};
+ $.each( obj, function ( key, conflicts ) {
+ var filterName,
+ adjustedConflicts = {};
+
conflicts.forEach( function ( conflict ) {
if ( conflict.filter ) {
- adjustedConflicts[ conflict.filter ] = conflict;
+ filterName = model.groups[ conflict.group ].getNamePrefix() + conflict.filter;
+
+ // Rename
+ adjustedConflicts[ filterName ] = $.extend(
+ {},
+ conflict,
+ { filter: filterName }
+ );
} else {
// This conflict is for an entire group. Split it up to
// represent each filter
// Get the relevant group items
model.groups[ conflict.group ].getItems().forEach( function ( groupItem ) {
// Rebuild the conflict
- adjustedConflicts[ groupItem.getName() ] = $.extend( {}, conflict, { filter: groupItem.getName() } );
+ adjustedConflicts[ groupItem.getName() ] = $.extend(
+ {},
+ conflict,
+ { filter: groupItem.getName() }
+ );
} );
}
} );
- result[ group ] = adjustedConflicts;
+ result[ key ] = adjustedConflicts;
} );
return result;
group: group,
label: mw.msg( data.filters[ i ].label ),
description: mw.msg( data.filters[ i ].description ),
- subset: data.filters[ i ].subset,
cssClass: data.filters[ i ].cssClass
} );
- // For convenience, we should store each filter's "supersets" -- these are
- // the filters that have that item in their subset list. This will just
- // make it easier to go through whether the item has any other items
- // that affect it (and are selected) at any given time
if ( data.filters[ i ].subset ) {
+ subsetNames = [];
data.filters[ i ].subset.forEach( function ( subsetFilterName ) { // eslint-disable-line no-loop-func
- supersetMap[ subsetFilterName ] = supersetMap[ subsetFilterName ] || [];
+ var subsetName = model.groups[ group ].getNamePrefix() + subsetFilterName;
+ // For convenience, we should store each filter's "supersets" -- these are
+ // the filters that have that item in their subset list. This will just
+ // make it easier to go through whether the item has any other items
+ // that affect it (and are selected) at any given time
+ supersetMap[ subsetName ] = supersetMap[ subsetName ] || [];
addArrayElementsUnique(
- supersetMap[ subsetFilterName ],
+ supersetMap[ subsetName ],
filterItem.getName()
);
+
+ // Translate subset param name to add the group name, so we
+ // get consistent naming. We know that subsets are only within
+ // the same group
+ subsetNames.push( subsetName );
} );
+
+ // Set translated subset
+ filterItem.setSubset( subsetNames );
}
// Store conflicts
if ( data.filters[ i ].conflicts ) {
- filterConflictMap[ data.filters[ i ].name ] = data.filters[ i ].conflicts;
+ filterConflictMap[ filterItem.getName() ] = data.filters[ i ].conflicts;
}
if ( data.type === 'send_unselected_if_any' ) {
}
} );
+ // Create a map between known parameters and their models
+ $.each( this.groups, function ( group, groupModel ) {
+ if ( groupModel.getType() === 'send_unselected_if_any' ) {
+ // Individual filters
+ groupModel.getItems().forEach( function ( filterItem ) {
+ model.parameterMap[ filterItem.getParamName() ] = filterItem;
+ } );
+ } else if ( groupModel.getType() === 'string_options' ) {
+ // Group
+ model.parameterMap[ groupModel.getName() ] = groupModel;
+ }
+ } );
+
// Add items to the model
this.addItems( items );
* @return {Object} Parameter state object
*/
mw.rcfilters.dm.FiltersViewModel.prototype.getParametersFromFilters = function ( filterGroups ) {
- var i, filterItems, anySelected, values,
- result = {},
+ var result = {},
groupItems = filterGroups || this.getFilterGroups();
$.each( groupItems, function ( group, model ) {
- filterItems = model.getItems();
-
- if ( model.getType() === 'send_unselected_if_any' ) {
- // First, check if any of the items are selected at all.
- // If none is selected, we're treating it as if they are
- // all false
- anySelected = filterItems.some( function ( filterItem ) {
- return filterItem.isSelected();
- } );
-
- // Go over the items and define the correct values
- for ( i = 0; i < filterItems.length; i++ ) {
- result[ filterItems[ i ].getName() ] = anySelected ?
- Number( !filterItems[ i ].isSelected() ) : 0;
- }
- } else if ( model.getType() === 'string_options' ) {
- values = [];
- for ( i = 0; i < filterItems.length; i++ ) {
- if ( filterItems[ i ].isSelected() ) {
- values.push( filterItems[ i ].getName() );
- }
- }
-
- if ( values.length === filterItems.length ) {
- result[ group ] = 'all';
- } else {
- result[ group ] = values.join( model.getSeparator() );
- }
- }
+ $.extend( result, model.getParamRepresentation() );
} );
return result;
mw.rcfilters.dm.FiltersViewModel.prototype.sanitizeStringOptionGroup = function( groupName, valueArray ) {
var result = [],
validNames = this.getGroupFilters( groupName ).map( function ( filterItem ) {
- return filterItem.getName();
+ return filterItem.getParamName();
} );
if ( valueArray.indexOf( 'all' ) > -1 ) {
* @return {Object} Filter state object
*/
mw.rcfilters.dm.FiltersViewModel.prototype.getFiltersFromParameters = function ( params ) {
- var i, filterItem,
+ var i,
groupMap = {},
model = this,
base = this.getDefaultParams(),
params = $.extend( {}, base, params );
+ // Go over the given parameters
$.each( params, function ( paramName, paramValue ) {
- // Find the filter item
- filterItem = model.getItemByName( paramName );
- // Ignore if no filter item exists
- if ( filterItem ) {
- groupMap[ filterItem.getGroupName() ] = groupMap[ filterItem.getGroupName() ] || {};
+ var itemOrGroup = model.parameterMap[ paramName ];
+ if ( itemOrGroup instanceof mw.rcfilters.dm.FilterItem ) {
// Mark the group if it has any items that are selected
- groupMap[ filterItem.getGroupName() ].hasSelected = (
- groupMap[ filterItem.getGroupName() ].hasSelected ||
+ groupMap[ itemOrGroup.getGroupName() ] = groupMap[ itemOrGroup.getGroupName() ] || {};
+ groupMap[ itemOrGroup.getGroupName() ].hasSelected = (
+ groupMap[ itemOrGroup.getGroupName() ].hasSelected ||
!!Number( paramValue )
);
- // Add the relevant filter into the group map
- groupMap[ filterItem.getGroupName() ].filters = groupMap[ filterItem.getGroupName() ].filters || [];
- groupMap[ filterItem.getGroupName() ].filters.push( filterItem );
- } else if ( model.groups.hasOwnProperty( paramName ) ) {
+ // Add filters
+ groupMap[ itemOrGroup.getGroupName() ].filters = groupMap[ itemOrGroup.getGroupName() ].filters || [];
+ groupMap[ itemOrGroup.getGroupName() ].filters.push( itemOrGroup );
+ } else if ( itemOrGroup instanceof mw.rcfilters.dm.FilterGroup ) {
+ groupMap[ itemOrGroup.getName() ] = groupMap[ itemOrGroup.getName() ] || {};
// This parameter represents a group (values are the filters)
// this is equivalent to checking if the group is 'string_options'
- groupMap[ paramName ] = { filters: model.groups[ paramName ].getItems() };
+ groupMap[ itemOrGroup.getName() ].filters = itemOrGroup.getItems();
}
} );
for ( i = 0; i < allItemsInGroup.length; i++ ) {
filterItem = allItemsInGroup[ i ];
- result[ filterItem.getName() ] = data.hasSelected ?
+ result[ filterItem.getName() ] = groupMap[ filterItem.getGroupName() ].hasSelected ?
// Flip the definition between the parameter
// state and the filter state
// This is what the 'toggleSelected' value of the filter is
- !Number( params[ filterItem.getName() ] ) :
+ !Number( params[ filterItem.getParamName() ] ) :
// Otherwise, there are no selected items in the
// group, which means the state is false
false;
}
} else if ( model.groups[ group ].getType() === 'string_options' ) {
- paramValues = model.sanitizeStringOptionGroup( group, params[ group ].split( model.groups[ group ].getSeparator() ) );
+ paramValues = model.sanitizeStringOptionGroup(
+ group,
+ params[ group ].split(
+ model.groups[ group ].getSeparator()
+ )
+ );
for ( i = 0; i < allItemsInGroup.length; i++ ) {
filterItem = allItemsInGroup[ i ];
// is the same as all filters set to false
false :
// Otherwise, the filter is selected only if it appears in the parameter values
- paramValues.indexOf( filterItem.getName() ) > -1;
+ paramValues.indexOf( filterItem.getParamName() ) > -1;
}
}
} );
+
return result;
};
* @param {boolean} [isSelected] Filter selected state
*/
mw.rcfilters.dm.FiltersViewModel.prototype.toggleFilterSelected = function ( name, isSelected ) {
- this.getItemByName( name ).toggleSelected( isSelected );
+ var item = this.getItemByName( name );
+
+ if ( item ) {
+ item.toggleSelected( isSelected );
+ }
};
/**
+/* eslint-disable camelcase */
( function ( mw, $ ) {
QUnit.module( 'mediawiki.rcfilters - FiltersViewModel', QUnit.newMwEnvironment( {
messages: {
type: 'send_unselected_if_any',
filters: [
{
- name: 'group1filter1',
+ name: 'filter1',
label: 'Group 1: Filter 1',
description: 'Description of Filter 1 in Group 1'
},
{
- name: 'group1filter2',
+ name: 'filter2',
label: 'Group 1: Filter 2',
description: 'Description of Filter 2 in Group 1'
}
type: 'send_unselected_if_any',
filters: [
{
- name: 'group2filter1',
+ name: 'filter1',
label: 'Group 2: Filter 1',
description: 'Description of Filter 1 in Group 2'
},
{
- name: 'group2filter2',
+ name: 'filter2',
label: 'Group 2: Filter 2',
description: 'Description of Filter 2 in Group 2'
}
type: 'string_options',
filters: [
{
- name: 'group3filter1',
+ name: 'filter1',
label: 'Group 3: Filter 1',
description: 'Description of Filter 1 in Group 3'
},
{
- name: 'group3filter2',
+ name: 'filter2',
label: 'Group 3: Filter 2',
description: 'Description of Filter 2 in Group 3'
}
model.initializeFilters( definition );
assert.ok(
- model.getItemByName( 'group1filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
- model.getItemByName( 'group1filter2' ) instanceof mw.rcfilters.dm.FilterItem &&
- model.getItemByName( 'group2filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
- model.getItemByName( 'group2filter2' ) instanceof mw.rcfilters.dm.FilterItem &&
- model.getItemByName( 'group3filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
- model.getItemByName( 'group3filter2' ) instanceof mw.rcfilters.dm.FilterItem,
+ model.getItemByName( 'group1__filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
+ model.getItemByName( 'group1__filter2' ) instanceof mw.rcfilters.dm.FilterItem &&
+ model.getItemByName( 'group2__filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
+ model.getItemByName( 'group2__filter2' ) instanceof mw.rcfilters.dm.FilterItem &&
+ model.getItemByName( 'group3__filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
+ model.getItemByName( 'group3__filter2' ) instanceof mw.rcfilters.dm.FilterItem,
'Filters instantiated and stored correctly'
);
assert.deepEqual(
model.getSelectedState(),
{
- group1filter1: false,
- group1filter2: false,
- group2filter1: false,
- group2filter2: false,
- group3filter1: false,
- group3filter2: false
+ group1__filter1: false,
+ group1__filter2: false,
+ group2__filter1: false,
+ group2__filter2: false,
+ group3__filter1: false,
+ group3__filter2: false
},
'Initial state of filters'
);
model.toggleFiltersSelected( {
- group1filter1: true,
- group2filter2: true,
- group3filter1: true
+ group1__filter1: true,
+ group2__filter2: true,
+ group3__filter1: true
} );
assert.deepEqual(
model.getSelectedState(),
{
- group1filter1: true,
- group1filter2: false,
- group2filter1: false,
- group2filter2: true,
- group3filter1: true,
- group3filter2: false
+ group1__filter1: true,
+ group1__filter2: false,
+ group2__filter1: false,
+ group2__filter2: true,
+ group3__filter1: true,
+ group3__filter2: false
},
'Updating filter states correctly'
);
type: 'send_unselected_if_any',
filters: [
{
- name: 'group1filter1',
+ name: 'filter1',
label: 'group1filter1-label',
description: 'group1filter1-desc'
},
{
- name: 'group1filter2',
+ name: 'filter2',
label: 'group1filter2-label',
description: 'group1filter2-desc'
}
type: 'send_unselected_if_any',
filters: [
{
- name: 'group2filter1',
+ name: 'filter1',
label: 'group2filter1-label',
description: 'group2filter1-desc'
},
{
- name: 'group2filter2',
+ name: 'filter2',
label: 'group2filter2-label',
description: 'group2filter2-desc'
}
{
query: 'group',
expectedMatches: {
- group1: [ 'group1filter1', 'group1filter2' ],
- group2: [ 'group2filter1' ]
+ group1: [ 'group1__filter1', 'group1__filter2' ],
+ group2: [ 'group2__filter1' ]
},
reason: 'Finds filters starting with the query string'
},
{
query: 'filter 2 in group',
expectedMatches: {
- group1: [ 'group1filter2' ],
- group2: [ 'group2filter2' ]
+ group1: [ 'group1__filter2' ],
+ group2: [ 'group2__filter2' ]
},
reason: 'Finds filters containing the query string in their description'
},
{
query: 'title',
expectedMatches: {
- group1: [ 'group1filter1', 'group1filter2' ],
- group2: [ 'group2filter1', 'group2filter2' ]
+ group1: [ 'group1__filter1', 'group1__filter2' ],
+ group2: [ 'group2__filter1', 'group2__filter2' ]
},
reason: 'Finds filters containing the query string in their group title'
}
// Select 1 filter
model.toggleFiltersSelected( {
- hidefilter1: true,
- hidefilter2: false,
- hidefilter3: false,
- hidefilter4: false,
- hidefilter5: false,
- hidefilter6: false
+ group1__hidefilter1: true,
+ group1__hidefilter2: false,
+ group1__hidefilter3: false,
+ group2__hidefilter4: false,
+ group2__hidefilter5: false,
+ group2__hidefilter6: false
} );
// Only one filter in one group
assert.deepEqual(
// Select 2 filters
model.toggleFiltersSelected( {
- hidefilter1: true,
- hidefilter2: true,
- hidefilter3: false,
- hidefilter4: false,
- hidefilter5: false,
- hidefilter6: false
+ group1__hidefilter1: true,
+ group1__hidefilter2: true,
+ group1__hidefilter3: false,
+ group2__hidefilter4: false,
+ group2__hidefilter5: false,
+ group2__hidefilter6: false
} );
// Two selected filters in one group
assert.deepEqual(
// Select 3 filters
model.toggleFiltersSelected( {
- hidefilter1: true,
- hidefilter2: true,
- hidefilter3: true,
- hidefilter4: false,
- hidefilter5: false,
- hidefilter6: false
+ group1__hidefilter1: true,
+ group1__hidefilter2: true,
+ group1__hidefilter3: true,
+ group2__hidefilter4: false,
+ group2__hidefilter5: false,
+ group2__hidefilter6: false
} );
// All filters of the group are selected == this is the same as not selecting any
assert.deepEqual(
// Select 1 filter from string_options
model.toggleFiltersSelected( {
- filter7: true,
- filter8: false,
- filter9: false
+ group3__filter7: true,
+ group3__filter8: false,
+ group3__filter9: false
} );
// All filters of the group are selected == this is the same as not selecting any
assert.deepEqual(
// Select 2 filters from string_options
model.toggleFiltersSelected( {
- filter7: true,
- filter8: true,
- filter9: false
+ group3__filter7: true,
+ group3__filter8: true,
+ group3__filter9: false
} );
// All filters of the group are selected == this is the same as not selecting any
assert.deepEqual(
// Select 3 filters from string_options
model.toggleFiltersSelected( {
- filter7: true,
- filter8: true,
- filter9: true
+ group3__filter7: true,
+ group3__filter8: true,
+ group3__filter9: true
} );
// All filters of the group are selected == this is the same as not selecting any
assert.deepEqual(
} ],
defaultFilterRepresentation = {
// Group 1 and 2, "send_unselected_if_any", the values of the filters are "flipped" from the values of the parameters
- hidefilter1: false,
- hidefilter2: true,
- hidefilter3: false,
- hidefilter4: true,
- hidefilter5: false,
- hidefilter6: true,
+ group1__hidefilter1: false,
+ group1__hidefilter2: true,
+ group1__hidefilter3: false,
+ group2__hidefilter4: true,
+ group2__hidefilter5: false,
+ group2__hidefilter6: true,
// Group 3, "string_options", default values correspond to parameters and filters
- filter7: false,
- filter8: true,
- filter9: false
+ group3__filter7: false,
+ group3__filter8: true,
+ group3__filter9: false
},
model = new mw.rcfilters.dm.FiltersViewModel();
hidefilter2: '1'
} ),
$.extend( {}, defaultFilterRepresentation, {
- hidefilter1: false, // The text is "show filter 1"
- hidefilter2: false, // The text is "show filter 2"
- hidefilter3: false // The text is "show filter 3"
+ group1__hidefilter1: false, // The text is "show filter 1"
+ group1__hidefilter2: false, // The text is "show filter 2"
+ group1__hidefilter3: false // The text is "show filter 3"
} ),
'One truthy parameter in a group whose other parameters are true by default makes the rest of the filters in the group false (unchecked)'
);
hidefilter3: '1'
} ),
$.extend( {}, defaultFilterRepresentation, {
- hidefilter1: false, // The text is "show filter 1"
- hidefilter2: false, // The text is "show filter 2"
- hidefilter3: false // The text is "show filter 3"
+ group1__hidefilter1: false, // The text is "show filter 1"
+ group1__hidefilter2: false, // The text is "show filter 2"
+ group1__hidefilter3: false // The text is "show filter 3"
} ),
'All paremeters in the same \'send_unselected_if_any\' group false is equivalent to none are truthy (checked) in the interface'
);
assert.deepEqual(
model.getSelectedState(),
$.extend( {}, defaultFilterRepresentation, {
- hidefilter5: false,
- hidefilter6: false
+ group2__hidefilter5: false,
+ group2__hidefilter6: false
} ),
'getFiltersFromParameters does not care about previous or existing state.'
);
assert.deepEqual(
model.getSelectedState(),
$.extend( {}, defaultFilterRepresentation, {
- filter7: true,
- filter8: false,
- filter9: false
+ group3__filter7: true,
+ group3__filter8: false,
+ group3__filter9: false
} ),
'A \'string_options\' parameter containing 1 value, results in the corresponding filter as checked'
);
assert.deepEqual(
model.getSelectedState(),
$.extend( {}, defaultFilterRepresentation, {
- filter7: true,
- filter8: true,
- filter9: false
+ group3__filter7: true,
+ group3__filter8: true,
+ group3__filter9: false
} ),
'A \'string_options\' parameter containing 2 values, results in both corresponding filters as checked'
);
assert.deepEqual(
model.getSelectedState(),
$.extend( {}, defaultFilterRepresentation, {
- filter7: false,
- filter8: false,
- filter9: false
+ group3__filter7: false,
+ group3__filter8: false,
+ group3__filter9: false
} ),
'A \'string_options\' parameter containing all values, results in all filters of the group as unchecked.'
);
assert.deepEqual(
model.getSelectedState(),
$.extend( {}, defaultFilterRepresentation, {
- filter7: false,
- filter8: false,
- filter9: false
+ group3__filter7: false,
+ group3__filter8: false,
+ group3__filter9: false
} ),
'A \'string_options\' parameter containing the value \'all\', results in all filters of the group as unchecked.'
);
assert.deepEqual(
model.getSelectedState(),
$.extend( {}, defaultFilterRepresentation, {
- filter7: true,
- filter8: false,
- filter9: true
+ group3__filter7: true,
+ group3__filter8: false,
+ group3__filter9: true
} ),
'A \'string_options\' parameter containing an invalid value, results in the invalid value ignored and the valid corresponding filters checked.'
);
} ],
defaultFilterRepresentation = {
// Group 1 and 2, "send_unselected_if_any", the values of the filters are "flipped" from the values of the parameters
- hidefilter1: false,
- hidefilter2: true,
- hidefilter3: false,
- hidefilter4: true,
- hidefilter5: false,
- hidefilter6: true
+ group1__hidefilter1: false,
+ group1__hidefilter2: true,
+ group1__hidefilter3: false,
+ group2__hidefilter4: true,
+ group2__hidefilter5: false,
+ group2__hidefilter6: true
},
model = new mw.rcfilters.dm.FiltersViewModel();
assert.deepEqual(
model.getSelectedState(),
{
- hidefilter1: false,
- hidefilter2: false,
- hidefilter3: false,
- hidefilter4: false,
- hidefilter5: false,
- hidefilter6: false
+ group1__hidefilter1: false,
+ group1__hidefilter2: false,
+ group1__hidefilter3: false,
+ group2__hidefilter4: false,
+ group2__hidefilter5: false,
+ group2__hidefilter6: false
},
'Initial state: default filters are not selected (controller selects defaults explicitly).'
);
model.toggleFiltersSelected( {
- hidefilter1: false,
- hidefilter3: false
+ group1__hidefilter1: false,
+ group1__hidefilter3: false
} );
model.setFiltersToDefaults();
]
} ],
baseFullState = {
- filter1: { selected: false, conflicted: false, included: false },
- filter2: { selected: false, conflicted: false, included: false },
- filter3: { selected: false, conflicted: false, included: false }
+ group1__filter1: { selected: false, conflicted: false, included: false },
+ group1__filter2: { selected: false, conflicted: false, included: false },
+ group1__filter3: { selected: false, conflicted: false, included: false }
},
model = new mw.rcfilters.dm.FiltersViewModel();
model.initializeFilters( definition );
// Select a filter that has subset with another filter
model.toggleFiltersSelected( {
- filter1: true
+ group1__filter1: true
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter1' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group1__filter1' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter1: { selected: true },
- filter2: { included: true },
- filter3: { included: true }
+ group1__filter1: { selected: true },
+ group1__filter2: { included: true },
+ group1__filter3: { included: true }
} ),
'Filters with subsets are represented in the model.'
);
// Select another filter that has a subset with the same previous filter
model.toggleFiltersSelected( {
- filter2: true
+ group1__filter2: true
} );
model.reassessFilterInteractions( model.getItemByName( 'filter2' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter1: { selected: true },
- filter2: { selected: true, included: true },
- filter3: { included: true }
+ group1__filter1: { selected: true },
+ group1__filter2: { selected: true, included: true },
+ group1__filter3: { included: true }
} ),
'Filters that have multiple subsets are represented.'
);
- // Remove one filter (but leave the other) that affects filter2
+ // Remove one filter (but leave the other) that affects filter3
model.toggleFiltersSelected( {
- filter1: false
+ group1__filter1: false
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter1' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group1__filter1' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter2: { selected: true, included: false },
- filter3: { included: true }
+ group1__filter2: { selected: true, included: false },
+ group1__filter3: { included: true }
} ),
'Removing a filter only un-includes its subset if there is no other filter affecting.'
);
model.toggleFiltersSelected( {
- filter2: false
+ group1__filter2: false
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter2' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group1__filter2' ) );
assert.deepEqual(
model.getFullState(),
baseFullState,
},
getCurrentItemsMutedState = function () {
return {
- filter1: isCapsuleItemMuted( 'filter1' ),
- filter2: isCapsuleItemMuted( 'filter2' ),
- filter3: isCapsuleItemMuted( 'filter3' ),
- filter4: isCapsuleItemMuted( 'filter4' ),
- filter5: isCapsuleItemMuted( 'filter5' ),
- filter6: isCapsuleItemMuted( 'filter6' )
+ group1__filter1: isCapsuleItemMuted( 'group1__filter1' ),
+ group1__filter2: isCapsuleItemMuted( 'group1__filter2' ),
+ group1__filter3: isCapsuleItemMuted( 'group1__filter3' ),
+ group2__filter4: isCapsuleItemMuted( 'group2__filter4' ),
+ group2__filter5: isCapsuleItemMuted( 'group2__filter5' ),
+ group2__filter6: isCapsuleItemMuted( 'group2__filter6' )
};
},
baseMuteState = {
- filter1: false,
- filter2: false,
- filter3: false,
- filter4: false,
- filter5: false,
- filter6: false
+ group1__filter1: false,
+ group1__filter2: false,
+ group1__filter3: false,
+ group2__filter4: false,
+ group2__filter5: false,
+ group2__filter6: false
};
model.initializeFilters( definition );
// Select most (but not all) items in each group
model.toggleFiltersSelected( {
- filter1: true,
- filter2: true,
- filter4: true,
- filter5: true
+ group1__filter1: true,
+ group1__filter2: true,
+ group2__filter4: true,
+ group2__filter5: true
} );
// Both groups have multiple (but not all) items selected, all items are non-muted
// Select all items in 'fullCoverage' group (group2)
model.toggleFiltersSelected( {
- filter6: true
+ group2__filter6: true
} );
// Group2 (full coverage) has all items selected, all its items are muted
assert.deepEqual(
getCurrentItemsMutedState(),
$.extend( {}, baseMuteState, {
- filter4: true,
- filter5: true,
- filter6: true
+ group2__filter4: true,
+ group2__filter5: true,
+ group2__filter6: true
} ),
'All items in \'full coverage\' group are selected - all items in the group are muted'
);
// Select all items in non 'fullCoverage' group (group1)
model.toggleFiltersSelected( {
- filter3: true
+ group1__filter3: true
} );
// Group1 (full coverage) has all items selected, no items in it are muted (non full coverage)
assert.deepEqual(
getCurrentItemsMutedState(),
$.extend( {}, baseMuteState, {
- filter4: true,
- filter5: true,
- filter6: true
+ group2__filter4: true,
+ group2__filter5: true,
+ group2__filter6: true
} ),
'All items in a non \'full coverage\' group are selected - none of the items in the group are muted'
);
// Uncheck an item from each group
model.toggleFiltersSelected( {
- filter3: false,
- filter5: false
+ group1__filter3: false,
+ group2__filter5: false
} );
assert.deepEqual(
getCurrentItemsMutedState(),
]
} ],
baseFullState = {
- filter1: { selected: false, conflicted: false, included: false },
- filter2: { selected: false, conflicted: false, included: false },
- filter3: { selected: false, conflicted: false, included: false },
- filter4: { selected: false, conflicted: false, included: false },
- filter5: { selected: false, conflicted: false, included: false },
- filter6: { selected: false, conflicted: false, included: false }
+ group1__filter1: { selected: false, conflicted: false, included: false },
+ group1__filter2: { selected: false, conflicted: false, included: false },
+ group1__filter3: { selected: false, conflicted: false, included: false },
+ group2__filter4: { selected: false, conflicted: false, included: false },
+ group2__filter5: { selected: false, conflicted: false, included: false },
+ group2__filter6: { selected: false, conflicted: false, included: false }
},
model = new mw.rcfilters.dm.FiltersViewModel();
// Select a filter that has a conflict with an entire group
model.toggleFiltersSelected( {
- filter1: true // conflicts: entire of group 2 ( filter4, filter5, filter6)
+ group1__filter1: true // conflicts: entire of group 2 ( filter4, filter5, filter6)
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter1' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group1__filter1' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter1: { selected: true },
- filter4: { conflicted: true },
- filter5: { conflicted: true },
- filter6: { conflicted: true }
+ group1__filter1: { selected: true },
+ group2__filter4: { conflicted: true },
+ group2__filter5: { conflicted: true },
+ group2__filter6: { conflicted: true }
} ),
'Selecting a filter that conflicts with a group sets all the conflicted group items as "conflicted".'
);
// Select one of the conflicts (both filters are now conflicted and selected)
model.toggleFiltersSelected( {
- filter4: true // conflicts: filter 1
+ group2__filter4: true // conflicts: filter 1
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter4' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group2__filter4' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter1: { selected: true, conflicted: true },
- filter4: { selected: true, conflicted: true },
- filter5: { conflicted: true },
- filter6: { conflicted: true }
+ group1__filter1: { selected: true, conflicted: true },
+ group2__filter4: { selected: true, conflicted: true },
+ group2__filter5: { conflicted: true },
+ group2__filter6: { conflicted: true }
} ),
'Selecting a conflicting filter inside a group, sets both sides to conflicted and selected.'
);
// Select a filter that has a conflict with a specific filter
model.toggleFiltersSelected( {
- filter2: true // conflicts: filter6
+ group1__filter2: true // conflicts: filter6
} );
-
- model.reassessFilterInteractions( model.getItemByName( 'filter2' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group1__filter2' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter2: { selected: true },
- filter6: { conflicted: true }
+ group1__filter2: { selected: true },
+ group2__filter6: { conflicted: true }
} ),
'Selecting a filter that conflicts with another filter sets the other as "conflicted".'
);
// Select the conflicting filter
model.toggleFiltersSelected( {
- filter6: true // conflicts: filter2
+ group2__filter6: true // conflicts: filter2
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter6' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group2__filter6' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter2: { selected: true, conflicted: true },
- filter6: { selected: true, conflicted: true },
+ group1__filter2: { selected: true, conflicted: true },
+ group2__filter6: { selected: true, conflicted: true },
// This is added to the conflicts because filter6 is part of group2,
// who is in conflict with filter1; note that filter2 also conflicts
// with filter6 which means that filter1 conflicts with filter6 (because it's in group2)
// and also because its **own sibling** (filter2) is **also** in conflict with the
// selected items in group2 (filter6)
- filter1: { conflicted: true }
+ group1__filter1: { conflicted: true }
} ),
'Selecting a conflicting filter with an individual filter, sets both sides to conflicted and selected.'
);
// Now choose a non-conflicting filter from the group
model.toggleFiltersSelected( {
- filter5: true
+ group2__filter5: true
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter5' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group2__filter5' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter2: { selected: true },
- filter6: { selected: true },
- filter5: { selected: true }
+ group1__filter2: { selected: true },
+ group2__filter6: { selected: true },
+ group2__filter5: { selected: true }
// Filter6 and filter1 are no longer in conflict because
// filter5, while it is in conflict with filter1, it is
// not in conflict with filter2 - and since filter2 is
// it is in conflict with the entire of group2, it means
// filter1 is once again conflicted
model.toggleFiltersSelected( {
- filter2: false
+ group1__filter2: false
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter2' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group1__filter2' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter1: { conflicted: true },
- filter6: { selected: true },
- filter5: { selected: true }
+ group1__filter1: { conflicted: true },
+ group2__filter6: { selected: true },
+ group2__filter5: { selected: true }
} ),
'Unselecting an item that did not conflict returns the conflict state.'
);
// Followup #2: Now actually select filter1, and make everything conflicted
model.toggleFiltersSelected( {
- filter1: true
+ group1__filter1: true
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter1' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group1__filter1' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter1: { selected: true, conflicted: true },
- filter6: { selected: true, conflicted: true },
- filter5: { selected: true, conflicted: true },
- filter4: { conflicted: true } // Not selected but conflicted because it's in group2
+ group1__filter1: { selected: true, conflicted: true },
+ group2__filter6: { selected: true, conflicted: true },
+ group2__filter5: { selected: true, conflicted: true },
+ group2__filter4: { conflicted: true } // Not selected but conflicted because it's in group2
} ),
'Selecting an item that conflicts with a whole group makes all selections in that group conflicted.'
);
// Select a filter that has a conflict with a specific filter
model.toggleFiltersSelected( {
- filter2: true // conflicts: filter6
+ group1__filter2: true // conflicts: filter6
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter2' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group1__filter2' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter2: { selected: true },
- filter6: { conflicted: true }
+ group1__filter2: { selected: true },
+ group2__filter6: { conflicted: true }
} ),
'Simple case: Selecting a filter that conflicts with another filter sets the other as "conflicted".'
);
model.toggleFiltersSelected( {
- filter3: true // conflicts: filter6
+ group1__filter3: true // conflicts: filter6
} );
- model.reassessFilterInteractions( model.getItemByName( 'filter3' ) );
+ model.reassessFilterInteractions( model.getItemByName( 'group1__filter3' ) );
assert.deepEqual(
model.getFullState(),
$.extend( true, {}, baseFullState, {
- filter2: { selected: true },
- filter3: { selected: true }
+ group1__filter2: { selected: true },
+ group1__filter3: { selected: true }
} ),
'Simple case: Selecting a filter that is not in conflict removes the conflict.'
);
'Highlight is enabled on toggle.'
);
- model.setHighlightColor( 'filter1', 'color1' );
- model.setHighlightColor( 'filter2', 'color2' );
+ model.setHighlightColor( 'group1__filter1', 'color1' );
+ model.setHighlightColor( 'group1__filter2', 'color2' );
assert.deepEqual(
model.getHighlightedItems().map( function ( item ) {
return item.getName();
} ),
[
- 'filter1',
- 'filter2'
+ 'group1__filter1',
+ 'group1__filter2'
],
'Highlighted items are highlighted.'
);
assert.equal(
- model.getItemByName( 'filter1' ).getHighlightColor(),
+ model.getItemByName( 'group1__filter1' ).getHighlightColor(),
'color1',
'Item highlight color is set.'
);
- model.setHighlightColor( 'filter1', 'color1changed' );
+ model.setHighlightColor( 'group1__filter1', 'color1changed' );
assert.equal(
- model.getItemByName( 'filter1' ).getHighlightColor(),
+ model.getItemByName( 'group1__filter1' ).getHighlightColor(),
'color1changed',
'Item highlight color is changed on setHighlightColor.'
);
- model.clearHighlightColor( 'filter1' );
+ model.clearHighlightColor( 'group1__filter1' );
assert.deepEqual(
model.getHighlightedItems().map( function ( item ) {
return item.getName();
} ),
[
- 'filter2'
+ 'group1__filter2'
],
'Clear highlight from an item results in the item no longer being highlighted.'
);
model = new mw.rcfilters.dm.FiltersViewModel();
model.initializeFilters( definition );
- model.setHighlightColor( 'filter1', 'color1' );
- model.setHighlightColor( 'filter2', 'color2' );
- model.setHighlightColor( 'filter3', 'color3' );
+ model.setHighlightColor( 'group1__filter1', 'color1' );
+ model.setHighlightColor( 'group1__filter2', 'color2' );
+ model.setHighlightColor( 'group1__filter3', 'color3' );
assert.deepEqual(
model.getHighlightedItems().map( function ( item ) {
return item.getName();
} ),
[
- 'filter1',
- 'filter2',
- 'filter3'
+ 'group1__filter1',
+ 'group1__filter2',
+ 'group1__filter3'
],
'Even if highlights are not enabled, the items remember their highlight state'
// NOTE: When actually displaying the highlights, the UI checks whether
model = new mw.rcfilters.dm.FiltersViewModel();
model.initializeFilters( definition );
- model.setHighlightColor( 'filter1', 'color1' );
- model.setHighlightColor( 'filter6', 'color6' );
+ model.setHighlightColor( 'group1__filter1', 'color1' );
+ model.setHighlightColor( 'group1__filter6', 'color6' );
assert.deepEqual(
model.getHighlightedItems().map( function ( item ) {
return item.getName();
} ),
[
- 'filter1'
+ 'group1__filter1'
],
'Items without a specified class identifier are not highlighted.'
);