import { loadScript } from '@paypal/paypal-js'; import { debounce } from './helper/debounce'; import { buttonRefreshTriggerFactory, buttonSettingsGetterFactory, } from './helper/preview-button'; import Renderer from '../../../ppcp-button/resources/js/modules/Renderer/Renderer'; import MessageRenderer from '../../../ppcp-button/resources/js/modules/Renderer/MessageRenderer'; import { setVisibleByClass, isVisible, } from '../../../ppcp-button/resources/js/modules/Helper/Hiding'; import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder'; document.addEventListener( 'DOMContentLoaded', () => { function disableAll( nodeList ) { nodeList.forEach( ( node ) => node.setAttribute( 'disabled', 'true' ) ); } const disabledCheckboxes = document.querySelectorAll( '.ppcp-disabled-checkbox' ); disableAll( disabledCheckboxes ); const form = jQuery( '#mainform' ); const payLaterButtonInput = document.querySelector( '#ppcp-pay_later_button_enabled' ); initializePayLaterPreview(); const separateCardButtonCheckbox = document.querySelector( '#ppcp-allow_card_button_gateway' ); if ( separateCardButtonCheckbox ) { separateCardButtonCheckbox.addEventListener( 'change', () => { setVisibleByClass( '#field-button_layout', ! separateCardButtonCheckbox.checked, 'hide' ); setVisibleByClass( '#field-button_general_layout', ! separateCardButtonCheckbox.checked, 'hide' ); } ); } [ { layoutSelector: '#ppcp-button_layout', taglineSelector: '#field-button_tagline', canHaveSeparateButtons: true, }, { layoutSelector: '#ppcp-button_general_layout', taglineSelector: '#field-button_general_tagline', canHaveSeparateButtons: true, }, { layoutSelector: '#ppcp-button_product_layout', taglineSelector: '#field-button_product_tagline', }, { layoutSelector: '#ppcp-button_cart_layout', taglineSelector: '#field-button_cart_tagline', }, { layoutSelector: '#ppcp-button_mini-cart_layout', taglineSelector: '#field-button_mini-cart_tagline', }, ].forEach( ( location ) => { const layoutSelect = document.querySelector( location.layoutSelector ); const taglineField = document.querySelector( location.taglineSelector ); if ( layoutSelect && taglineField ) { const setTaglineFieldVisibility = () => { const supportsTagline = jQuery( layoutSelect ).val() === 'horizontal' && ( ! location.canHaveSeparateButtons || ( separateCardButtonCheckbox && ! separateCardButtonCheckbox.checked ) ) && isVisible( layoutSelect.parentElement ); setVisibleByClass( taglineField, supportsTagline, 'hide' ); }; setTaglineFieldVisibility(); // looks like only jQuery event fires for WC selects jQuery( layoutSelect ).change( setTaglineFieldVisibility ); if ( location.canHaveSeparateButtons && separateCardButtonCheckbox ) { separateCardButtonCheckbox.addEventListener( 'change', setTaglineFieldVisibility ); } } } ); function initializePayLaterPreview() { if ( ! payLaterButtonInput ) { return; } const payLaterButtonPreview = document.querySelector( '.ppcp-button-preview[data-ppcp-preview-block="paylater"]' ); if ( ! payLaterButtonPreview ) { return; } if ( ! payLaterButtonInput.checked ) { payLaterButtonPreview.classList.add( 'disabled' ); } if ( payLaterButtonInput.classList.contains( 'ppcp-disabled-checkbox' ) ) { payLaterButtonPreview.style.display = 'none'; } payLaterButtonInput.addEventListener( 'click', () => { payLaterButtonPreview.classList.remove( 'disabled' ); if ( ! payLaterButtonInput.checked ) { payLaterButtonPreview.classList.add( 'disabled' ); } } ); } function createButtonPreview( settingsCallback ) { const render = ( settings ) => { const wrapperSelector = Object.values( settings.separate_buttons ).length > 0 ? Object.values( settings.separate_buttons )[ 0 ].wrapper : settings.button.wrapper; const wrapper = document.querySelector( wrapperSelector ); if ( ! wrapper ) { return; } wrapper.innerHTML = ''; const renderer = new Renderer( null, settings, ( data, actions ) => actions.reject(), null ); try { renderer.render( {} ); jQuery( document ).trigger( 'ppcp_paypal_render_preview', settings ); } catch ( err ) { console.error( err ); } }; renderPreview( settingsCallback, render ); } function currentTabId() { const params = new URLSearchParams( location.search ); return params.has( 'ppcp-tab' ) ? params.get( 'ppcp-tab' ) : params.get( 'section' ); } function shouldShowPayLaterButton() { const payLaterButtonLocations = document.querySelector( '[name="ppcp[pay_later_button_locations][]"]' ); if ( ! payLaterButtonInput || ! payLaterButtonLocations ) { return PayPalCommerceGatewaySettings.is_pay_later_button_enabled; } return ( payLaterButtonInput.checked && payLaterButtonLocations.selectedOptions.length > 0 ); } function shouldDisableCardButton() { return ( PayPalCommerceGatewaySettings.is_acdc_enabled || jQuery( '#ppcp-allow_card_button_gateway' ).is( ':checked' ) ); } function getPaypalScriptSettings() { const disableFundingInput = jQuery( '[name="ppcp[disable_funding][]"]' ); let disabledSources = disableFundingInput.length > 0 ? disableFundingInput.val() : PayPalCommerceGatewaySettings.disabled_sources; const payLaterButtonPreview = jQuery( '#ppcpPayLaterButtonPreview' ); const settings = { 'client-id': PayPalCommerceGatewaySettings.client_id, currency: PayPalCommerceGatewaySettings.currency, 'integration-date': PayPalCommerceGatewaySettings.integration_date, components: PayPalCommerceGatewaySettings.components, 'enable-funding': [ 'venmo', 'paylater' ], }; if ( PayPalCommerceGatewaySettings.environment === 'sandbox' ) { settings[ 'buyer-country' ] = PayPalCommerceGatewaySettings.country; } if ( payLaterButtonPreview?.length ) { disabledSources = Object.keys( PayPalCommerceGatewaySettings.all_funding_sources ); } if ( ! shouldShowPayLaterButton() ) { disabledSources = disabledSources.concat( 'credit' ); } if ( shouldDisableCardButton() ) { const standardCardButtonInput = document.querySelector( '#woocommerce_ppcp-card-button-gateway_enabled' ); if ( standardCardButtonInput ) { standardCardButtonInput.disabled = true; } disabledSources = disabledSources.concat( 'card' ); } if ( disabledSources?.length ) { settings[ 'disable-funding' ] = disabledSources; } const smartButtonLocale = document.getElementById( 'ppcp-smart_button_language' ); if ( smartButtonLocale?.length > 0 && smartButtonLocale?.value !== '' ) { settings.locale = smartButtonLocale.value; } return settings; } function loadPaypalScript( settings, onLoaded = () => {} ) { loadScript( JSON.parse( JSON.stringify( settings ) ) ) // clone the object to prevent modification .then( ( paypal ) => { widgetBuilder.setPaypal( paypal ); document.dispatchEvent( new CustomEvent( 'ppcp_paypal_script_loaded' ) ); onLoaded( paypal ); } ) .catch( ( error ) => console.error( 'failed to load the PayPal JS SDK script', error ) ); } function getButtonSettings( wrapperSelector, fields, apm = null ) { const layoutElement = jQuery( fields.layout ); const layout = layoutElement.length && layoutElement.is( ':visible' ) ? layoutElement.val() : 'vertical'; const style = { color: jQuery( fields.color ).val(), shape: jQuery( fields.shape ).val(), label: jQuery( fields.label ).val(), tagline: layout === 'horizontal' && jQuery( fields.tagline ).is( ':checked' ), layout, }; if ( 'height' in fields ) { style.height = parseInt( jQuery( fields.height ).val() ); } if ( 'poweredby_tagline' in fields ) { style.layout = jQuery( fields.poweredby_tagline ).is( ':checked' ) ? 'vertical' : 'horizontal'; } const settings = { button: { wrapper: wrapperSelector, style, }, separate_buttons: {}, }; if ( apm ) { settings.separate_buttons[ apm ] = { wrapper: wrapperSelector, style, }; settings.button.wrapper = null; } return settings; } function createMessagesPreview( settingsCallback ) { const render = ( settings ) => { let wrapper = document.querySelector( settings.wrapper ); if ( ! wrapper ) { return; } // looks like .innerHTML = '' is not enough, PayPal somehow renders with old style const parent = wrapper.parentElement; parent.removeChild( wrapper ); wrapper = document.createElement( 'div' ); wrapper.setAttribute( 'id', settings.wrapper.replace( '#', '' ) ); parent.appendChild( wrapper ); const messageRenderer = new MessageRenderer( settings ); try { messageRenderer.renderWithAmount( settings.amount ); } catch ( err ) { console.error( err ); } }; renderPreview( settingsCallback, render ); } function getMessageSettings( wrapperSelector, fields ) { const layout = jQuery( fields.layout ).val(); const style = { layout, logo: { type: jQuery( fields.logo_type ).val(), position: jQuery( fields.logo_position ).val(), }, text: { color: jQuery( fields.text_color ).val(), }, color: jQuery( fields.flex_color ).val(), ratio: jQuery( fields.flex_ratio ).val(), }; return { wrapper: wrapperSelector, style, amount: 30, placement: 'product', }; } function renderPreview( settingsCallback, render ) { let oldSettings = settingsCallback(); form.on( 'change', ':input', debounce( () => { const newSettings = settingsCallback(); if ( JSON.stringify( oldSettings ) === JSON.stringify( newSettings ) ) { return; } render( newSettings ); oldSettings = newSettings; }, 300 ) ); jQuery( document ).on( 'ppcp_paypal_script_loaded', () => { oldSettings = settingsCallback(); render( oldSettings ); } ); render( oldSettings ); } function getButtonDefaultSettings( wrapperSelector ) { const style = { color: 'gold', shape: 'pill', label: 'paypal', tagline: false, layout: 'vertical', }; return { button: { wrapper: wrapperSelector, style, }, separate_buttons: {}, }; } const previewElements = document.querySelectorAll( '.ppcp-preview' ); if ( previewElements.length ) { let oldScriptSettings = getPaypalScriptSettings(); form.on( 'change', ':input', debounce( () => { const newSettings = getPaypalScriptSettings(); if ( JSON.stringify( oldScriptSettings ) === JSON.stringify( newSettings ) ) { return; } loadPaypalScript( newSettings ); oldScriptSettings = newSettings; }, 1000 ) ); loadPaypalScript( oldScriptSettings, () => { const payLaterMessagingLocations = [ 'product', 'cart', 'checkout', 'shop', 'home', 'general', ]; const paypalButtonLocations = [ 'product', 'cart', 'checkout', 'mini-cart', 'cart-block', 'checkout-block-express', 'general', ]; // Default preview buttons; on "Standard Payments" tab. paypalButtonLocations.forEach( ( location ) => { const inputNamePrefix = location === 'checkout' ? '#ppcp-button' : '#ppcp-button_' + location; const wrapperName = location .split( '-' ) .map( ( s ) => s.charAt( 0 ).toUpperCase() + s.slice( 1 ) ) .join( '' ); const fields = { color: inputNamePrefix + '_color', shape: inputNamePrefix + '_shape', label: inputNamePrefix + '_label', tagline: inputNamePrefix + '_tagline', layout: inputNamePrefix + '_layout', }; if ( document.querySelector( inputNamePrefix + '_height' ) ) { fields.height = inputNamePrefix + '_height'; } createButtonPreview( () => getButtonSettings( '#ppcp' + wrapperName + 'ButtonPreview', fields ) ); } ); /** * Inspect DOM to find APM button previews; on tabs like "Advanced Card Payments". * * How it works: * * 1. Add a