- } else if ( this.getGroup( group ).getExclusionType() === 'explicit' ) {
- // Explicit behavior
- // - Go over the list of excluded filters to change their
- // active states accordingly
-
- // For each item in the list, see if there are other selected
- // filters that also exclude it. If it does, it will still be
- // inactive.
-
- item.getExcludedFilters().forEach( function ( filterName ) {
- var filterItem = model.getItemByName( filterName );
-
- // Note to reduce confusion:
- // - item is the filter whose state changed and should exclude the other filters
- // in its list of exclusions
- // - filterItem is the filter that is potentially being excluded by the current item
- // - anotherExcludingFilter is any other filter that excludes filterItem; we must check
- // if that filter is selected, because if it is, we should not touch the excluded item
- if (
- // Check if there are any filters (other than the current one)
- // that also exclude the filterName
- !model.excludedByMap[ filterName ].some( function ( anotherExcludingFilterName ) {
- var anotherExcludingFilter = model.getItemByName( anotherExcludingFilterName );
-
- return (
- anotherExcludingFilterName !== item.getName() &&
- anotherExcludingFilter.isSelected()
- );
- } )
- ) {
- // Only change the state for filters that aren't
- // also affected by other excluding selected filters
- filterItem.toggleActive( !item.isSelected() );
+
+ // Update coverage for the changed group
+ if ( groupModel.isFullCoverage() ) {
+ allSelected = groupModel.areAllSelected();
+ groupModel.getItems().forEach( function ( filterItem ) {
+ filterItem.toggleFullyCovered( allSelected );
+ } );
+ }
+ } );
+
+ // Check for conflicts
+ // In this case, we must go over all items, since
+ // conflicts are bidirectional and depend not only on
+ // individual items, but also on the selected states of
+ // the groups they're in.
+ this.getItems().forEach( function ( filterItem ) {
+ var inConflict = false,
+ filterItemGroup = filterItem.getGroupModel();
+
+ // For each item, see if that item is still conflicting
+ $.each( model.groups, function ( groupName, groupModel ) {
+ if ( filterItem.getGroupName() === groupName ) {
+ // Check inside the group
+ inConflict = groupModel.areAnySelectedInConflictWith( filterItem );
+ } else {
+ // According to the spec, if two items conflict from two different
+ // groups, the conflict only lasts if the groups **only have selected
+ // items that are conflicting**. If a group has selected items that
+ // are conflicting and non-conflicting, the scope of the result has
+ // expanded enough to completely remove the conflict.
+
+ // For example, see two groups with conflicts:
+ // userExpLevel: [
+ // {
+ // name: 'experienced',
+ // conflicts: [ 'unregistered' ]
+ // }
+ // ],
+ // registration: [
+ // {
+ // name: 'registered',
+ // },
+ // {
+ // name: 'unregistered',
+ // }
+ // ]
+ // If we select 'experienced', then 'unregistered' is in conflict (and vice versa),
+ // because, inherently, 'experienced' filter only includes registered users, and so
+ // both filters are in conflict with one another.
+ // However, the minute we select 'registered', the scope of our results
+ // has expanded to no longer have a conflict with 'experienced' filter, and
+ // so the conflict is removed.
+
+ // In our case, we need to check if the entire group conflicts with
+ // the entire item's group, so we follow the above spec
+ inConflict = (
+ // The foreign group is in conflict with this item
+ groupModel.areAllSelectedInConflictWith( filterItem ) &&
+ // Every selected member of the item's own group is also
+ // in conflict with the other group
+ filterItemGroup.getSelectedItems().every( function ( otherGroupItem ) {
+ return groupModel.areAllSelectedInConflictWith( otherGroupItem );
+ } )
+ );