import jQ from 'jquery';
import BaseComponent from "../../../base-component";
import Labels from "../../../../helpers/labels";
import Class from "../../../../helpers/class";
import Globals from "../../../../helpers/globals";
import Settings from '../../../../helpers/settings';
import FilterTreeEnum from "../../../../enum/filter-tree-enum";
import FilterOptionEnum from '../../../../enum/filter-option-enum';
import FilterApi from '../../../../api/filter-api';
import Utils from "../../../../helpers/utils";
/**
* Filter clear button
*/
class FilterClearButton extends BaseComponent {
/**
* Creates new FilterClearButton
* @param {FilterTreeEnum} filterTreeType - 'vertical' or 'horizontal'
* @param {ClearType} clearType - clear type 'clear-single-value', 'clear-option-values', 'clear-all'
*/
constructor(filterTreeType, clearType) {
super();
this.filterTreeType = filterTreeType;
this.clearType = clearType;
this.requestInstantly = true;
this.label = (this.clearType == FilterClearButton.ClearType.CLEAR_ALL) ? Labels.clearAll : Labels.clear;
}
/**
* Get the clear button types enum
*/
static get ClearType() {
return {
CLEAR_SINGLE_VALUE: 'clear-single-value',
CLEAR_OPTION_VALUES: 'clear-option-values',
CLEAR_ALL: 'clear-all'
}
}
/**
* Get the clear button's html template.
* Depending on its clearType, it returns different templates
* @returns {string} Raw html template
*/
getTemplate() {
switch (this.clearType) {
case FilterClearButton.ClearType.CLEAR_SINGLE_VALUE:
return `
<button aria-label="{{adaLabel}}" class="{{class.button}} {{class.clearButton}}"></button>
`;
case FilterClearButton.ClearType.CLEAR_OPTION_VALUES:
return `
<button aria-label="{{adaLabel}}" class="{{class.button}} {{class.clearButton}}">{{label}}</button>
`;
case FilterClearButton.ClearType.CLEAR_ALL:
return `
<button aria-label="{{adaLabel}}" class="{{class.button}} {{class.clearAllButton}}">{{label}}</button>
`;
default:
throw Error('Wrong filter clear type');
}
}
compileTemplate() {
this.buildAdaLabel();
return this.getTemplate()
.replace(/{{label.clear}}/g, Labels.clear)
.replace(/{{class.button}}/g, Class.button)
.replace(/{{class.clearButton}}/g, Class.clearButton)
.replace(/{{class.clearAllButton}}/g, Class.clearAllButton)
.replace(/{{adaLabel}}/g, this.adaLabel)
.replace(/{{label}}/g, this.label);
}
render() {
if (!this.$element) {
this.$element = jQ(this.compileTemplate());
}
if (this.isVisible()) {
this.$element.show();
} else {
this.$element.hide();
}
}
buildAdaLabel() {
this.adaLabel = '';
switch (this.clearType) {
case FilterClearButton.ClearType.CLEAR_SINGLE_VALUE:
var refineByItem = this.parent;
if (refineByItem && refineByItem.type && refineByItem.label) {
this.adaLabel = Labels.ada.clearFilterItem
.replace(/{{filterOption}}/g, refineByItem.type)
.replace(/{{filterItem}}/g, refineByItem.label);
}
break;
case FilterClearButton.ClearType.CLEAR_OPTION_VALUES:
var filterOption = this.parent;
if (filterOption && filterOption.label) {
this.adaLabel = Labels.ada.clearFilterOption.replace(/{{filterOption}}/g, filterOption.label);
}
break;
case FilterClearButton.ClearType.CLEAR_ALL:
this.adaLabel = Labels.ada.clearAllFilterItems;
break;
}
}
/**
* Check if the clear button is visible.
* For example, if there are no selected filter items,
* clear all button won't be visible.
* @returns {boolean}
*/
isVisible() {
var isShowClearButton = true;
switch (this.clearType) {
case FilterClearButton.ClearType.CLEAR_OPTION_VALUES:
var filterOption = this.parent;
if (filterOption.displayType == FilterOptionEnum.DisplayType.MULTI_LEVEL_COLLECTIONS) {
var filterOptionTagId = filterOption.filterOptionId.replace(Globals.prefix + '_c_', Globals.prefix + '_ct_');
isShowClearButton = Globals.queryParams[filterOption.filterOptionId] || Globals.queryParams[filterOptionTagId];
} else {
isShowClearButton = Globals.queryParams[filterOption.filterOptionId];
}
break;
case FilterClearButton.ClearType.CLEAR_ALL:
isShowClearButton = false;
Object.keys(Globals.queryParams).forEach(key => {
// Check if there is any filter option param
if (key.startsWith(Globals.prefix)) {
var value = Globals.queryParams[key];
var isCollectionAllInSearchPage = Utils.isSearchPage() && key.startsWith(Globals.prefix + '_c_') && value == 0;
// Show clear button when there is filter option param
// EXCEPT when filter by collection All in search page
if (!isCollectionAllInSearchPage) {
isShowClearButton = true;
}
}
})
break;
}
return !!(isShowClearButton);
}
isBindEvents() { return !this.isBoundEvent; }
bindEvents() {
if (this.$element) {
this.$element.on('click', this.onClick.bind(this));
}
}
/**
* On click the clear button
* calls onClearSingleValue, or onClearOptionValues, or onClearAll depending on clear type
* @param event
*/
onClick(event) {
if (event) {
event.preventDefault();
}
if (this.requestInstantly) {
switch(this.clearType) {
case FilterClearButton.ClearType.CLEAR_SINGLE_VALUE:
this.onClearSingleValue();
break;
case FilterClearButton.ClearType.CLEAR_OPTION_VALUES:
this.onClearOptionValues();
break;
case FilterClearButton.ClearType.CLEAR_ALL:
this.onClearAll();
break;
}
} else {
switch(this.clearType) {
case FilterClearButton.ClearType.CLEAR_OPTION_VALUES:
this.onDeselectOptionValues();
break;
}
}
}
/**
* Clears single filter value
* This clear button is a child of the RefineByItem component,
* RefineByItem component has filterOptionId and filterItemId fields, to know which value to clear.
* Calls API
*/
onClearSingleValue() {
var refineByItem = this.parent;
var filterOptionId = refineByItem.filterOptionId;
var filterOptionValue = refineByItem.filterItemId;
var currentValues = Globals.queryParams[filterOptionId];
if (currentValues == null) return;
if (!Array.isArray(currentValues)) {
currentValues = [currentValues];
}
var removeAtIndex = currentValues.indexOf(filterOptionValue);
var newValues = [];
if (removeAtIndex > -1) {
newValues = currentValues.filter((value, index) => index != removeAtIndex);
}
// Clear values
if (newValues.length == 0) {
FilterApi.setParam(filterOptionId, null);
FilterApi.setParam(filterOptionId + '_and_condition', null);
FilterApi.setParam(filterOptionId + '_show_exact_rating', null);
FilterApi.setParam(filterOptionId + '_exclude_from_value', null);
} else {
FilterApi.setParam(filterOptionId, newValues);
}
// On search page, if clear multi-level tag, also clear the collection
if (Utils.isSearchPage() && filterOptionId.startsWith(Globals.prefix + '_ct_')) {
var collectionFilterOptionId = filterOptionId.replace(Globals.prefix + '_ct_', Globals.prefix + '_c_');
FilterApi.setParam(collectionFilterOptionId, null);
}
// Reset page
FilterApi.setParam('page', 1);
var eventType = 'clear';
var eventInfo = {
filterOptionId: filterOptionId,
filterOptionValue: filterOptionValue
}
FilterApi.applyFilter(eventType, eventInfo);
}
/**
* Clear all values of one filter options
* This button is a child of a FilterOption component
* FilterOption component has filterOptionId field, to know which values to clear.
* Calls API.
*/
onClearOptionValues() {
// Close the tab on horizontal
var filterOption = this.parent;
if (filterOption.filterTreeType == FilterTreeEnum.FilterTreeType.HORIZONTAL && !Settings.getSettingValue('general.keepTabOpenState') && filterOption.collapse) {
this.parent.collapse.onToggleHorizontal();
}
Globals.internalClick = true;
var filterOptionId = filterOption.filterOptionId;
// With multi collection on collection page, don't clear the collection, only clear the tags
if (filterOption.displayType == FilterOptionEnum.DisplayType.MULTI_LEVEL_COLLECTIONS && !Utils.isSearchPage()) {
filterOptionId = filterOptionId.replace(Globals.prefix + '_c_', Globals.prefix + '_ct_');
}
var eventType = 'clear';
var eventInfo = {
filterOptionId: filterOptionId
}
FilterApi.setParam('page', 1);
FilterApi.setParam(filterOptionId, null);
FilterApi.setParam(filterOptionId + '_and_condition', null);
FilterApi.setParam(filterOptionId + '_show_exact_rating', null);
FilterApi.setParam(filterOptionId + '_exclude_from_value', null);
FilterApi.applyFilter(eventType, eventInfo);
}
/**
* Clear all values of the filter
* This button is a child of a FilterTree component
* Calls API.
*/
onClearAll() {
var currentFilterOptionIds = [];
Object.keys(Globals.queryParams).forEach(queryParam => {
if (queryParam.startsWith(Globals.prefix)) {
currentFilterOptionIds.push(queryParam);
}
});
currentFilterOptionIds.forEach(filterOptionId => {
FilterApi.setParam(filterOptionId, null);
});
FilterApi.setParam('page', 1);
var eventType = 'clearAll';
var eventInfo = {};
FilterApi.applyFilter(eventType, eventInfo);
}
/**
* Deselects all filter option item in a filter option
* Don't call API.
*/
onDeselectOptionValues() {
if (this.parent.filterItems) {
this.parent.filterItems.forEach(filterItem => {
filterItem.$element.removeClass('selected');
filterItem.isSelected = false;
})
}
}
}
export default FilterClearButton;