import jQ from 'jquery';
import BaseComponent from "../../../base-component";
import FilterTreeEnum from "../../../../enum/filter-tree-enum";
import Labels from "../../../../helpers/labels";
import FilterClearButton from '../filter-option-element/filter-clear-button';
import Class from '../../../../helpers/class';
import Globals from '../../../../helpers/globals';
import FilterRefineByItem from './filter-refine-by-item';
import FilterOptionEnum from '../../../../enum/filter-option-enum';
import Selector from "../../../../helpers/selector";
/**
* The refine by element of the filter.
* It contains list of refine by items, and a clear all button.
* @extends BaseComponent
*/
class FilterRefineBy extends BaseComponent {
/**
* Creates a new FilterRefineBy
* @param {FilterTreeEnum} filterTreeType - 'vertical' or 'horizontal'
*/
constructor(filterTreeType) {
super();
/**
* List of refine by items
* @type {Array}
*/
this.refineByItems = [];
this.clearAllButton = null;
this.filterTreeType = filterTreeType;
this.$element = null;
}
init() {
// Check separate refine by display vertical or horizontal
if (Settings.getSettingValue('general.separateRefineByFromFilter')) {
if (jQ(Selector.filterRefineByHorizontal).length > 0) {
this.filterTreeType = FilterTreeEnum.FilterTreeType.HORIZONTAL;
} else if (jQ(Selector.filterRefineByVertical).length > 0) {
this.filterTreeType = FilterTreeEnum.FilterTreeType.VERTICAL;
}
}
this.clearAllButton = new FilterClearButton(this.filterTreeType, FilterClearButton.ClearType.CLEAR_ALL);
this.addComponent(this.clearAllButton);
}
/**
* Get the refine by's html template.
* Depending on its filterTreeType, it returns different templates for 'vertical' and 'horizontal'
* @returns {string} Raw html template
*/
getTemplate() {
switch (this.filterTreeType) {
case FilterTreeEnum.FilterTreeType.VERTICAL:
return `
<div class="{{class.filterRefineBy}}">
<div class="{{class.filterOptionTitle}}">
<h3><span>{{label}}</span></h3>
{{clearAllButton}}
</div>
<div class="{{class.filterSelectedItems}}">{{refineByItems}}</div>
</div>
`;
case FilterTreeEnum.FilterTreeType.HORIZONTAL:
return `
<div class="boost-pfs-filter-pc {{class.filterRefineBy}}">
<span>{{label}}</span>
<div class="{{class.filterSelectedItems}}">{{refineByItems}}</div>
{{clearAllButton}}
</div>
`;
default:
throw Error('Wrong filterTreeType');
}
}
compileTemplate() {
return this.getTemplate()
.replace(/{{class.filterRefineBy}}/g, Class.filterRefineBy)
.replace(/{{class.filterOptionTitle}}/g, Class.filterOptionTitle)
.replace(/{{class.filterSelectedItems}}/g, Class.filterSelectedItems)
.replace(/{{label}}/g, Labels.refine)
.replace(/{{refineByItems}}/g, '')
.replace(/{{clearAllButton}}/g, '');
}
render() {
if (this.refineByItems && this.refineByItems.length > 0) {
this.$element = jQ(this.compileTemplate());
this.$refineByItemsContainer = this.$element.find('.' + Class.filterSelectedItems);
this.refineByItems.forEach((refineByItem) => {
this.$refineByItemsContainer.append(refineByItem.$element);
})
this.$clearAllButtonContainer = this.filterTreeType == FilterTreeEnum.FilterTreeType.VERTICAL ?
this.$element.find('.' + Class.filterOptionTitle) : this.$element;
this.$clearAllButtonContainer.append(this.clearAllButton.$element);
} else {
this.$element = null;
}
}
/**
* Set data for refine by.
* It doesn't have input param, because it gets the data from existing filter option.
* Call this setData function after you've called setData on filter options.
*/
setData() {
this.refineByItems = [];
var filterOptionIds = Object.keys(Globals.queryParams).filter(key => key.startsWith(Globals.prefix));
if (filterOptionIds && filterOptionIds.length > 0) {
filterOptionIds.forEach((filterOptionId) => {
var filterOption = this.parent.filterOptions.get(filterOptionId);
var isCollectionTagFilter = filterOptionId.startsWith(Globals.prefix + '_ct_');
if (isCollectionTagFilter){
filterOption = this.parent.filterOptions.get(filterOptionId.replace(Globals.prefix + '_ct_', Globals.prefix + '_c_'));
}
var filterItemKeys = Globals.queryParams[filterOptionId];
var isCollectionFilter = filterOptionId.startsWith(Globals.prefix + '_c_');
if (isCollectionFilter && !Array.isArray(filterItemKeys)) {
filterItemKeys = [filterItemKeys];
}
if (filterOption && filterItemKeys) {
var isMultiLevel = filterOption.displayType == FilterOptionEnum.DisplayType.MULTI_LEVEL_COLLECTIONS
|| filterOption.displayType == FilterOptionEnum.DisplayType.MULTI_LEVEL_TAG;
var isRangeSlider = filterOption.displayType == FilterOptionEnum.DisplayType.RANGE;
// Range slider has different refine by (from - to)
if (isRangeSlider) {
var refineByItem = new FilterRefineByItem(this.filterTreeType);
var keyValue = '';
if (filterOption.isNumberRangeSlider) {
keyValue = filterItemKeys[0];
} else {
keyValue = filterItemKeys;
}
refineByItem.setData(filterOption, null, keyValue);
this.refineByItems.push(refineByItem);
this.addComponent(refineByItem);
// Multi level has different refine by
} else if (isMultiLevel) {
var isMultiLevelSingle =
(filterOption.displayType == FilterOptionEnum.DisplayType.MULTI_LEVEL_COLLECTIONS
&& Settings.getSettingValue('general.multiLevelCollectionSelectType') == FilterOptionEnum.SelectType.SINGLE)
|| (filterOption.displayType == FilterOptionEnum.DisplayType.MULTI_LEVEL_TAG
&& filterOption.selectType == FilterOptionEnum.SelectType.SINGLE);
Object.values(filterItemKeys).forEach(filterItemKey => {
var combineKey = filterItemKey;
if (isCollectionTagFilter) {
combineKey = Globals.collectionId + ':' + filterItemKey;
}
var filterItem = filterOption.allNestedFilterItems.get(combineKey);
// Collection multi level SINGLE only shows the deepest selected level
if (isMultiLevelSingle && isCollectionFilter && filterItem && filterItem.isSelectedChild) {
return;
}
var refineByItem = new FilterRefineByItem(this.filterTreeType);
refineByItem.setData(filterOption, filterItem, filterItemKey);
this.refineByItems.push(refineByItem);
this.addComponent(refineByItem);
})
} else {
Object.values(filterItemKeys).forEach(filterItemKey => {
var filterItem = filterOption.filterItems.get(filterItemKey);
var refineByItem = new FilterRefineByItem(this.filterTreeType);
refineByItem.setData(filterOption, filterItem, filterItemKey);
this.refineByItems.push(refineByItem);
this.addComponent(refineByItem);
})
}
}
});
}
}
}
export default FilterRefineBy;