import BaseComponent from "../../../base-component";
import FilterOptionEnum from "../../../../enum/filter-option-enum";
import Class from "../../../../helpers/class";
import Settings from "../../../../helpers/settings";
import Utils from "../../../../helpers/utils";
/**
* The scrollbar of a filter option.
* @extends BaseComponent
*/
class FilterScrollbar extends BaseComponent {
constructor() {
super();
this.placeHolderHeight = '';
this.numberFilterItemsRendered = 0;
this.$scrollElement = null;
}
/**
* Get the scroll state of a filter option.
* This is a static field, so it won't be destroyed along with class instance.
* @param {string} filterOptionId
* @return {number} - scrollTop value.
*/
static getScrollStateData(filterOptionId) {
return scrollStateData.get(filterOptionId);
}
/**
* Store the scroll state of a filter option.
* This is a static field, so it won't be destroyed along with class instance.
* @param {string} filterOptionId
* @param {number} scrollTop - scrollTop value
*/
static setScrollStateData(filterOptionId, scrollTop) {
scrollStateData.set(filterOptionId, scrollTop);
}
isBindEvents() { return !this.isBoundEvent; }
bindEvents() {
if (this.parent.$element && FilterScrollbar.isEnabled(this.parent.displayType, this.parent.filterType, this.parent.showMoreType)) {
// Get scroll container
var $scrollbarContainer = this.parent.$element.find('.' + Class.filterOptionContentInner);
if ($scrollbarContainer.length > 0) {
// Assign scrollbar
this.$scrollElement = $scrollbarContainer;
// Bind loadmore on scroll
if (this.parent.isLoadMoreOnScroll || Settings.getSettingValue('general.keepScrollState')) {
this.$scrollElement.on('scroll', this.onScroll.bind(this));
}
// Keep scroll state
if (Settings.getSettingValue('general.keepScrollState')) {
var scrollTop = FilterScrollbar.getScrollStateData(this.parent.filterOptionId);
if (!isNaN(scrollTop)) {
this.$scrollElement[0].scrollTop = scrollTop;
}
}
}
}
}
/**
* Check if scrollbar is enabled.
* @param {FilterOptionEnum.DisplayType} displayType
* @param {FilterOptionEnum.ShowMoreType} showMoreType
* @return {boolean}
*/
static isEnabled(displayType, filterType, showMoreType) {
var excludeDisplayTypes = [FilterOptionEnum.DisplayType.RANGE];
var excludeFilterTypes = [
FilterOptionEnum.FilterType.REVIEW_RATINGS,
FilterOptionEnum.FilterType.STOCK,
FilterOptionEnum.FilterType.PERCENT_SALE,
FilterOptionEnum.FilterType.PRICE,
FilterOptionEnum.FilterType.VARIANTS_PRICE
];
var hasScrollbar = showMoreType == FilterOptionEnum.ShowMoreType.SCROLLBAR || showMoreType == FilterOptionEnum.ShowMoreType.VIEWMORE_SCROLLBAR;
var isMobile = Utils.isMobile();
var activeScrollbarByDevice = (isMobile && Settings.getSettingValue('general.activeFilterScrollbarMobile')) || (!isMobile && Settings.getSettingValue('general.activeFilterScrollbarPC'));
return !excludeDisplayTypes.includes(displayType)
&& !excludeFilterTypes.includes(filterType)
&& hasScrollbar
&& activeScrollbarByDevice;
}
/**
* On scroll filter option
*/
onScroll() {
if (Settings.getSettingValue('general.keepScrollState')) {
var scrollTop = this.$scrollElement[0].scrollTop;
FilterScrollbar.setScrollStateData(this.parent.filterOptionId, scrollTop);
}
if (this.parent.isLoadMoreOnScroll && this.isScrollToBottom()) {
var isSearching = this.parent.searchBox && this.parent.searchBox.searchValue;
if (!isSearching) {
this.appendFilterItems();
}
}
}
/**
* Check if scroll to bottom of a filter option
* @return {boolean}
*/
isScrollToBottom() {
if (this.$scrollElement) {
return this.$scrollElement[0].scrollHeight - this.$scrollElement.scrollTop() - this.$scrollElement.outerHeight() < 1 ;
}
return false;
}
/**
* Appends filter items on scroll to bottom of a filter option
*/
appendFilterItems() {
if (this.parent.$filterItemsContainerElement) {
// Check if all items are rendered
var numberItems = Settings.getSettingValue('general.scrollFirstLoadLength');
if (this.numberFilterItemsRendered == 0) {
this.numberFilterItemsRendered = numberItems;
} else if (this.numberFilterItemsRendered == this.parent.filterItems.size) {
return;
}
// Css class to display spinner
this.parent.$element.addClass('boost-pfs-filter-scrollbar-loading');
// Append filter items
var count = 0;
this.parent.filterItems.forEach((filterItem) => {
if (filterItem.isRenderOnScroll && count < numberItems) {
this.parent.$filterItemsContainerElement.append(filterItem.$element);
filterItem.isRenderOnScroll = false;
count++;
this.numberFilterItemsRendered++;
}
})
// Remove spinner with a timeout because spinner get removed too fast
setTimeout(function () {
this.parent.$element.removeClass('boost-pfs-filter-scrollbar-loading');
}.bind(this), 200);
}
}
}
var scrollStateData = new Map();
export default FilterScrollbar;