From 587e065fba83e0270f359ea36797974101b9fd53 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Fri, 23 Jun 2023 08:23:11 +0100 Subject: [PATCH] Refactored button display logic Replaced show / hide buttons mode with enable / disable buttons mode --- .../SingleProductActionHandler.js | 1 - .../ContextBootstrap/SingleProductBootstap.js | 67 +++++++++++-------- .../js/modules/Helper/ButtonDisabler.js | 58 ++++++++++++++++ .../modules/Helper/ButtonsToggleListener.js | 39 ----------- 4 files changed, 98 insertions(+), 67 deletions(-) create mode 100644 modules/ppcp-button/resources/js/modules/Helper/ButtonDisabler.js delete mode 100644 modules/ppcp-button/resources/js/modules/Helper/ButtonsToggleListener.js diff --git a/modules/ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler.js b/modules/ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler.js index 3c3371542..146fd7e94 100644 --- a/modules/ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler.js +++ b/modules/ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler.js @@ -1,4 +1,3 @@ -import ButtonsToggleListener from '../Helper/ButtonsToggleListener'; import Product from '../Entity/Product'; import onApprove from '../OnApproveHandler/onApproveForContinue'; import {payerData} from "../Helper/PayerData"; diff --git a/modules/ppcp-button/resources/js/modules/ContextBootstrap/SingleProductBootstap.js b/modules/ppcp-button/resources/js/modules/ContextBootstrap/SingleProductBootstap.js index 376962772..c6b86657c 100644 --- a/modules/ppcp-button/resources/js/modules/ContextBootstrap/SingleProductBootstap.js +++ b/modules/ppcp-button/resources/js/modules/ContextBootstrap/SingleProductBootstap.js @@ -1,7 +1,6 @@ import UpdateCart from "../Helper/UpdateCart"; import SingleProductActionHandler from "../ActionHandler/SingleProductActionHandler"; -import {hide, show, setVisible} from "../Helper/Hiding"; -import ButtonsToggleListener from "../Helper/ButtonsToggleListener"; +import {disable, enable} from "../Helper/ButtonDisabler"; class SingleProductBootstap { constructor(gateway, renderer, messages, errorHandler) { @@ -10,56 +9,70 @@ class SingleProductBootstap { this.messages = messages; this.errorHandler = errorHandler; this.mutationObserver = new MutationObserver(this.handleChange.bind(this)); + this.formSelector = 'form.cart'; } + form() { + return document.querySelector(this.formSelector); + } handleChange() { - const shouldRender = this.shouldRender(); - setVisible(this.gateway.button.wrapper, shouldRender); - setVisible(this.gateway.messages.wrapper, shouldRender); - if (!shouldRender) { + if (!this.shouldRender()) { return; } this.render(); + this.handleButtonStatus(); + } + + handleButtonStatus() { + if (!this.shouldEnable()) { + disable(this.gateway.button.wrapper, this.formSelector); + disable(this.gateway.messages.wrapper); + return; + } + enable(this.gateway.button.wrapper); + enable(this.gateway.messages.wrapper); + this.messages.renderWithAmount(this.priceAmount()) } init() { - const form = document.querySelector('form.cart'); + const form = this.form(); + if (!form) { return; } form.addEventListener('change', this.handleChange.bind(this)); - this.mutationObserver.observe(form, {childList: true, subtree: true}); + this.mutationObserver.observe(form, { childList: true, subtree: true }); - const buttonObserver = new ButtonsToggleListener( - form.querySelector('.single_add_to_cart_button'), - () => { - show(this.gateway.button.wrapper); - show(this.gateway.messages.wrapper); - this.messages.renderWithAmount(this.priceAmount()) - }, - () => { - hide(this.gateway.button.wrapper); - hide(this.gateway.messages.wrapper); - }, - ); - buttonObserver.init(); + const addToCartButton = form.querySelector('.single_add_to_cart_button'); + + if (addToCartButton) { + (new MutationObserver(this.handleButtonStatus.bind(this))) + .observe(addToCartButton, { attributes : true }); + } if (!this.shouldRender()) { - hide(this.gateway.button.wrapper); - hide(this.gateway.messages.wrapper); return; } this.render(); + this.handleButtonStatus(); } shouldRender() { - return document.querySelector('form.cart') !== null + return this.form() !== null + && !this.isDisabledReasonExternalPlugins(); + } + + shouldEnable() { + const form = this.form(); + const addToCartButton = form ? form.querySelector('.single_add_to_cart_button') : null; + + return this.shouldRender() && !this.priceAmountIsZero() - && !this.isSubscriptionMode(); + && ((null === addToCartButton) || !addToCartButton.classList.contains('disabled')); } priceAmount() { @@ -93,7 +106,7 @@ class SingleProductBootstap { return !price || price === 0; } - isSubscriptionMode() { + isDisabledReasonExternalPlugins() { // Check "All products for subscriptions" plugin. return document.querySelector('.wcsatt-options-product:not(.wcsatt-options-product--hidden) .subscription-option input[type="radio"]:checked') !== null || document.querySelector('.wcsatt-options-prompt-label-subscription input[type="radio"]:checked') !== null; // grouped @@ -106,7 +119,7 @@ class SingleProductBootstap { this.gateway.ajax.change_cart.endpoint, this.gateway.ajax.change_cart.nonce, ), - document.querySelector('form.cart'), + this.form(), this.errorHandler, ); diff --git a/modules/ppcp-button/resources/js/modules/Helper/ButtonDisabler.js b/modules/ppcp-button/resources/js/modules/Helper/ButtonDisabler.js new file mode 100644 index 000000000..b9f98cbab --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/Helper/ButtonDisabler.js @@ -0,0 +1,58 @@ +/** + * @param selectorOrElement + * @returns {Element} + */ +const getElement = (selectorOrElement) => { + if (typeof selectorOrElement === 'string') { + return document.querySelector(selectorOrElement); + } + return selectorOrElement; +} + +export const setEnabled = (selectorOrElement, enable, form = null) => { + const element = getElement(selectorOrElement); + + if (!element) { + return; + } + + if (enable) { + jQuery(element).css({ + 'cursor': '', + '-webkit-filter': '', + 'filter': '', + } ) + .off('mouseup') + .find('> *') + .css('pointer-events', ''); + } else { + jQuery(element).css( { + 'cursor': '', + '-webkit-filter': '', + 'filter': '', + } ) + .css({ + 'cursor': 'not-allowed', + '-webkit-filter': 'grayscale(100%)', + 'filter': 'grayscale(100%)', + }) + .on('mouseup', function(event) { + event.stopImmediatePropagation(); + + if (form) { + // Trigger form submit to show the error message + jQuery(form).find(':submit').trigger('click'); + } + }) + .find('> *') + .css('pointer-events', 'none'); + } +}; + +export const disable = (selectorOrElement, form = null) => { + setEnabled(selectorOrElement, false, form); +}; + +export const enable = (selectorOrElement) => { + setEnabled(selectorOrElement, true); +}; diff --git a/modules/ppcp-button/resources/js/modules/Helper/ButtonsToggleListener.js b/modules/ppcp-button/resources/js/modules/Helper/ButtonsToggleListener.js deleted file mode 100644 index add1ee28a..000000000 --- a/modules/ppcp-button/resources/js/modules/Helper/ButtonsToggleListener.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * When you can't add something to the cart, the PayPal buttons should not show. - * Therefore we listen for changes on the add to cart button and show/hide the buttons accordingly. - */ - -class ButtonsToggleListener { - constructor(element, showCallback, hideCallback) - { - this.element = element; - this.showCallback = showCallback; - this.hideCallback = hideCallback; - this.observer = null; - } - - init() - { - if (!this.element) { - return; - } - const config = { attributes : true }; - const callback = () => { - if (this.element.classList.contains('disabled')) { - this.hideCallback(); - return; - } - this.showCallback(); - } - this.observer = new MutationObserver(callback); - this.observer.observe(this.element, config); - callback(); - } - - disconnect() - { - this.observer.disconnect(); - } -} - -export default ButtonsToggleListener;