import jQ from 'jquery';
import BaseComponent from "../../../base-component";
import Labels from "../../../../helpers/labels";
import Class from "../../../../helpers/class";
import Settings from '../../../../helpers/settings';
import FilterTreeEnum from '../../../../enum/filter-tree-enum';
import FilterOptionEnum from '../../../../enum/filter-option-enum';
/**
* The view more button of a filter option
* @extends BaseComponent
*/
class FilterViewMore extends BaseComponent {
/**
* Creates a new FilterViewMore button
* @param {FilterTreeEnum} filterTreeType - 'vertical' or 'horizontal'
*/
constructor(filterTreeType) {
super();
this.filterTreeType = filterTreeType;
this.isExpanded = false;
this.label = Labels.viewMore;
this.class = Class.filterOptionViewMore;
this.isVisible = true;
this.$element = null;
}
/**
* Get the view more state of a filter option.
* This is a static field, so it won't be destroyed along with class instance.
* @param {string} filterOptionId
* @return {boolean} - isExpanded value.
*/
static getViewMoreStateData(filterOptionId) {
return viewMoreStateData.get(filterOptionId);
}
/**
* Store the view more state of a filter option.
* This is a static field, so it won't be destroyed along with class instance.
* @param {string} filterOptionId
* @param {boolean} isExpanded - is the view more expanded or not
*/
static setViewMoreStateData(filterOptionId, isExpanded) {
viewMoreStateData.set(filterOptionId, isExpanded);
}
init() {
this.numberVisibleItems = this.getNumberVisibleItems();
}
/**
* Get html template of view more button
* 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.button}} {{class}}"><button>{{label}}</button></div>
`;
case FilterTreeEnum.FilterTreeType.HORIZONTAL:
return `
<div class="{{class.button}} {{class}}"><button aria-label="{{label}}"></button></div>
`;
default:
throw Error('Pass a filter tree type into the constructor');
}
}
compileTemplate() {
return this.getTemplate()
.replace(/{{class.button}}/g, Class.button)
.replace(/{{class}}/g, this.class)
.replace(/{{label}}/g, this.label);
}
isRender() {
return this.parent.displayType != FilterOptionEnum.DisplayType.RANGE
&& (this.parent.showMoreType == FilterOptionEnum.ShowMoreType.VIEWMORE
|| this.parent.showMoreType == FilterOptionEnum.ShowMoreType.VIEWMORE_SCROLLBAR);
}
render() {
if (!this.$element) {
this.$element = jQ(this.compileTemplate());
}
this.setVisibility();
}
bindEvents() {
if (this.$element) {
if (!this.isBoundEvent) {
this.$element.on('click', this.onClick.bind(this));
}
// Add class to parent for CSS
if (this.parent.$filterOptionContentElement) {
this.parent.$filterOptionContentElement.addClass(Class.filterHasViewMore);
}
// Expand the view more if it was expanded before
if (!this.isExpanded && FilterViewMore.getViewMoreStateData(this.parent.filterOptionId)) {
this.onClick();
// Else just calculate how many items are visible
} else {
this.setFilterItemsVisibility();
}
}
}
/**
* On clicking the filter view more
* Toggle show more/show less items
*/
onClick() {
this.isExpanded = !this.isExpanded;
FilterViewMore.setViewMoreStateData(this.parent.filterOptionId, this.isExpanded);
var oldClass = '';
if (this.isExpanded) {
this.label = Labels.viewLess;
this.class = Class.filterOptionViewLess;
oldClass = Class.filterOptionViewMore;
} else {
this.label = Labels.viewMore;
this.class = Class.filterOptionViewMore;
oldClass = Class.filterOptionViewLess;
}
if (this.filterTreeType == FilterTreeEnum.FilterTreeType.VERTICAL) {
this.$element.find('button').html(this.label);
} else {
this.$element.removeClass(oldClass).addClass(this.class);
}
this.setFilterItemsVisibility();
}
/**
* Check settings for how many items are visible before we show 'view more'
*/
getNumberVisibleItems() {
var numberVisibleItems = Settings.getSettingValue('general.startViewMore')[this.parent.displayType];
if (this.filterTreeType == FilterTreeEnum.FilterTreeType.HORIZONTAL) {
var filterHorizontalColumn = Settings.getSettingValue('general.filterHorizontalColumn')
if (Number.isInteger(filterHorizontalColumn)) {
numberVisibleItems = numberVisibleItems * filterHorizontalColumn;
} else {
numberVisibleItems = Settings.getSettingValue('general.startViewMoreH')[this.parent.displayType];
}
}
if (!numberVisibleItems || numberVisibleItems <= 1) {
numberVisibleItems = 5;
}
return numberVisibleItems;
}
/**
* Set visibility of the view more button
* If there are too few items (<=5), view more button will be hidden
*/
setVisibility() {
if (this.$element) {
// Get number of filter items on first load (parent not yet rendered)
var numberFilterItems = this.parent.filterItems.size;
if (!this.parent.keepValuesStatic && !Settings.getSettingValue('general.showOutOfStockOption')) {
var filterItemsArray = Array.from(this.parent.filterItems, ([key, value]) => ({ key, value }));
var filterItemsAvailble = filterItemsArray.filter((fitlerItem) => {
return fitlerItem.value.docCount > 0;
});
numberFilterItems = filterItemsAvailble.length;
}
// Get number filter items on the DOM (after search box or load more)
if (this.parent.$filterItemsContainerElement) {
numberFilterItems = this.parent.$filterItemsContainerElement.find('li').length;
}
this.isVisible = numberFilterItems > this.numberVisibleItems;
if (this.isVisible) {
this.$element.show();
} else {
this.$element.hide();
}
} else {
this.isVisible = false;
}
}
/**
* Show/hide the filter option items on clicking view more/view less
*/
setFilterItemsVisibility() {
if (this.parent.$filterItemsContainerElement) {
var $filterItemElements = this.parent.$filterItemsContainerElement.find('li');
$filterItemElements.show();
if (!this.isExpanded) {
var sliceFrom = this.numberVisibleItems;
var sliceTo = $filterItemElements.length;
$filterItemElements.slice(sliceFrom, sliceTo).hide();
}
}
}
}
var viewMoreStateData = new Map();
export default FilterViewMore;