import jQ from 'jquery';
import BaseComponent from "../../../base-component";
import FilterTreeEnum from "../../../../enum/filter-tree-enum";
import Class from "../../../../helpers/class";
import Labels from "../../../../helpers/labels";
import FilterClearButton from "../filter-option-element/filter-clear-button";
import FilterOptionEnum from '../../../../enum/filter-option-enum';
import FilterOptionItem from "../filter-option-item/filter-option-item";
/**
* A single refine by item
* It has a label and a clear button.
*/
class FilterRefineByItem extends BaseComponent {
/**
* Creates a new FilterRefineByItem
* @param {FilterTreeEnum} filterTreeType - 'vertical' or 'horizontal'
*/
constructor(filterTreeType) {
super();
this.filterTreeType = filterTreeType;
this.$element = null;
}
init() {
this.clearButton = new FilterClearButton(this.filterTreeType, FilterClearButton.ClearType.CLEAR_SINGLE_VALUE);
this.addComponent(this.clearButton);
}
/**
* Get the refine by item'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="refine-by-item {{class.filterOptionLabel}}">
<a tabindex="-1" href="javascript:;">
<span class="refine-by-type">
<span>{{type}}</span><strong>{{label}}</strong>
</span>
{{clearButton}}
</a>
</div>
`;
case FilterTreeEnum.FilterTreeType.HORIZONTAL:
return `
<div class="refine-by-item">
<a tabindex="-1" href="javascript:;">
<span class="{{class.filterOptionLabel}} refine-by-type">{{label}}</span>
{{clearButton}}
</a>
</div>
`;
default:
throw Error('Wrong filterTreeType');
}
}
compileTemplate() {
return this.getTemplate()
.replace(/{{class.filterOptionLabel}}/g, Class.filterOptionLabel)
.replace(/{{type}}/g, this.type ? this.type + ': ' : '')
.replace(/{{label}}/g, this.label)
.replace(/{{clearButton}}/g, '');
}
render() {
this.$element = jQ(this.compileTemplate());
this.$element.find('a').append(this.clearButton.$element);
}
/**
* Set data for refine by item.
* @param {FilterOption} filterOption - currently selected filter option
* @param {FilterOptionItem} filterItem - currently selected filter option item
* @param {string} filterItemKey - the key of the above filter option item
*/
setData(filterOption, filterItem, filterItemKey) {
this.filterOption = filterOption;
this.filterItem = filterItem;
this.filterOptionId = filterOption.filterOptionId;
this.filterItemId = filterItemKey;
this.type = filterOption.label;
// Build label
this.label = this.buildLabel();
}
/**
* Build label for refine by item.
* It gets the label from filterItem.label, except for some cases (Rating, Range)
* @returns {string}
*/
buildLabel() {
var formatLabel = this.filterItemId;
if (this.filterOption) {
switch (this.filterOption.displayType) {
case FilterOptionEnum.DisplayType.RANGE:
formatLabel = this.buildLabelRange();
break;
case FilterOptionEnum.DisplayType.RATING:
formatLabel = this.buildLabelRating();
break;
case FilterOptionEnum.DisplayType.MULTI_LEVEL_COLLECTIONS:
case FilterOptionEnum.DisplayType.MULTI_LEVEL_TAG:
formatLabel = this.buildLabelMultiLevel();
break;
default:
if (this.filterItem) {
formatLabel = this.filterItem.label;
} else {
// Fix issue when user filter by a value but the value doesn't exist in filter tree
var dummyFilterItem = new FilterOptionItem(this.filterOption.filterTreeType);
dummyFilterItem.filterOption = this.filterOption;
dummyFilterItem.label = this.filterItemId;
formatLabel = dummyFilterItem.buildLabel();
}
break;
}
}
return formatLabel;
}
/**
* Build special refine by label for filter by rating
* @returns {string} - Formatted label
*/
buildLabelRating() {
var label = '';
if (this.filterItem) {
var from = this.filterItem.from;
label = Math.ceil(from) + ' ';
if (Math.ceil(from) == 1) {
label += Labels.ratingStar;
} else {
label += Labels.ratingStars;
}
if (!this.filterOption.showExactRating) {
label += ' ' + Labels.ratingUp;
}
}
return label;
}
/**
* Build special refine by label for filter by range
* @returns {string} - Formatted label
*/
buildLabelRange() {
var label = '';
if (this.filterOption) {
if (this.filterOption.isNumberRangeSlider) {
var values = this.filterItemId.split(':');
if (values && values.length == 2) {
var minLabel = this.filterOption.buildLabel(values[0]);
var maxLabel = this.filterOption.buildLabel(values[1]);
if (minLabel == maxLabel) {
label = minLabel;
} else {
label = minLabel + ' - ' + maxLabel;
}
}
} else {
var values = this.filterItemId;
var minLabel = '';
var maxLabel = '';
// Get label from filter option data
if ((this.filterOption.currentMax - 1 > 0)
&& (this.filterOption.currentMax - 1 < this.filterOption.valuesData.length)) {
minLabel = this.filterOption.valuesData[this.filterOption.currentMin].key;
maxLabel = this.filterOption.valuesData[this.filterOption.currentMax - 1].key;
// Fallback: get label from filter item id
} else if (Array.isArray(values) && values.length > 0){
minLabel = values[0];
maxLabel = values[values.length - 1];
}
// Remove prefix
if (this.filterOption.prefix) {
var prefix = this.filterOption.prefix.replace(/\\/g, '');
minLabel = minLabel.replace(prefix, '').trim();
maxLabel = maxLabel.replace(prefix, '').trim();
}
// Build label min-max
if (minLabel == maxLabel) {
label = minLabel;
} else {
label = minLabel + ' - ' + maxLabel;
}
}
}
return label;
}
/**
* Build refine by label for filter by multi level tag
* @returns {string} - Formatted label
*/
buildLabelMultiLevel() {
var label = '';
// Different logic for multi level
if (this.filterOption && this.filterItem &&
(this.filterOption.displayType == FilterOptionEnum.DisplayType.MULTI_LEVEL_COLLECTIONS
|| this.filterOption.displayType == FilterOptionEnum.DisplayType.MULTI_LEVEL_TAG)) {
switch (this.filterItem.level) {
case 1:
this.type = this.filterOption.label;
label = this.filterItem.buildLabel();
break;
case 2:
this.filterOptionId = this.filterOptionId.replace(Globals.prefix + '_c_', Globals.prefix + '_ct_');
this.type = this.filterOption.label;
label = this.filterItem.buildLabel();
break;
case 3:
this.filterOptionId = this.filterOptionId.replace(Globals.prefix + '_c_', Globals.prefix + '_ct_');
this.type = this.filterOption.label;
label = this.filterItem.buildLabel();
break;
}
}
return label ? label : this.filterItemId;
}
}
export default FilterRefineByItem;