Source: components/filter/filter-result/product/product-item/product-item.js

import jQ from "jquery";
import BaseComponent from "../../../../base-component";
import Settings from "../../../../../helpers/settings";
import Globals from "../../../../../helpers/globals";
import Utils from "../../../../../helpers/utils";
import Selector from "../../../../../helpers/selector";

/**
 * Base product item
 * @extends BaseComponent
 */
class ProductItem extends BaseComponent {
	constructor() {
		super();
		this.data = null;
		this.id = null;
		this.totalProduct = null;
		this.$element = null;
		this.$productList = jQ(Selector.products);
		this.settings = {
			enableKeepScrollbackPosition: Settings.getSettingValue('general.enableKeepScrollbackPosition')
		}
	}

	init() {
		if (window.BoostOTP) {
			BoostOTP.OTPButtons.init(this);
		}
	}

	/**
	 * Build the product item HTML
	 */
	compileTemplate() {
		return '';
	}

	/**
	 * Render the product item
	 */
	render() {
		if (!this.$element || this.$element.length == 0) {
			if (this.parent.isRender()) {
				// On none first load, render element from template
				var productHtml = this.compileTemplate();
				if (productHtml && typeof productHtml == 'string') {
					this.$element = jQ(productHtml);
				}
			} else {
				// On first load, select element from the DOM
				var productItemClass = Settings.getSettingValue('general.otpProductItemClass');
				if (productItemClass) {
					this.$element = this.$productList.children(productItemClass).eq(this.index);
				} else {
					this.$element = this.$productList.children().eq(this.index);
				}
			}
		}
		if (this.$element) {
			this.$element.attr('data-id', this.id);
			this.$element.data('page', Globals.queryParams.page);
			if (window.BoostOTP) {
				BoostOTP.OTPButtons.render(this);
			}
		}
	}

	/**
	 * Bind the events on the product item
	 */
	bindEvents() {
		this._bindKeepScrollbackPositionEvent();

		// Calculate OTP position
		if (window.BoostOTP) {
			BoostOTP.OTPButtons.bindEvents(this);
		}
	}

	/**
	 * Bind the events for Keep scrollback position feature
	 * @protected
	 */
	_bindKeepScrollbackPositionEvent() {
		if (this.$element) {
			if (this.settings.enableKeepScrollbackPosition) {
				// bind the click event on the product item
				if (Utils.isMobileDevice()) {
					// Change params on the address bar when click to item
					var isScrolling = false;
					/**
					 * Change params on the address bar when click to item ( Ignore if scrolling action )
					 */
					this.$element
						.on('touchstart', () => {
							isScrolling = false;
						})
						.on('touchmove', () => {
							isScrolling = true;
						})
						.on('touchend', this._onClickKeepPositionEvent.bind(this, isScrolling));
				} else {
					this.$element.on('click', this._onClickKeepPositionEvent.bind(this, false));
				}
			}
		}
	}

	/**
	 * Bind the click event on the product item
	 * @param {Boolean} isScrolling - Use it to distinguish the scrolling action from touch event on mobile
	 * @param {*} event - DOM event
	 */
	_onClickKeepPositionEvent(isScrolling, event) {
		if (!isScrolling && this.id) {
			var urlW = new URL(Utils.getWindowLocation().href);
			var stage = {
				productId: this.id,
				// FIXME: Shouldn't use the Global page param, because it's not correctly when use load more, infinite loading
				page: this.$element.data('page')
			};
			// Remove page param from URL
			if (urlW.searchParams.get('page') !== null) {
				urlW.searchParams.delete('page');
			}
			// Append the page number that you get
			if (stage.page > 1 && Utils.FilterResult.isAdvancedPaginationType()) {
				urlW.searchParams.append('page', stage.page);
			}
			// Storage our data to state of history before redirect to product page
			window.history.replaceState(stage, '', urlW.toString().replace(/\+/g, '%20'));
		}
	}

	/**
	 * Set data for product item
	 * @param {Object} data - The filter result data
	 * @param {Number} index - The index of product item
	 */
	setData(data, index) {
		this.data = data;
		this.id = data.id;
		this.index = index;
		this.totalProduct = this.parent.totalProduct;
	}
}

export default ProductItem;