Source: otp/product-item-buttons/quick-view.js

var Labels = BoostPFS.Labels;
var jQ = BoostPFS.jQ;
var Settings = BoostPFS.Settings;
var Utils = BoostPFS.Utils;

import BaseComponent from "../../components/base-component";
import AjaxCart from "../ajax-cart/ajax-cart";

/**
 * Quick view
 * @extends BaseComponent
 */
class QuickView extends BaseComponent {
	getTemplate() {
		return `
			<button class="boost-pfs-quickview-btn boost-pfs-filter-button" data-href="{{productUrl}}" aria-label="{{label.quickview}}">
				<span>
					{{icoQuickView}}
				</span>
			</button>
		`
	}

	getModalTemplate() {
		return `
			<div class="boost-pfs-modal-backdrop">
				<div class="boost-pfs-modal-container">
					<div class="boost-pfs-modal-content"></div>
				</div>
			</div>
		`;
	}

	compileTemplate() {
		var productData = this.parent.data;
		var productListData = this.parent.parent.data;
		var productIsFirst = productData.id == productListData[0].id;
		var icoQuickView = '<svg width="32" height="32" viewBox="0 0 32 32"><g id="boost-pfs-icon-quick-view" transform="scale(0.03125 0.03125)"><path d="M1009.004 493.256c-2.256-2.82-56.254-69.828-143.786-137.492-51.696-39.962-104.462-71.87-156.832-94.834-66.48-29.152-132.556-43.932-196.386-43.932-63.832 0-129.904 14.782-196.386 43.932-52.37 22.962-105.136 54.87-156.834 94.834-87.53 67.666-141.528 134.674-143.784 137.494l-14.996 18.742 14.998 18.744c2.256 2.82 56.252 69.828 143.784 137.492 51.696 39.962 104.462 71.87 156.834 94.834 66.48 29.152 132.554 43.932 196.386 43.932 63.83 0 129.904-14.782 196.386-43.932 52.37-22.962 105.136-54.87 156.832-94.834 87.53-67.666 141.53-134.674 143.786-137.492l14.994-18.744-14.996-18.744zM827.402 621.624c-74.24 57.196-189.226 125.374-315.402 125.374-126.18 0-241.162-68.178-315.402-125.374-55.36-42.65-97.042-85.794-118.512-109.612 52.994-58.698 229.246-235.006 433.916-235.006 126.178 0 241.162 68.178 315.402 125.374 55.366 42.654 97.050 85.8 118.522 109.622-21.474 23.82-63.158 66.968-118.524 109.622z"></path><path d="M512 309.976c-111.396 0-202.024 90.63-202.024 202.024s90.63 202.024 202.024 202.024 202.026-90.628 202.026-202.024-90.63-202.024-202.026-202.024zM512 654.018c-78.308 0-142.018-63.71-142.018-142.018s63.71-142.018 142.018-142.018 142.018 63.71 142.018 142.018c0 78.308-63.71 142.018-142.018 142.018z"></path><path d="M512 419.322c-51.102 0-92.678 41.576-92.678 92.678s41.576 92.68 92.678 92.68 92.678-41.576 92.678-92.68c0-51.104-41.574-92.678-92.678-92.678zM512 544.672c-18.014 0-32.67-14.656-32.67-32.672s14.656-32.67 32.67-32.67 32.67 14.656 32.67 32.67c0.002 18.014-14.654 32.672-32.67 32.672z"></path></g></svg>';
		var icoQuickViewLink = '<svg width="32" height="32" viewBox="0 0 32 32"><use xlink:href="#boost-pfs-icon-quick-view"></use></svg>';

		var productUrl = Utils.buildProductItemUrl(this.parent.data) + '?view=boost-pfs-quickview';
		return this.getTemplate()
			.replace(/{{label.quickview}}/g, Labels.action_list.qvBtnLabel)
			.replace(/{{productUrl}}/g, productUrl)
			.replace(/{{icoQuickView}}/g, productIsFirst ? icoQuickView : icoQuickViewLink);
	}

	render() {
		if (!this.$element) {
			this.$element = jQ(this.compileTemplate());
		}
	}

	bindEvents() {
		if (this.$element) {
			this.$element.on('click', this.getQuickViewModalContent.bind(this));
		}
	}

	getQuickViewModalContent(e) {
		if (!e) return;
		e.stopPropagation();
		e.preventDefault();

		// Get quickview url
		var url = jQ(e.currentTarget).data('href');

		this.isGetQuickViewOption = jQ(e.currentTarget).attr('data-get-quickview-option') ? true : false;

		// Clear all select option in product item
		jQ('.boost-pfs-select-option-wrapper').remove();
		jQ('.boost-pfs-select-option-show').removeClass('boost-pfs-select-option-show');

		if (this.isGetQuickViewOption) {
			jQ(e.currentTarget).removeAttr('data-get-quickview-option');
			url += '-option';
			this.parent.$element.addClass('boost-pfs-select-option-show');
		} else {
			// Hide the quickview button so it doesn't show on top of modal
			this.$element.closest('.boost-pfs-action-list-wrapper').css('visibility', 'hidden');
			// Render the backdrop and modal empty html
			this.renderQuickViewBackdrop();
		}

		// Set up HTTP request
		var xhr = new XMLHttpRequest();
		xhr.open('GET', url);
		xhr.setRequestHeader("Content-Type", "text/html;charset=UTF-8");
		xhr.onload = function () {
			// On sucess, render the modal
			if (xhr.readyState > 3 && xhr.status == 200) {
				this.renderQuickViewModal(xhr.responseText);
				this.bindQuickViewModalEvents();
			}
		}.bind(this);

		// Send request
		xhr.send();
		if (boostPFS.filter && !this.isGetQuickViewOption) {
			boostPFS.filter.filterLoadingIcon.setShow(true);
		}
	}

	renderQuickViewBackdrop() {
		if (jQ('.boost-pfs-modal-backdrop').length == 0) {
			jQ('body').append(this.getModalTemplate());
			jQ('.boost-pfs-modal-backdrop').on('click', this.closeModal.bind(this));
		}
		jQ('.boost-pfs-modal-backdrop').show();
		jQ('.boost-pfs-modal-container').hide();
		jQ('body').addClass('boost-pfs-body-no-scroll');
		jQ('html').addClass('boost-pfs-body-no-scroll');
	}

	renderQuickViewModal(modalHtml) {
		if (boostPFS.filter) {
			boostPFS.filter.filterLoadingIcon.setShow(false);
		}
		if (this.isGetQuickViewOption) {
			var $container = this.parent.$element;
			if (Settings.getSettingValue('general.selectOptionContainer')) {
				$container = this.parent.$element.find(Settings.getSettingValue('general.selectOptionContainer'));
			}
			if ($container.length > 0) {
				$container.find('.boost-pfs-select-option-wrapper').remove();
				$container.append('<div class="boost-pfs-select-option-wrapper"><div class="boost-pfs-select-option-close"></div>'+ modalHtml +'</div>');
				
				
			}
		} else {
			jQ('.boost-pfs-modal-content').html(modalHtml);
			jQ('.boost-pfs-modal-container').show();
		}
	}

	bindQuickViewModalEvents() {
		if (this.isGetQuickViewOption) {
			if (Settings.getSettingValue('general.enableAjaxCart')) {
				this.parent.$element.find('#boost-pfs-quickview-cart-form-' + this.parent.data.id).on('submit', this.onClickAddToCart.bind(this));
			}
			jQ('.boost-pfs-select-option-close').on('click', function(){
				jQ('.boost-pfs-select-option-wrapper').hide();
				jQ('.boost-pfs-action-list-enabled').removeClass('boost-pfs-select-option-show');
			});
		} else {
			this.initImageSlider();
			jQ('.boost-pfs-quickview-close').on('click', this.closeModal.bind(this));

			// Bind changing options
			jQ('.boost-pfs-quickview-select-option').on('change', this.onChangeVariant.bind(this));
			jQ('.boost-pfs-quickview-select-option-color').on('change', this.onChangeVariant.bind(this));

			// Bind changing options with enter/space key for ADA
			jQ('.boost-pfs-swatch-element label').on('keydown', (event) => {
				if (event.target && (event.keyCode == 13 || event.keyCode == 32)) {
					jQ(event.target).click();
				}
			});

			if (Settings.getSettingValue('general.enableAjaxCart')) {
				jQ('#boost-pfs-quickview-cart-form').on('submit', this.onClickAddToCart.bind(this));
			}

			// Focus inside quickview
			jQ('.boost-pfs-quickview-close').focus();
		}
	}

	closeModal(e) {
		var $target = jQ(e.target);
		if (!$target.hasClass('boost-pfs-modal-backdrop')
			&& !$target.hasClass('boost-pfs-modal-container')
			&& !$target.hasClass('boost-pfs-quickview-close')) return;
		jQ('.boost-pfs-modal-backdrop').hide();
		jQ('.boost-pfs-modal-container').hide();
		jQ('body').removeClass('boost-pfs-body-no-scroll');
		jQ('html').removeClass('boost-pfs-body-no-scroll');

		// Focus on the product item (ADA)
		if (jQ('body').hasClass('boost-pfs-ada') && this.parent.$element) {
			this.parent.$element.find('.boost-pfs-action-list-wrapper').css({visibility: 'visible'});
			setTimeout(() => {
				console.log(this.$element);
				this.$element.focus();
				}, 200);
		}
	}

	initImageSlider() {
		var $itemsWrapper = jQ('.boost-pfs-quickview-featured-image-wrapper');
		var $items = jQ('.boost-pfs-quickview-featured-image');
		var $prev = jQ('.boost-pfs-quickview-slider-prev');
		var $next = jQ('.boost-pfs-quickview-slider-next');
		var $dots = jQ('.boost-pfs-quickview-slider-dot');
		if ($itemsWrapper.length == 0 || $items.length == 0) return;

		this.imageSlider = {
			$itemsWrapper: $itemsWrapper,
			$prev: $prev,
			$next: $next,
			$dots: $dots,
			posX1: 0,
			posX2: 0,
			posInitial: 0,
			posFinal: 0,
			threshold: 50,
			slidesLength: $items.length,
			slideSize: $items[0].offsetWidth,
			index: 0,
			allowShift: true,
			isDragging: false
		}

		// Init css classes
		if (this.imageSlider.index == 0) {
			this.imageSlider.$prev.addClass('disabled');
		}
		if (this.imageSlider.index == this.imageSlider.slidesLength - 1) {
			this.imageSlider.$next.addClass('disabled');
		}
		this.imageSlider.$itemsWrapper.css('left', '0px');
		this.imageSlider.$dots.first().addClass('active');

		// Mouse events
		this.imageSlider.$itemsWrapper.on('mousedown', this.dragStart.bind(this));
		jQ(document).off('mousemove');
		jQ(document).off('mouseup');
		jQ(document).on('mousemove', this.dragAction.bind(this));
		jQ(document).on('mouseup', this.dragEnd.bind(this));

		// Click events
		this.imageSlider.$prev.on('click', this.shiftSlide.bind(this, null, -1));
		this.imageSlider.$next.on('click', this.shiftSlide.bind(this, null, 1));
		this.imageSlider.$dots.on('click', function (e) {
			var index = jQ(e.currentTarget).data('index');
			this.shiftSlide(index, null);
		}.bind(this))
	}

	dragStart(e) {
		e = e || window.event;
		e.preventDefault();
		this.imageSlider.posInitial = this.imageSlider.$itemsWrapper[0].offsetLeft;
		this.imageSlider.posX1 = e.clientX;
		this.imageSlider.isDragging = true;
	}

	dragAction(e) {
		if (!this.imageSlider.isDragging) return;
		e = e || window.event;
		this.imageSlider.posX2 = this.imageSlider.posX1 - e.clientX;
		this.imageSlider.posX1 = e.clientX;
		var offset = this.imageSlider.$itemsWrapper[0].offsetLeft - this.imageSlider.posX2;
		var offsetMax = this.imageSlider.slideSize * 0.2;
		var offsetMin = -this.imageSlider.slideSize * (this.imageSlider.slidesLength - 0.8);
		if (offset > offsetMax) {
			offset = offsetMax;
		} else if (offset < offsetMin) {
			offset = offsetMin;
		}
		this.imageSlider.$itemsWrapper.css('left', offset + "px");
	}

	dragEnd(e) {
		if (!this.imageSlider.isDragging) return;
		this.imageSlider.isDragging = false;
		this.imageSlider.posFinal = this.imageSlider.$itemsWrapper[0].offsetLeft;
		if (this.imageSlider.posFinal - this.imageSlider.posInitial < -this.imageSlider.threshold) {
			this.shiftSlide(null, 1);
		} else if (this.imageSlider.posFinal - this.imageSlider.posInitial > this.imageSlider.threshold) {
			this.shiftSlide(null, -1);
		} else {
			this.imageSlider.$itemsWrapper.css('left', (this.imageSlider.posInitial) + "px");
		}
	}

	shiftSlide(slideIndex, direction) {
		if (slideIndex == null) {
			slideIndex = this.imageSlider.index + direction;
		}
		if (this.imageSlider.allowShift) {
			var currentOffset = this.imageSlider.$itemsWrapper.css('left');
			var newOffset;

			if (slideIndex > -1 && slideIndex < this.imageSlider.slidesLength) {
				newOffset = (-1 * slideIndex * this.imageSlider.slideSize) + "px";
				this.imageSlider.index = slideIndex;
			} else {
				newOffset = (-1 * this.imageSlider.index * this.imageSlider.slideSize) + "px";
			}

			if (currentOffset != newOffset) {
				// Update previous/next
				if (this.imageSlider.index == 0) {
					this.imageSlider.$prev.addClass('disabled');
				} else {
					this.imageSlider.$prev.removeClass('disabled');
				}
				if (this.imageSlider.index == this.imageSlider.slidesLength - 1) {
					this.imageSlider.$next.addClass('disabled');
				} else {
					this.imageSlider.$next.removeClass('disabled');
				}
				// Update dots
				this.imageSlider.$dots.removeClass('active');
				this.imageSlider.$dots.eq(this.imageSlider.index).addClass('active');
				// Slide image
				this.imageSlider.$itemsWrapper.addClass('boost-pfs-quickview-slider-shifting');
				this.imageSlider.$itemsWrapper.css('left', newOffset);

				this.imageSlider.allowShift = false;
				setTimeout(this.afterShiftSlide.bind(this), 300);
			}
		}
	}

	afterShiftSlide() {
		this.imageSlider.$itemsWrapper.removeClass('boost-pfs-quickview-slider-shifting');
		this.imageSlider.allowShift = true;
	}

	onClickAddToCart(e) {
		if (e) e.preventDefault();
		var selectedVariant = this._getSelectedVariant();
		var quantity = 1;
		var $addingLabel = null;
		var $errorLabel = null;
		if (this.isGetQuickViewOption) {
			$addingLabel = jQ('.boost-pfs-quickview-cart-btn-text');
			$errorLabel = jQ('.boost-pfs-select-option-wrapper .boost-pfs-addtocart-error-label');
		} else {
			quantity = jQ('#boost-pfs-quickview-cart-quantity').val();
			$addingLabel = jQ('#boost-pfs-quickview-cart-btn-text');
			$errorLabel = jQ('#boost-pfs-addtocart-error-label');
		}
		if (selectedVariant) {
			AjaxCart.instance.addToCart(selectedVariant.id, quantity, $addingLabel, $errorLabel);
		}
	}

	onChangeVariant() {
		var selectedVariant = this._getSelectedVariant();
		this._updateQuickViewModal(selectedVariant);
		if (selectedVariant != null && selectedVariant.image) {
			jQ('.boost-pfs-quickview-slider-dot[data-image="' + Utils.optimizeImage(selectedVariant.image, 'small').replace('https:', '') + '"]').click();
		}
	}

	_getSelectedVariant() {
		// Option name field (fixed by shopify)
		var optionNames = ['option1', 'option2', 'option3'];

		// Get the selected options from the quickview form
		var formData = null;
        if (this.isGetQuickViewOption) {
        	formData = jQ('#boost-pfs-quickview-cart-form-'+ this.parent.data.id).serializeArray();
        } else {
        	formData = jQ('#boost-pfs-quickview-cart-form').serializeArray();
        }

		var selectedOptions = [];
		formData.forEach(entry => {
			if (optionNames.includes(entry.name)) {
				selectedOptions.push(entry);
			}
		})

		// Back end only return "merged_options", so we need to get original option data from liquid
		var variantOptionData = [];
        if (this.isGetQuickViewOption) {
        	variantOptionData = JSON.parse(jQ('.boost-pfs-quickview-variants-data-' + this.parent.data.id).html());
        } else {
        	variantOptionData = JSON.parse(jQ('#boost-pfs-quickview-variants-data').html());
        }

		// Find the selected variant
		var selectedVariant = null;
		variantOptionData.forEach(variant => {
			// Return if found variant
			if (selectedVariant) return;

			// Check if variant's option match with the selected option
			var isMatchAllOptions = true;
			selectedOptions.forEach(option => {
				if (!isMatchAllOptions) return;

				var variantValue = variant[option.name];
				var optionValue = option.value;
				if (variantValue != null && optionValue != null && variantValue != optionValue) isMatchAllOptions = false;
			})
			if (isMatchAllOptions) selectedVariant = variant;
		})

		// Merge variant data from liquid with variant data from our API
		if (selectedVariant && selectedVariant.id) {
			if (this.parent && this.parent.data && Array.isArray(this.parent.data.variants)) {
				var variantData = this.parent.data.variants.find(data => data.id == selectedVariant.id);
				if (variantData) {
					Object.assign(selectedVariant, variantData);
				}
			}
		}

		return selectedVariant;
	}

	_updateQuickViewModal(selectedVariant) {
		// Update variant input & button text
		var $selectElement = jQ('#boost-pfs-quickview-variants-selector')
		var $cartButton = jQ('#boost-pfs-quickview-cart-btn');
		var $cartButtonText = jQ('#boost-pfs-quickview-cart-btn-text');
		var $priceWrapper = jQ('.boost-pfs-quickview-price-wrapper');

		if (selectedVariant && selectedVariant.available) {
			$selectElement.val(selectedVariant.id);
			$cartButton.removeAttr("disabled");
			$cartButtonText.html(Labels.action_list.qvAddToCartBtnLabel);

			// Get the price labels
			var $option = $selectElement.find(":selected");
			var priceHtml = $option.data('current-price');
			var compareAtPriceHtml = $option.data('was-price');

			// Check if onsale or not
			var price = $option.data('current-price-without-currency');
			if (price && typeof price == 'string') {
				price = price.replace(/[ ,.]/g, "");
			}
			var compareAtPrice = $option.data('was-price-without-currency');
			if (compareAtPrice && typeof compareAtPrice == 'string') {
				compareAtPrice = compareAtPrice.replace(/[ ,.]/g, "");
			}
			var onSale = false;
			if (price && compareAtPrice) {
				onSale = parseFloat(compareAtPrice) > parseFloat(price);
			}

			// Replace price labels in DOM
			if (onSale) {
				jQ('#boost-pfs-quickview-current-price').html(priceHtml);
				jQ('#boost-pfs-quickview-was-price').html(compareAtPriceHtml);
				$priceWrapper.addClass('boost-pfs-quickview-price-on-sale');
			} else {
				jQ('#boost-pfs-quickview-current-price').html(priceHtml);
				jQ('#boost-pfs-quickview-was-price').html('');
				$priceWrapper.removeClass('boost-pfs-quickview-price-on-sale');
			}

		} else {
			$cartButton.attr("disabled", true);
			$cartButtonText.html(Labels.action_list.qvSoldOutLabel);
		}
	}
}

export default QuickView;