Source: components/filter/filter-tree/filter-option-element/filter-collapse.js

import jQ from 'jquery';
import BaseComponent from "../../../base-component";
import FilterTreeEnum from "../../../../enum/filter-tree-enum";
import Settings from "../../../../helpers/settings";
import Utils from "../../../../helpers/utils";
import Selector from "../../../../helpers/selector";
import Class from "../../../../helpers/class";

/**
 * Handle collapse/toggle of filter option.
 * @extends BaseComponent
 */
class FilterCollapse extends BaseComponent {
	constructor(filterTreeType) {
		super();
		this.filterTreeType = filterTreeType;

		this.$clickElement = null;
		this.$toggleElement = null;
	}

	/**
	 * Get the collapsed 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} - isCollapsed state.
	 */
	static getCollapsedStateData(filterOptionId) {
		return collapsedStateData.get(filterOptionId);
	}

	/**
	 * Store the collapsed 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} isCollapsed
	 */
	static setCollapsedStateData(filterOptionId, isCollapsed) {
		collapsedStateData.set(filterOptionId, isCollapsed);
	}

	init() {
		// Set initial collapse state
		this.isCollapsed = false;
		if (this.filterTreeType == FilterTreeEnum.FilterTreeType.HORIZONTAL) {
			this.isCollapsed = true;
		} else {
			// Check if keep the collapsed state
			var isCollapsed;
			if (Settings.getSettingValue('general.keepToggleState')) {
				isCollapsed = FilterCollapse.getCollapsedStateData(this.parent.filterOptionId);
			}
			if (typeof isCollapsed == 'undefined') {
				var isMobile = Utils.isMobile();
				this.isCollapsed = (isMobile && (this.parent.isCollapseMobile || Settings.getSettingValue('general.collapseOnMobileByDefault')))
					|| (!isMobile && (this.parent.isCollapsePC || Settings.getSettingValue('general.collapseOnPCByDefault')));
			} else {
				this.isCollapsed = isCollapsed;
			}
		}
	}

	isBindEvents() { return !!(!this.isBoundEvent && this.parent.$element && this.parent.$filterOptionContentElement && this.parent.$filterOptionTitleElement); }

	bindEvents() {
		this.$clickElement = this.parent.$filterOptionTitleElement;
		this.$toggleElement = this.parent.$filterOptionContentElement;

		if (this.filterTreeType == FilterTreeEnum.FilterTreeType.VERTICAL) {
			this.$clickElement.on('click', this.onToggleVertical.bind(this));
		} else {
			this.$clickElement.on('click', this.onToggleHorizontal.bind(this));
			if (!isBoundClickOutsideEvent) {
				isBoundClickOutsideEvent = true;
				jQ('body').on('click', this.onClickOutSideHorizontal.bind(this));
			}
			if (this.parent.filterOptionId == reopenHorizontalFilterOptionId) {
				reopenHorizontalFilterOptionId = '';
				this.onToggleHorizontal();
			}
		}

		// Add aria-expand state
		this.$clickElement.attr('aria-expanded', !this.isCollapsed);
	}

	/**
	 * On clicking the title of vertical filter option, show/hide the content
	 */
	onToggleVertical() {
		this.isCollapsed = !this.isCollapsed;

		// Store the toggle state
		if (Settings.getSettingValue('general.keepToggleState')) {
			FilterCollapse.setCollapsedStateData(this.parent.filterOptionId, this.isCollapsed);
		}

		this.parent.$element.toggleClass('boost-pfs-filter-option-collapsed');
		this.$clickElement.attr('aria-expanded', !this.isCollapsed);
		this.$toggleElement.slideToggle(400, this.afterToggle.bind(this));
	}

	/**
	 * On clicking the title of horizontal filter option, show/hide the content
	 */
	onToggleHorizontal() {
		var isCollapsed = !this.isCollapsed;

		this.calculateHorizontalColumn();
		var isApply = this.closeAllHorizontalTabs();

		if (!isCollapsed) {
			if (isApply) {
				reopenHorizontalFilterOptionId = this.parent.filterOptionId;
			} else {
				reopenHorizontalFilterOptionId = '';
				this.parent.$element.removeClass('boost-pfs-filter-option-collapsed');
				this.$clickElement.attr('aria-expanded', true);
				this.$toggleElement.show();
				this.isCollapsed = false;
			}
		}
		this.afterToggle();
	}

	/**
	 * On clicking outside of the filter on horizontal, close the tabs
	 */
	onClickOutSideHorizontal(event) {
		if (!event || !event.target) return;
		var clickedElement = jQ(event.target);

		// Returns if clicking inside the filter tree
		if (clickedElement.closest(Selector.filterTreeHorizontal + ' .' + Class.filterOption).length > 0) {
			return;
		}
		if (clickedElement.closest(Selector.filterTreeHorizontal + ' .' + Class.clearButton).length > 0) {
			return;
		}
		if (clickedElement.closest(Selector.filterTreeHorizontal + ' .' + Class.clearAllButton).length > 0) {
			return;
		}
		this.closeAllHorizontalTabs();
	}

	closeAllHorizontalTabs() {
		var filterTree = this.parent.parent;
		var isChangedFilter = false;
		filterTree.filterOptions.forEach((filterOption) => {
			if (filterOption.$element && filterOption.collapse && !filterOption.collapse.isCollapsed) {
				filterOption.$element.addClass('boost-pfs-filter-option-collapsed');
				filterOption.$filterOptionTitleElement.attr('aria-expanded', false);
				filterOption.collapse.isCollapsed = true;
				filterOption.collapse.$toggleElement.hide();
				var filterItems = filterOption.allNestedFilterItems ? filterOption.allNestedFilterItems : filterOption.filterItems;
				filterItems.forEach(item => {
					if (!isChangedFilter) {
						if (item.isAppliedFilter() != item.isSelected) {
							isChangedFilter = filterOption;
						}
					}
				});
			}
		})
		if (isChangedFilter) {
			isChangedFilter.applyButton.onApplyOptionValues();
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Called after the toggle filter option animation is done.
	 */
	afterToggle() {}

	/**
	 * Add special css classes to the horizontal filter option,
	 * to specify number of columns layout (1,2,3,full)
	 * and align left/right
	 */
	calculateHorizontalColumn() {
		// Get default number of columns
		var columnNumber = this.parent.displayColumn;

		// Add left right class
		var leftRight = 'left';
		var offset = this.parent.$filterOptionTitleElement.offset();
        
        if ((columnNumber == 1 || columnNumber == '1') && this.parent.displayType == FilterOptionEnum.DisplayType.RANGE) {
			columnNumber = 2;
		}
		if (offset && offset.left) {
			switch (columnNumber) {
				case 1:
				case "1":
					if ((offset.left + 250) > jQ(window).width()) {
						leftRight = 'right';
					}
					break;
				case 2:
				case "2":
					if ((offset.left + 532) > jQ(window).width()) {
                        if (offset.left < 532) {
                          leftRight= 'center';
                        } else {
                          leftRight = 'right';
                        }
					} 
					break;
				case 3:
				case "3":
					if ((offset.left + 700) > jQ(window).width()) {
						leftRight = 'right';
					}
					break;
				default:
					break;
			}
		}

		if (leftRight == 'left') {
			this.parent.$element.removeClass('boost-pfs-filter-option-right');
			this.parent.$element.addClass('boost-pfs-filter-option-left');
		} else if (leftRight == 'center'){
            this.parent.$element.removeClass('boost-pfs-filter-option-left');
            this.parent.$element.removeClass('boost-pfs-filter-option-right');
			this.parent.$element.addClass('boost-pfs-filter-option-center');
        } else {
			this.parent.$element.removeClass('boost-pfs-filter-option-left');
			this.parent.$element.addClass('boost-pfs-filter-option-right');
		}
	}
}

var reopenHorizontalFilterOptionId = '';
var collapsedStateData = new Map();
var isBoundClickOutsideEvent = false;

export default FilterCollapse;