From 890175a35dad43dda1417be48fae434cb76ef489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Ste=CC=A8pien=CC=81?= <igor@istepien.dev> Date: Wed, 4 Oct 2023 00:26:32 +0200 Subject: [PATCH 1/2] product quick view fixes --- _dev/js/theme/components/product.js | 8 +++++--- .../handler/product/productPopStateHandler.js | 4 +++- .../updateProductCustomizationHandler.js | 4 +++- .../updateProductDOMElementsHandler.js | 20 ++++++++++--------- .../handler/product/updateProductHandler.js | 11 +++++++--- .../product/updateQuantityInputHandler.js | 4 +++- .../utils/productEventContextSelector.js | 13 ++++++++++++ _dev/js/theme/core/selectors.js | 17 ++++++++-------- templates/catalog/_partials/quickview.tpl | 5 ++++- 9 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 _dev/js/theme/core/product/utils/productEventContextSelector.js diff --git a/_dev/js/theme/components/product.js b/_dev/js/theme/components/product.js index a611c987..3cc7f8a4 100644 --- a/_dev/js/theme/components/product.js +++ b/_dev/js/theme/components/product.js @@ -2,6 +2,7 @@ import $ from 'jquery'; import prestashop from 'prestashop'; import useCustomQuantityInput from './useCustomQuantityInput'; import { each } from '../utils/DOMHelpers'; +import productEventContextSelector from "../core/product/utils/productEventContextSelector"; $(() => { const createInputFile = () => { @@ -29,7 +30,7 @@ $(() => { init(); }; - each('.js-product-qty-spinner', initQtySpinner); + each(`${productEventContextSelector()} .js-product-qty-spinner`, initQtySpinner); }; initProductQuantityInput(); @@ -56,10 +57,11 @@ $(() => { prestashop.on('updatedProduct', (event) => { createInputFile(); + const contextSelector = productEventContextSelector(); if (updateEvenType === 'updatedProductCombination') { - $('.js-product-images').replaceWith(event.product_cover_thumbnails); - $('.js-product-images-modal').replaceWith(event.product_images_modal); + $(`${contextSelector} .js-product-images`).replaceWith(event.product_cover_thumbnails); + $(`${contextSelector} .js-product-images-modal`).replaceWith(event.product_images_modal); prestashop.emit('updatedProductCombination', event); } diff --git a/_dev/js/theme/core/product/handler/product/productPopStateHandler.js b/_dev/js/theme/core/product/handler/product/productPopStateHandler.js index 12c2d69c..4f4b5082 100644 --- a/_dev/js/theme/core/product/handler/product/productPopStateHandler.js +++ b/_dev/js/theme/core/product/handler/product/productPopStateHandler.js @@ -1,6 +1,7 @@ import prestashop from 'prestashop'; import productFormDataPersister from '../../persister/productFormDataPersister'; import productStateStore from '../../store/productStateStore'; +import productEventContextSelector from "../../utils/productEventContextSelector"; const { setOnPopState, isFormChanged } = productStateStore(); @@ -12,6 +13,7 @@ const { get } = productFormDataPersister(); * @param {Event} event */ const productPopStateHandler = (event) => { + const contextElement = document.querySelector(productEventContextSelector()); setOnPopState(true); const formData = event?.state?.form || get(); @@ -20,7 +22,7 @@ const productPopStateHandler = (event) => { return; } - const form = document.querySelector(`${prestashop.selectors.product.actions} .js-product-form`); + const form = contextElement.querySelector(`${prestashop.selectors.product.actions} .js-product-form`); const handleFormElementState = (data) => { const element = form.querySelector(`[name="${data.name}"]`); diff --git a/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js b/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js index 48d3d692..afcd7dd5 100644 --- a/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js +++ b/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js @@ -1,4 +1,5 @@ import prestashop from 'prestashop'; +import productEventContextSelector from "../../utils/productEventContextSelector"; /** * Update product customization input value @@ -9,7 +10,8 @@ import prestashop from 'prestashop'; * @return {void} */ const updateProductCustomizationHandler = (eventType, { id_customization: idCustomization }) => { - const customizationIdInput = document.querySelector(prestashop.selectors.cart.productCustomizationId); + const contextElement = document.querySelector(productEventContextSelector()); + const customizationIdInput = contextElement.querySelector(prestashop.selectors.cart.productCustomizationId); // refill customizationId input value when updating quantity or combination if ( diff --git a/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js b/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js index 160468a9..03c0e06c 100644 --- a/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js +++ b/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js @@ -1,6 +1,7 @@ import prestashop from 'prestashop'; import parseToHtml from '../../../../utils/parseToHtml'; import { each } from '../../../../utils/DOMHelpers'; +import productEventContextSelector from "../../utils/productEventContextSelector"; /** * Replace element with new html string @@ -41,15 +42,16 @@ const updateProductDOMElementsHandler = ({ product_add_to_cart, /* eslint-enable */ }) => { - each(prestashop.selectors.product.imageContainer, (el) => replaceElement(el, product_cover_thumbnails)); - each(prestashop.selectors.product.prices, (el) => replaceElement(el, product_prices)); - each(prestashop.selectors.product.customization, (el) => replaceElement(el, product_customization)); - each(prestashop.selectors.product.variantsUpdate, (el) => replaceElement(el, product_variants)); - each(prestashop.selectors.product.discounts, (el) => replaceElement(el, product_discounts)); - each(prestashop.selectors.product.additionalInfos, (el) => replaceElement(el, product_additional_info)); - each(prestashop.selectors.product.details, (el) => replaceElement(el, product_details)); - each(prestashop.selectors.product.flags, (el) => replaceElement(el, product_flags)); - each(prestashop.selectors.product.addToCart, (el) => replaceElement(el, product_add_to_cart)); + const contextSelector = productEventContextSelector(); + + each(`${contextSelector} ${prestashop.selectors.product.prices}`, (el) => replaceElement(el, product_prices)); + each(`${contextSelector} ${prestashop.selectors.product.customization}`, (el) => replaceElement(el, product_customization)); + each(`${contextSelector} ${prestashop.selectors.product.variantsUpdate}`, (el) => replaceElement(el, product_variants)); + each(`${contextSelector} ${prestashop.selectors.product.discounts}`, (el) => replaceElement(el, product_discounts)); + each(`${contextSelector} ${prestashop.selectors.product.additionalInfos}`, (el) => replaceElement(el, product_additional_info)); + each(`${contextSelector} ${prestashop.selectors.product.details}`, (el) => replaceElement(el, product_details)); + each(`${contextSelector} ${prestashop.selectors.product.flags}`, (el) => replaceElement(el, product_flags)); + each(`${contextSelector} ${prestashop.selectors.product.addToCart}`, (el) => replaceElement(el, product_add_to_cart)); }; export default updateProductDOMElementsHandler; diff --git a/_dev/js/theme/core/product/handler/product/updateProductHandler.js b/_dev/js/theme/core/product/handler/product/updateProductHandler.js index 9d2c25f7..7d2a489d 100644 --- a/_dev/js/theme/core/product/handler/product/updateProductHandler.js +++ b/_dev/js/theme/core/product/handler/product/updateProductHandler.js @@ -8,6 +8,7 @@ import updateQuantityInputHandler from './updateQuantityInputHandler'; import updateProductCustomizationHandler from './updateProductCustomizationHandler'; import updateProductDOMElementsHandler from './updateProductDOMElementsHandler'; import { fromSerializeObject } from '../../../../utils/formSerialize'; +import productEventContextSelector from "../../utils/productEventContextSelector"; const { getCurrentRequestDelayedId, setCurrentRequestDelayedId } = productStateStore(); @@ -18,7 +19,9 @@ const { getCurrentRequestDelayedId, setCurrentRequestDelayedId } = productStateS * @return {Promise<void>} */ const updateProductHandler = async ({ eventType }) => { - const productActions = document.querySelector(prestashop.selectors.product.actions); + const isQuickView = isQuickViewOpen(); + const contextElement = document.querySelector(productEventContextSelector()); + const productActions = contextElement.querySelector(prestashop.selectors.product.actions); const quantityWantedInput = productActions.querySelector(prestashop.selectors.quantityWanted); const form = productActions.querySelector('.js-product-form'); @@ -38,7 +41,7 @@ const updateProductHandler = async ({ eventType }) => { const payload = { quantity_wanted: Number.parseInt(quantityWantedInput.value, 10), preview: isProductPreview() ? 1 : 0, - quickview: isQuickViewOpen() ? 1 : 0, + quickview: isQuickView ? 1 : 0, ...formSerialized, id_product: Number.parseInt(formSerialized.id_product, 10), id_product_attribute: Number.parseInt(idProductAttribute, 10), @@ -53,7 +56,9 @@ const updateProductHandler = async ({ eventType }) => { updateProductCustomizationHandler(eventType, data); updateQuantityInputHandler(eventType, data); - document.dispatchEvent(updateRatingEvent); + if (isQuickView) { + document.dispatchEvent(updateRatingEvent); + } const { persist, get: getPersistedData } = productFormDataPersister(); persist(form); diff --git a/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js b/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js index 9339378d..f9d41637 100644 --- a/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js +++ b/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js @@ -1,4 +1,5 @@ import prestashop from 'prestashop'; +import productEventContextSelector from "../../utils/productEventContextSelector"; /** * Update quantity input value @@ -11,9 +12,10 @@ const updateQuantityInputHandler = (eventType, { product_minimal_quantity: produ productMinimalQuantity, 10, ); + const contextElement = document.querySelector(productEventContextSelector()); if (!Number.isNaN(minimalProductQuantity) && eventType !== 'updatedProductQuantity') { - const newQtyInput = document.querySelector(`${prestashop.selectors.product.actions} ${prestashop.selectors.quantityWanted}`); + const newQtyInput = contextElement.querySelector(`${prestashop.selectors.product.actions} ${prestashop.selectors.quantityWanted}`); newQtyInput.value = minimalProductQuantity; } }; diff --git a/_dev/js/theme/core/product/utils/productEventContextSelector.js b/_dev/js/theme/core/product/utils/productEventContextSelector.js new file mode 100644 index 00000000..a656a59f --- /dev/null +++ b/_dev/js/theme/core/product/utils/productEventContextSelector.js @@ -0,0 +1,13 @@ +import isQuickViewOpen from "./isQuickViewOpen"; +import prestashop from "prestashop"; + +const productEventContextSelector = () => { + const { + quickViewModal, + container, + } = prestashop.selectors.product; + + return isQuickViewOpen() ? quickViewModal : container; +} + +export default productEventContextSelector; diff --git a/_dev/js/theme/core/selectors.js b/_dev/js/theme/core/selectors.js index 368d9291..ee546be5 100644 --- a/_dev/js/theme/core/selectors.js +++ b/_dev/js/theme/core/selectors.js @@ -12,7 +12,8 @@ prestashop.selectors = { modalProductCover: '.js-modal-product-cover', cover: '.js-qv-product-cover', customizationModal: '.js-customization-modal', - imageContainer: '.js-quickview js-images-container, .page-product:not(.js-quickview-open) .js-product-container .images-container', + quickViewModal: '.js-quickview', + imageContainer: '.js-product-images', container: '.js-product-container', availability: '.js-product-availability', actions: '.js-product-actions', @@ -21,16 +22,16 @@ prestashop.selectors = { miniature: '.js-product-miniature', minimalQuantity: '.js-product-minimal-quantity', addToCart: '.js-product-add-to-cart', - prices: '.js-quickview .js-product-prices, .page-product:not(.js-quickview-open) .js-product-prices', + prices: '.js-product-prices', inputCustomization: '.js-product-actions .js-product-customization-id', // eslint-disable-next-line max-len - customization: '.js-quickview .js-product-customization, .page-product:not(.js-quickview-open) .js-product-container .js-product-customization', - variantsUpdate: '.js-quickview .js-product-variants, .page-product:not(.js-quickview-open) .js-product-container .js-product-variants', - discounts: '.js-quickview .js-product-discounts, .page-product:not(.js-quickview-open) .js-product-container .js-product-discounts', + customization: '.js-product-customization', + variantsUpdate: '.js-product-variants', + discounts: '.js-product-discounts', // eslint-disable-next-line max-len - additionalInfos: '.js-quickview .js-product-additional-info, .page-product:not(.js-quickview-open) .js-product-container .js-product-additional-info', - details: '.js-quickview .js-product-details, .page-product:not(.js-quickview-open) .js-product-container .js-product-details', - flags: '.js-quickview .js-product-flags, .page-product:not(.js-quickview-open) .js-product-container .js-product-flags', + additionalInfos: '.js-product-additional-info', + details: '.js-product-details', + flags: '.js-product-flags', }, listing: { searchFilterToggler: '.js-search-toggler', diff --git a/templates/catalog/_partials/quickview.tpl b/templates/catalog/_partials/quickview.tpl index 8340e886..52b6b69d 100644 --- a/templates/catalog/_partials/quickview.tpl +++ b/templates/catalog/_partials/quickview.tpl @@ -48,7 +48,10 @@ {/block} {block name='product_buy'} <div class="product-actions js-product-actions"> - <form action="{$urls.pages.cart}" method="post" id="add-to-cart-or-refresh"> + <form action="{$urls.pages.cart}" + method="post" + id="add-to-cart-or-refresh" + class="js-product-form"> <input type="hidden" name="token" value="{$static_token}"> <input type="hidden" name="id_product" value="{$product.id}" id="product_page_product_id"> <input type="hidden" name="id_customization" value="{$product.id_customization}" id="product_customization_id" class="js-product-customization-id"> From a03c37b7fad5e35ad8679dd616915a1777f81992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Ste=CC=A8pien=CC=81?= <igor@istepien.dev> Date: Wed, 4 Oct 2023 00:27:54 +0200 Subject: [PATCH 2/2] es-lint fix --- _dev/js/theme/components/product.js | 2 +- .../core/product/handler/product/productPopStateHandler.js | 2 +- .../handler/product/updateProductCustomizationHandler.js | 2 +- .../handler/product/updateProductDOMElementsHandler.js | 2 +- .../core/product/handler/product/updateProductHandler.js | 2 +- .../product/handler/product/updateQuantityInputHandler.js | 2 +- .../theme/core/product/utils/productEventContextSelector.js | 6 +++--- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/_dev/js/theme/components/product.js b/_dev/js/theme/components/product.js index 3cc7f8a4..4a11a510 100644 --- a/_dev/js/theme/components/product.js +++ b/_dev/js/theme/components/product.js @@ -2,7 +2,7 @@ import $ from 'jquery'; import prestashop from 'prestashop'; import useCustomQuantityInput from './useCustomQuantityInput'; import { each } from '../utils/DOMHelpers'; -import productEventContextSelector from "../core/product/utils/productEventContextSelector"; +import productEventContextSelector from '../core/product/utils/productEventContextSelector'; $(() => { const createInputFile = () => { diff --git a/_dev/js/theme/core/product/handler/product/productPopStateHandler.js b/_dev/js/theme/core/product/handler/product/productPopStateHandler.js index 4f4b5082..77182d60 100644 --- a/_dev/js/theme/core/product/handler/product/productPopStateHandler.js +++ b/_dev/js/theme/core/product/handler/product/productPopStateHandler.js @@ -1,7 +1,7 @@ import prestashop from 'prestashop'; import productFormDataPersister from '../../persister/productFormDataPersister'; import productStateStore from '../../store/productStateStore'; -import productEventContextSelector from "../../utils/productEventContextSelector"; +import productEventContextSelector from '../../utils/productEventContextSelector'; const { setOnPopState, isFormChanged } = productStateStore(); diff --git a/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js b/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js index afcd7dd5..ddd6c71c 100644 --- a/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js +++ b/_dev/js/theme/core/product/handler/product/updateProductCustomizationHandler.js @@ -1,5 +1,5 @@ import prestashop from 'prestashop'; -import productEventContextSelector from "../../utils/productEventContextSelector"; +import productEventContextSelector from '../../utils/productEventContextSelector'; /** * Update product customization input value diff --git a/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js b/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js index 03c0e06c..b8221c1d 100644 --- a/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js +++ b/_dev/js/theme/core/product/handler/product/updateProductDOMElementsHandler.js @@ -1,7 +1,7 @@ import prestashop from 'prestashop'; import parseToHtml from '../../../../utils/parseToHtml'; import { each } from '../../../../utils/DOMHelpers'; -import productEventContextSelector from "../../utils/productEventContextSelector"; +import productEventContextSelector from '../../utils/productEventContextSelector'; /** * Replace element with new html string diff --git a/_dev/js/theme/core/product/handler/product/updateProductHandler.js b/_dev/js/theme/core/product/handler/product/updateProductHandler.js index 7d2a489d..20aa2695 100644 --- a/_dev/js/theme/core/product/handler/product/updateProductHandler.js +++ b/_dev/js/theme/core/product/handler/product/updateProductHandler.js @@ -8,7 +8,7 @@ import updateQuantityInputHandler from './updateQuantityInputHandler'; import updateProductCustomizationHandler from './updateProductCustomizationHandler'; import updateProductDOMElementsHandler from './updateProductDOMElementsHandler'; import { fromSerializeObject } from '../../../../utils/formSerialize'; -import productEventContextSelector from "../../utils/productEventContextSelector"; +import productEventContextSelector from '../../utils/productEventContextSelector'; const { getCurrentRequestDelayedId, setCurrentRequestDelayedId } = productStateStore(); diff --git a/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js b/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js index f9d41637..4ca8f82d 100644 --- a/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js +++ b/_dev/js/theme/core/product/handler/product/updateQuantityInputHandler.js @@ -1,5 +1,5 @@ import prestashop from 'prestashop'; -import productEventContextSelector from "../../utils/productEventContextSelector"; +import productEventContextSelector from '../../utils/productEventContextSelector'; /** * Update quantity input value diff --git a/_dev/js/theme/core/product/utils/productEventContextSelector.js b/_dev/js/theme/core/product/utils/productEventContextSelector.js index a656a59f..cebfd0c0 100644 --- a/_dev/js/theme/core/product/utils/productEventContextSelector.js +++ b/_dev/js/theme/core/product/utils/productEventContextSelector.js @@ -1,5 +1,5 @@ -import isQuickViewOpen from "./isQuickViewOpen"; -import prestashop from "prestashop"; +import prestashop from 'prestashop'; +import isQuickViewOpen from './isQuickViewOpen'; const productEventContextSelector = () => { const { @@ -8,6 +8,6 @@ const productEventContextSelector = () => { } = prestashop.selectors.product; return isQuickViewOpen() ? quickViewModal : container; -} +}; export default productEventContextSelector;