Merge pull request #361 from woocommerce/pcp-125-fix-duplicated-button

Fix duplicated button and saved cards in Pay Now
This commit is contained in:
Emili Castells 2021-11-23 11:07:21 +01:00 committed by GitHub
commit 035cbe5957
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 106 additions and 130 deletions

View file

@ -11,3 +11,7 @@
.ppcp-credit-card-gateway-form-field-disabled {
opacity: .5 !important;
}
.ppcp-dcc-order-button {
float: right;
}

View file

@ -1,5 +1,6 @@
import ErrorHandler from '../ErrorHandler';
import CheckoutActionHandler from '../ActionHandler/CheckoutActionHandler';
import { setVisible } from '../Helper/Hiding';
class CheckoutBootstap {
constructor(gateway, renderer, messages, spinner) {
@ -7,31 +8,38 @@ class CheckoutBootstap {
this.renderer = renderer;
this.messages = messages;
this.spinner = spinner;
this.standardOrderButtonSelector = '#place_order';
this.buttonChangeObserver = new MutationObserver((el) => {
this.updateUi();
});
}
init() {
this.render();
// Unselect saved card.
// WC saves form values, so with our current UI it would be a bit weird
// if the user paid with saved, then after some time tries to pay again,
// but wants to enter a new card, and to do that they have to choose “Select payment” in the list.
jQuery('#saved-credit-card').val(jQuery('#saved-credit-card option:first').val());
jQuery(document.body).on('updated_checkout', () => {
this.render()
});
jQuery(document.body).
on('updated_checkout payment_method_selected', () => {
this.switchBetweenPayPalandOrderButton()
this.displayPlaceOrderButtonForSavedCreditCards()
})
jQuery(document.body).on('updated_checkout payment_method_selected', () => {
this.updateUi();
});
jQuery(document).on('hosted_fields_loaded', () => {
jQuery('#saved-credit-card').on('change', () => {
this.displayPlaceOrderButtonForSavedCreditCards()
this.updateUi();
})
});
this.switchBetweenPayPalandOrderButton()
this.displayPlaceOrderButtonForSavedCreditCards()
this.updateUi();
}
shouldRender() {
@ -60,55 +68,35 @@ class CheckoutBootstap {
this.gateway.hosted_fields.wrapper,
actionHandler.configuration(),
);
this.buttonChangeObserver.observe(
document.querySelector(this.standardOrderButtonSelector),
{attributes: true}
);
}
switchBetweenPayPalandOrderButton() {
jQuery('#saved-credit-card').val(jQuery('#saved-credit-card option:first').val());
updateUi() {
const currentPaymentMethod = this.currentPaymentMethod();
const isPaypal = currentPaymentMethod === 'ppcp-gateway';
const isCard = currentPaymentMethod === 'ppcp-credit-card-gateway';
const isSavedCard = isCard && this.isSavedCardSelected();
const isNotOurGateway = !isPaypal && !isCard;
const currentPaymentMethod = jQuery(
'input[name="payment_method"]:checked').val();
setVisible(this.standardOrderButtonSelector, isNotOurGateway || isSavedCard, true);
setVisible(this.gateway.button.wrapper, isPaypal);
setVisible(this.gateway.messages.wrapper, isPaypal);
setVisible(this.gateway.hosted_fields.wrapper, isCard && !isSavedCard);
if (currentPaymentMethod !== 'ppcp-gateway' && currentPaymentMethod !== 'ppcp-credit-card-gateway') {
this.renderer.hideButtons(this.gateway.button.wrapper);
this.renderer.hideButtons(this.gateway.messages.wrapper);
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
jQuery('#place_order').show();
if (isPaypal) {
this.messages.render();
}
else {
jQuery('#place_order').hide();
if (currentPaymentMethod === 'ppcp-gateway') {
this.renderer.showButtons(this.gateway.button.wrapper);
this.renderer.showButtons(this.gateway.messages.wrapper);
this.messages.render()
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper)
if (isCard) {
if (isSavedCard) {
this.disableCreditCardFields();
} else {
this.enableCreditCardFields();
}
if (currentPaymentMethod === 'ppcp-credit-card-gateway') {
this.renderer.hideButtons(this.gateway.button.wrapper)
this.renderer.hideButtons(this.gateway.messages.wrapper)
this.renderer.showButtons(this.gateway.hosted_fields.wrapper)
}
}
}
displayPlaceOrderButtonForSavedCreditCards() {
const currentPaymentMethod = jQuery(
'input[name="payment_method"]:checked').val();
if (currentPaymentMethod !== 'ppcp-credit-card-gateway') {
return;
}
if (jQuery('#saved-credit-card').length && jQuery('#saved-credit-card').val() !== '') {
this.renderer.hideButtons(this.gateway.button.wrapper)
this.renderer.hideButtons(this.gateway.messages.wrapper)
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper)
jQuery('#place_order').show()
this.disableCreditCardFields()
} else {
jQuery('#place_order').hide()
this.renderer.hideButtons(this.gateway.button.wrapper)
this.renderer.hideButtons(this.gateway.messages.wrapper)
this.renderer.showButtons(this.gateway.hosted_fields.wrapper)
this.enableCreditCardFields()
}
}
@ -137,6 +125,15 @@ class CheckoutBootstap {
jQuery('#ppcp-credit-card-vault').attr("disabled", false)
this.renderer.enableCreditCardFields()
}
currentPaymentMethod() {
return jQuery('input[name="payment_method"]:checked').val();
}
isSavedCardSelected() {
const savedCardList = jQuery('#saved-credit-card');
return savedCardList.length && savedCardList.val() !== '';
}
}
export default CheckoutBootstap

View file

@ -1,86 +1,17 @@
import ErrorHandler from '../ErrorHandler';
import CheckoutActionHandler from '../ActionHandler/CheckoutActionHandler';
import CheckoutBootstap from './CheckoutBootstap'
class PayNowBootstrap {
class PayNowBootstrap extends CheckoutBootstap {
constructor(gateway, renderer, messages, spinner) {
this.gateway = gateway;
this.renderer = renderer;
this.messages = messages;
this.spinner = spinner;
super(gateway, renderer, messages, spinner)
}
init() {
this.render();
jQuery(document.body).on('updated_checkout', () => {
this.render();
});
jQuery(document.body).
on('updated_checkout payment_method_selected', () => {
this.switchBetweenPayPalandOrderButton();
});
this.switchBetweenPayPalandOrderButton();
}
shouldRender() {
if (document.querySelector(this.gateway.button.cancel_wrapper)) {
return false;
}
return document.querySelector(this.gateway.button.wrapper) !== null || document.querySelector(this.gateway.hosted_fields.wrapper) !== null;
}
render() {
if (!this.shouldRender()) {
return;
}
if (document.querySelector(this.gateway.hosted_fields.wrapper + '>div')) {
document.querySelector(this.gateway.hosted_fields.wrapper + '>div').setAttribute('style', '');
}
const actionHandler = new CheckoutActionHandler(
PayPalCommerceGateway,
new ErrorHandler(this.gateway.labels.error.generic),
this.spinner
);
this.renderer.render(
this.gateway.button.wrapper,
this.gateway.hosted_fields.wrapper,
actionHandler.configuration(),
);
}
switchBetweenPayPalandOrderButton() {
updateUi() {
const urlParams = new URLSearchParams(window.location.search)
if (urlParams.has('change_payment_method')) {
return
}
const currentPaymentMethod = jQuery(
'input[name="payment_method"]:checked').val();
if (currentPaymentMethod !== 'ppcp-gateway' && currentPaymentMethod !== 'ppcp-credit-card-gateway') {
this.renderer.hideButtons(this.gateway.button.wrapper);
this.renderer.hideButtons(this.gateway.messages.wrapper);
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
jQuery('#place_order').show();
}
else {
jQuery('#place_order').hide();
if (currentPaymentMethod === 'ppcp-gateway') {
this.renderer.showButtons(this.gateway.button.wrapper);
this.renderer.showButtons(this.gateway.messages.wrapper);
this.messages.render();
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
}
if (currentPaymentMethod === 'ppcp-credit-card-gateway') {
this.renderer.hideButtons(this.gateway.button.wrapper);
this.renderer.hideButtons(this.gateway.messages.wrapper);
this.renderer.showButtons(this.gateway.hosted_fields.wrapper);
}
}
super.updateUi();
}
}

View file

@ -0,0 +1,44 @@
const getElement = (selectorOrElement) => {
if (typeof selectorOrElement === 'string') {
return document.querySelector(selectorOrElement);
}
return selectorOrElement;
}
export const isVisible = (element) => {
return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
}
export const setVisible = (selectorOrElement, show, important = false) => {
const element = getElement(selectorOrElement);
if (!element) {
return;
}
const currentValue = element.style.getPropertyValue('display');
if (!show) {
if (currentValue === 'none') {
return;
}
element.style.setProperty('display', 'none', important ? 'important' : '');
} else {
if (currentValue === 'none') {
element.style.removeProperty('display');
}
// still not visible (if something else added display: none in CSS)
if (!isVisible(element)) {
element.style.setProperty('display', 'block');
}
}
};
export const hide = (selectorOrElement, important = false) => {
setVisible(selectorOrElement, false, important);
};
export const show = (selectorOrElement) => {
setVisible(selectorOrElement, true);
};

View file

@ -564,7 +564,7 @@ class SmartButton implements SmartButtonInterface {
printf(
'<div id="%1$s" style="display:none;">
<button class="button alt">%2$s</button>
<button class="button alt ppcp-dcc-order-button">%2$s</button>
</div><div id="payments-sdk__contingency-lightbox"></div><style id="ppcp-hide-dcc">.payment_method_ppcp-credit-card-gateway {display:none;}</style>',
esc_attr( $id ),
esc_html( $label )