PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.4.1
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.4.1
2.4.1 2.4.0 2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 All 68 releases
better-payment / assets / js / better-payment.js

better-payment.js in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.4.1, at assets/js/better-payment.js

33 lines 28.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*
2 * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
3 * This devtool is neither made for production nor for readable output files.
4 * It uses "eval()" calls to create a separate source file in the browser devtools.
5 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
6 * or disable the default devtool with "devtool: false".
7 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
8 */
9 /******/ (() => { // webpackBootstrap
10 /******/ "use strict";
11 /******/ var __webpack_modules__ = ({
12
13 /***/ "./src/js/better-payment.js"
14 /*!**********************************************!*\
15 !*** ./src/js/better-payment.js + 1 modules ***!
16 \**********************************************/
17 () {
18
19 eval("{\n;// ./src/js/_checkout-lock.js\n/**\n * Keeps a payment button locked from the moment a checkout is requested until the\n * browser has left the page.\n *\n * Every click on a Stripe or Paystack button asks the server for a new checkout,\n * and the server records an `unpaid` order for each one. The button used to be\n * re-enabled (and its \"Redirecting\" label overwritten) in the same tick that\n * started the redirect, while `stripe.redirectToCheckout()` was still loading\n * Stripe. A visitor who clicked again in that second got a second checkout and a\n * second order: they paid one, and the other stayed `Incomplete` in the admin\n * list forever beside the completed one.\n *\n * So the button is released only when the visitor is still here and needs it:\n * the request failed, the server refused, the redirect reported an error, or the\n * page came back from the back/forward cache after the redirect had happened.\n *\n * Plain DOM (no jQuery) so it can be unit-tested.\n */\n\n/** Marks a button that has a checkout in flight. */\nconst LOCK_ATTRIBUTE = 'data-bp-checkout-lock';\n\n/** The label each locked button had before it was locked. */\nconst originalLabels = new WeakMap();\n\n/**\n * Whether a checkout is already in flight for this button.\n *\n * @param {HTMLElement|null|undefined} button The payment button.\n * @return {boolean} True while locked.\n */\nfunction isCheckoutLocked(button) {\n return !!button?.hasAttribute?.(LOCK_ATTRIBUTE);\n}\n\n/**\n * Lock a button before its checkout request is sent.\n *\n * @param {HTMLElement|null|undefined} button The payment button.\n * @return {boolean} False when there is no button or it is already locked —\n * the caller must then send nothing.\n */\nfunction lockCheckoutButton(button) {\n if (!button || isCheckoutLocked(button)) {\n return false;\n }\n originalLabels.set(button, button.innerHTML);\n button.setAttribute(LOCK_ATTRIBUTE, '');\n button.disabled = true;\n return true;\n}\n\n/**\n * Show the \"Redirecting\" label on a locked button. The button stays locked.\n *\n * @param {HTMLElement|null|undefined} button The payment button.\n * @param {string} html Label markup.\n */\nfunction showRedirecting(button, html) {\n if (isCheckoutLocked(button)) {\n button.innerHTML = html;\n }\n}\n\n/**\n * Unlock a button and give it back the label it had before it was locked.\n *\n * @param {HTMLElement|null|undefined} button The payment button.\n */\nfunction releaseCheckoutButton(button) {\n if (!isCheckoutLocked(button)) {\n return;\n }\n if (originalLabels.has(button)) {\n button.innerHTML = originalLabels.get(button);\n originalLabels.delete(button);\n }\n button.removeAttribute(LOCK_ATTRIBUTE);\n button.disabled = false;\n}\n\n/**\n * Unlock every locked button under `root`.\n *\n * @param {ParentNode} root Where to look.\n */\nfunction releaseAllCheckoutButtons(root) {\n root?.querySelectorAll?.(`[${LOCK_ATTRIBUTE}]`).forEach(releaseCheckoutButton);\n}\n\n/**\n * `pageshow` handler: a page restored from the back/forward cache comes back\n * exactly as it was left — mid-redirect, buttons locked. Unlock them so a\n * visitor who pressed Back from the gateway can pay. A normal load needs\n * nothing: its buttons were never locked.\n *\n * @param {PageTransitionEvent} event The pageshow event.\n * @param {ParentNode} root Where to look.\n */\nfunction releaseOnPageRestore(event, root) {\n if (event?.persisted) {\n releaseAllCheckoutButtons(root);\n }\n}\n\n/**\n * Start a Stripe Checkout redirect, always settling with `{ error }` or `{}`.\n *\n * Stripe.js missing, blocked or throwing is reported as an error, the same as\n * an error `redirectToCheckout()` returns, so the caller has one place to\n * release the button. On success the page navigates away and the promise is\n * usually never observed.\n *\n * @param {Function} StripeFactory The global `Stripe` (may be undefined).\n * @param {string} publicKey Publishable key.\n * @param {string} sessionId Checkout Session id.\n * @return {Promise<{error?: {message?: string}}>} Settles with the outcome.\n */\nfunction redirectToStripeCheckout(StripeFactory, publicKey, sessionId) {\n try {\n return Promise.resolve(StripeFactory(publicKey).redirectToCheckout({\n sessionId\n })).then(result => result !== null && result !== void 0 ? result : {}, error => ({\n error: {\n message: error?.message\n }\n }));\n } catch (error) {\n return Promise.resolve({\n error: {\n message: error?.message\n }\n });\n }\n}\n;// ./src/js/better-payment.js\n\n(function ($) {\n 'use strict';\n\n const formsFieldTypeBPName = 'payment_amount';\n const {\n custom_texts\n } = betterPayment || {};\n const redirectingText = custom_texts?.redirecting || 'Redirecting';\n const redirectingHtml = `${redirectingText} <span class=\"elementor-control-spinner\">&nbsp;<i class=\"eicon-spinner eicon-animation-spin\"></i>&nbsp;</span>`;\n\n // Back from the gateway restores this page from the back/forward cache with\n // its payment button still locked mid-redirect; unlock it so the visitor can pay.\n window.addEventListener('pageshow', function (event) {\n releaseOnPageRestore(event, document);\n });\n // let fieldText = (custom_texts?.field || 'field').toLowerCase();\n // let requiredText = (custom_texts?.required || 'required').toLowerCase();\n let fieldIsRequiredText = custom_texts?.field_is_required || 'field is required';\n let businessEmailIsRequiredText = custom_texts?.business_email_is_required || 'Business Email is required';\n let paymentAmountFieldIsRequiredText = custom_texts?.payment_amount_field_is_required || 'Payment Amount field is required';\n let minimumAmountIsOneText = custom_texts?.minimum_amount_is_one || 'Minimum amount is 1';\n let somethingWentWrongText = custom_texts?.something_went_wrong || 'Something went wrong';\n $(document).on('click', '.better-payment-paypal-bt', function (e) {\n const id = $('#' + this.form.id),\n $form = $(id),\n paymentInfo = $(this).data('paypal-info'),\n fields = $form.serializeObject();\n let data = validateBetterPaymentForm(paymentInfo, fields, this.form);\n\n // $(this).html('Submitting <span class=\"elementor-control-spinner\">&nbsp;<i class=\"eicon-spinner eicon-animation-spin\"></i>&nbsp;</span>');\n $(this).attr('disabled', true);\n if (typeof data.status !== 'undefined' && !data.status) {\n e.preventDefault();\n toastr.error(data.errors.length ? data.errors[0] : `${somethingWentWrongText}!`);\n this.disabled = false;\n return false;\n }\n\n // $(this).html('Proceed to Payment');\n $(this).attr('disabled', false);\n $(this).html(`${redirectingText} <span class=\"elementor-control-spinner\">&nbsp;<i class=\"eicon-spinner eicon-animation-spin\"></i>&nbsp;</span>`);\n });\n $(document).on('click', '.better-payment-stripe-bt', function (e) {\n e.preventDefault();\n\n // A checkout is already in flight for this button.\n if (isCheckoutLocked(this)) {\n return false;\n }\n const id = $('#' + this.form.id),\n $form = $(id),\n setting_data = $form.data('better-payment'),\n fields = $form.serializeObject();\n let data = validateBetterPaymentForm('', fields, this.form, false);\n if (typeof data.status !== 'undefined' && !data.status) {\n e.preventDefault();\n toastr.error(data.errors.length ? data.errors[0] : `${somethingWentWrongText}!`);\n this.disabled = false;\n return false;\n }\n\n // One checkout per click: a second request would record a second order.\n if (!lockCheckoutButton(this)) {\n return false;\n }\n const button = this;\n $.ajax({\n url: betterPayment.ajax_url,\n type: 'post',\n data: {\n action: 'better_payment_stripe_get_token',\n security: betterPayment.nonce,\n fields: fields,\n setting_data: setting_data\n },\n success: function (response) {\n if (typeof response?.data?.stripe_data === 'undefined') {\n toastr.error(response?.data || `${somethingWentWrongText}!`);\n releaseCheckoutButton(button);\n return;\n }\n\n // Stays locked: the page is about to leave for Stripe.\n showRedirecting(button, redirectingHtml);\n redirectToStripeCheckout(window.Stripe, response.data.stripe_public_key, response.data.stripe_data).then(function (result) {\n if (result?.error) {\n toastr.error(result.error.message || `${somethingWentWrongText}!`);\n releaseCheckoutButton(button);\n }\n });\n },\n error: function () {\n console.log('Something went wrong!');\n releaseCheckoutButton(button);\n }\n });\n });\n $(document).on('click', '.better-payment-paystack-bt', function (e) {\n e.preventDefault();\n\n // A checkout is already in flight for this button.\n if (isCheckoutLocked(this)) {\n return false;\n }\n const id = $('#' + this.form.id),\n $form = $(id),\n setting_data = $form.data('better-payment'),\n fields = $form.serializeObject();\n let data = validateBetterPaymentForm('', fields, this.form, false);\n if (typeof data.status !== 'undefined' && !data.status) {\n e.preventDefault();\n toastr.error(data.errors.length ? data.errors[0] : `${somethingWentWrongText}!`);\n this.disabled = false;\n return false;\n }\n\n // One checkout per click: a second request would record a second order.\n if (!lockCheckoutButton(this)) {\n return false;\n }\n const button = this;\n $.ajax({\n url: betterPayment.ajax_url,\n type: 'post',\n data: {\n action: 'better_payment_paystack_get_token',\n security: betterPayment.nonce,\n fields: fields,\n setting_data: setting_data\n },\n success: function (response) {\n if (typeof response?.data?.authorization_url === 'undefined') {\n toastr.error(response?.data || `${somethingWentWrongText}!`);\n releaseCheckoutButton(button);\n return;\n }\n\n // Stays locked: the page is about to leave for Paystack.\n showRedirecting(button, redirectingHtml);\n window.location.href = response.data.authorization_url;\n },\n error: function () {\n console.log('Something went wrong!');\n releaseCheckoutButton(button);\n }\n });\n });\n function validateBetterPaymentForm(paymentInfo, fields, thisForm, isPaypal = true) {\n let fieldsToExclude = getExcludedFields(),\n data = {};\n data.status = true;\n data.errors = [];\n let validatedData = validateForm(thisForm, fields, fieldsToExclude);\n data.status = typeof validatedData.status !== 'undefined' ? validatedData.status : data.status;\n data.errors = typeof validatedData.errors !== 'undefined' && validatedData.errors.constructor === Array ? data.errors.concat(validatedData.errors) : data.errors;\n if (isPaypal && !paymentInfo.business_email) {\n data.errors.push(`${businessEmailIsRequiredText}!`);\n data.status = false;\n }\n if (typeof fields.primary_payment_amount === 'undefined' || fields.primary_payment_amount === '') {\n if (typeof fields.primary_payment_amount_radio === 'undefined' || fields.primary_payment_amount_radio === '') {\n data.errors.push(`${paymentAmountFieldIsRequiredText}!`);\n data.status = false;\n }\n }\n if (typeof fields.primary_payment_amount !== 'undefined' && parseFloat(fields.primary_payment_amount) < 1) {\n data.errors.push(`${minimumAmountIsOneText}!`);\n data.status = false;\n }\n return data;\n }\n $(document).on('change', '.bp-custom-payment-amount', function (e) {\n let formWrapID = $(this).closest('.elementor-form').data('id');\n let formIDSelector = this.form && this.form.id ? this.form.id : '';\n formIDSelector = formIDSelector == '' && formWrapID != '' ? '.elementor-element-' + formWrapID : '#' + formIDSelector;\n const radioInput = document.querySelectorAll(formIDSelector + ' .bp-payment-amount-wrap input[type=\"radio\"]');\n radioInput.forEach(radio => {\n radio.checked = false;\n });\n let amountValue = parseFloat(this.value);\n $('.bp-transaction-details-amount-text').text(amountValue);\n\n // Hook: a layout can adjust the total it shows (Pro's layouts 4 and 5 multiply it by their quantity field).\n $(document).trigger('better_payment_amount_changed', [amountValue, 'input']);\n });\n $(document).on('click', '.bp-form_pay-radio', function (e) {\n const $this = $(this);\n let amount = parseFloat($this.val());\n if (amount == '') {\n return false;\n }\n $this.closest('form').find('.bp-custom-payment-amount').val(amount);\n $('.bp-transaction-details-amount-text').text(amount);\n\n // Hook: a layout can adjust the total it shows (Pro's layouts 4 and 5 multiply it by their quantity field).\n $(document).trigger('better_payment_amount_changed', [amount, 'radio']);\n });\n $(window).on('elementor/frontend/init', () => {\n const Better_Payment_Stripe = elementorModules.frontend.handlers.Base.extend({\n getDefaultSettings: function getDefaultSettings() {\n return {\n selectors: {\n form: '.elementor-form'\n }\n };\n },\n getDefaultElements: function getDefaultElements() {\n let selectors = this.getSettings('selectors'),\n elements = {};\n elements.$form = this.$element.find(selectors.form);\n return elements;\n },\n bindEvents: function bindEvents() {\n this.elements.$form.on('submit_success', this.handleFormAction);\n },\n handleFormAction: function handleFormAction(event, res) {\n if (typeof res.data.better_stripe_data != 'undefined') {\n let stripe = Stripe(res.data.better_stripe_data.stripe_public_key);\n stripe.redirectToCheckout({\n sessionId: res.data.better_stripe_data.stripe_data\n }).then(function (t) {});\n }\n if (typeof res.data.better_paystack_data != 'undefined') {\n if (typeof res.data.better_paystack_data.authorization_url != 'undefined') {\n window.location.href = res.data.better_paystack_data.authorization_url;\n } else {\n toastr.error(response.data);\n }\n }\n }\n });\n const Better_Payment_Handler = $element => {\n elementorFrontend.elementsHandler.addHandler(Better_Payment_Stripe, {\n $element\n });\n };\n elementorFrontend.hooks.addAction('frontend/element_ready/form.default', Better_Payment_Handler);\n if (typeof elementor != 'undefined') {\n elementor.hooks.addAction('panel/open_editor/widget/form', function (panel, model, view) {\n elementor.hooks.addFilter('elementor_pro/forms/content_template/item', function (item, i, settings) {\n if (typeof item.field_type !== 'undefined' && item.field_type === formsFieldTypeBPName) {\n item.field_type = 'html';\n item.field_html = getFormsFieldsMarkup(settings, item);\n }\n return item;\n }, 10, 3);\n });\n }\n });\n $.fn.serializeObject = function () {\n var objInit = {};\n var a = this.serializeArray();\n $.each(a, function () {\n if (objInit[this.name]) {\n if (!objInit[this.name].push) {\n objInit[this.name] = [objInit[this.name]];\n }\n objInit[this.name].push(this.value || '');\n } else {\n objInit[this.name] = this.value || '';\n }\n });\n return objInit;\n };\n\n //Better Payment Functions Starts\n function isFormsFieldsEnable(settings) {\n return typeof settings.better_payment_payment_amount_enable != 'undefined' && 'yes' === settings.better_payment_payment_amount_enable;\n }\n function isFormsInputFieldEnable(settings, item) {\n if (!isFormsFieldsEnable(settings)) {\n return false;\n }\n return typeof item.bp_field_type != 'undefined' && ('input-field' === item.bp_field_type || 'both' === item.bp_field_type);\n }\n function isFormsAmountListEnable(settings, item) {\n if (!isFormsFieldsEnable(settings)) {\n return false;\n }\n let showAmountListEnable = typeof settings.better_payment_show_amount_list_enable != 'undefined' && 'yes' === settings.better_payment_show_amount_list_enable;\n return showAmountListEnable && typeof item.bp_field_type !== 'undefined' && ('amount-list' === item.bp_field_type || 'both' === item.bp_field_type);\n }\n function getFormsCurrency(settings) {\n let currency = 'USD';\n if (settings.submit_actions.includes('paypal')) {\n currency = typeof settings.better_payment_form_paypal_currency !== 'undefined' ? settings.better_payment_form_paypal_currency : currency;\n } else if (settings.submit_actions.includes('stripe')) {\n currency = typeof settings.better_payment_form_stripe_currency !== 'undefined' ? settings.better_payment_form_stripe_currency : currency;\n } else if (settings.submit_actions.includes('paystack')) {\n currency = typeof settings.better_payment_form_paystack_currency !== 'undefined' ? settings.better_payment_form_paystack_currency : currency;\n }\n return currency;\n }\n function getFormsCurrencyAlignment(settings) {\n let currencyAlignment = 'left';\n if (settings.submit_actions.includes('paypal')) {\n currencyAlignment = typeof settings.better_payment_form_currency_alignment_paypal !== 'undefined' ? settings.better_payment_form_currency_alignment_paypal : currencyAlignment;\n } else if (settings.submit_actions.includes('stripe')) {\n currencyAlignment = typeof settings.better_payment_form_currency_alignment_stripe !== 'undefined' ? settings.better_payment_form_currency_alignment_stripe : currencyAlignment;\n } else if (settings.submit_actions.includes('paystack')) {\n currencyAlignment = typeof settings.better_payment_form_currency_alignment_paystack !== 'undefined' ? settings.better_payment_form_currency_alignment_paystack : currencyAlignment;\n }\n currencyAlignment = 'left' === currencyAlignment || 'right' === currencyAlignment ? currencyAlignment : 'left';\n return currencyAlignment;\n }\n function getFormsAmountListMarkup(settings, item) {\n if (typeof settings.better_payment_show_amount_list_items === 'undefined' && settings.better_payment_show_amount_list_items === '') {\n return;\n }\n let currency = getFormsCurrency(settings);\n let currencySymbol = getCurrencySymbols(currency);\n let currencyAlignment = getFormsCurrencyAlignment(settings);\n let currencySymbolLeft = 'left' === currencyAlignment ? currencySymbol : '';\n let currencySymbolRight = 'right' === currencyAlignment ? currencySymbol : '';\n let bpFormsAmountListMarkup = '';\n let bpFormsAmountListItemMarkup = '';\n if (Array.isArray(settings.better_payment_show_amount_list_items)) {\n let amountList = settings.better_payment_show_amount_list_items;\n let uniqueId,\n itemValue = '';\n amountList.forEach(amountListItem => {\n uniqueId = uniqid();\n itemValue = typeof amountListItem.better_payment_amount_val !== 'undefined' ? parseFloat(amountListItem.better_payment_amount_val) : '';\n bpFormsAmountListItemMarkup += `\n <div class=\"bp-form__group pb-3\">\n <input type=\"radio\" value=\"${itemValue}\"\n id=\"bp_payment_amount-${uniqueId}\" class=\"bp-form__control bp-form_pay-radio \"\n name=\"primary_payment_amount_radio\">\n <label for=\"bp_payment_amount-${uniqueId}\">${currencySymbolLeft}${itemValue}${currencySymbolRight}</label>\n </div>\n `;\n });\n bpFormsAmountListMarkup += `\n <div class=\"payment-form-layout\">\n <div class=\"bp-payment-amount-wrap\">\n ${bpFormsAmountListItemMarkup}\n </div>\n </div>\n `;\n }\n return bpFormsAmountListMarkup;\n }\n function getFormsInputFieldMarkup(settings, item) {\n let currency = getFormsCurrency(settings);\n let currencySymbol = getCurrencySymbols(currency);\n let bpPlaceholder = typeof item.bp_placeholder !== 'undefined' ? item.bp_placeholder : '';\n let bpPaymentAmountInput = `<input id=\"form-field-${formsFieldTypeBPName}\" class=\"input is-medium required bp-custom-payment-amount bp-custom-payment-amount-el-integration\" type=\"number\" placeholder=\"${bpPlaceholder}\" name=\"form_fields[${formsFieldTypeBPName}]\" required=\"required\" min=\"${item.bp_field_min}\" max=\"${item.bp_field_max}\" value=\"\">`;\n let paymentAmountInputGroup = ` <div class=\"better-payment-field-advanced-layout field-primary_payment_amount elementor-repeater-item-form-field-payment_amount\">\n <div class=\"control has-icons-left\">\n ${bpPaymentAmountInput}\n <span class=\"icon is-medium is-left\">\n <span class=\"bp-currency-symbol\">${currencySymbol}</span>\n </span>\n </div>\n </div>\n `;\n return paymentAmountInputGroup;\n }\n function getFormsFieldsMarkup(settings, item) {\n let showAmountList = isFormsAmountListEnable(settings, item);\n let showInputField = isFormsInputFieldEnable(settings, item);\n let bpFormsFieldsMarkup = '';\n if (showAmountList || showInputField) {\n let bpPaymentAmountLabel = `<label for=\"form-field-${formsFieldTypeBPName}\" class=\"elementor-field-label\">${item.field_label}</label>`;\n bpFormsFieldsMarkup += bpPaymentAmountLabel;\n bpFormsFieldsMarkup += `<div class =\"better-payment is-full-width\">`;\n }\n if (showAmountList) {\n bpFormsFieldsMarkup += getFormsAmountListMarkup(settings, item);\n }\n if (showInputField) {\n bpFormsFieldsMarkup += getFormsInputFieldMarkup(settings, item);\n }\n if (showAmountList || showInputField) {\n bpFormsFieldsMarkup += `</div>`;\n }\n return bpFormsFieldsMarkup;\n }\n function uniqid(prefix = '', random = false) {\n const sec = Date.now() * 1000 + Math.random() * 1000;\n const id = sec.toString(16).replace(/\\./g, '').padEnd(14, '0');\n return `${prefix}${id}${random ? `.${Math.trunc(Math.random() * 100000000)}` : ''}`;\n }\n function getExcludedFields() {\n return ['better_payment_page_id', 'better_payment_widget_id', 'return', 'action', 'security', 'cancel_return', 'payment_amount', 'primary_payment_amount'];\n }\n function getCurrencySymbols(currency = 'USD') {\n let currencySymbol = '$';\n let currencyList = betterPayment.currency_symbols;\n if (currency in currencyList) {\n currencySymbol = currencyList[currency];\n }\n return currencySymbol;\n }\n //Better Payment Functions Ends\n\n //Helper Functions Starts\n function validateEmail(email) {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n }\n function validateForm(formSelector, fields, fieldsToExclude) {\n let data = {};\n data.status = true;\n data.errors = [];\n for (var key in fields) {\n if (fields.hasOwnProperty(key)) {\n if (fieldsToExclude.indexOf(key) === -1) {\n let validatedData = validateField(formSelector[key], fields[key]);\n if (!validatedData.status) {\n data.errors.push(typeof validatedData.error !== 'undefined' ? validatedData.error : `${key} ${fieldIsRequiredText}!`);\n data.status = false;\n return data;\n }\n }\n }\n }\n return data;\n }\n function validateField(fieldSelector, fieldValue, errorMessage = '') {\n let fieldRequired = isFieldRequired(fieldSelector);\n let data = {};\n data.error = '';\n data.status = true;\n if (fieldSelector.length > 1) {\n // Multiple Fields/Nodes\n return data;\n }\n if (fieldRequired) {\n let itemPlaceholder = fieldSelector.placeholder;\n itemPlaceholder = itemPlaceholder.replace(' *', '');\n if (!itemPlaceholder) {\n itemPlaceholder = fieldSelector.name;\n itemPlaceholder = itemPlaceholder.replace('primary', '').replace('_', ' ').replace(/\\b\\w/g, char => char.toUpperCase()); // primary_first_name => First Name\n }\n let error = errorMessage ? errorMessage : `${itemPlaceholder} ${fieldIsRequiredText}!`;\n if (typeof fieldValue === 'undefined' || fieldValue === '') {\n data.error = error;\n data.status = false;\n }\n }\n return data;\n }\n function isFieldRequired(fieldSelector) {\n let fieldRequired = false;\n if (fieldSelector.length > 1) {\n //Multiple Fields/Nodes\n return true;\n }\n\n //if required attribute has value rather than null or ''\n fieldRequired = !(fieldSelector.getAttribute('required') === null || fieldSelector.getAttribute('required') === '');\n return fieldRequired;\n }\n function toasterOptions() {\n toastr.options = {\n timeOut: '2000',\n toastClass: 'font-size-md',\n maxOpened: 1\n };\n }\n toasterOptions();\n //Helper Functions Ends\n\n // PayPal IPN polling — fires when the return URL lands before IPN is received.\n (function initPaypalPendingPoller() {\n const $pending = $('.bp-paypal-pending');\n if (!$pending.length) return;\n const orderId = $pending.data('order-id');\n const returnUrl = $pending.data('return-url');\n const maxAttempts = 20;\n const intervalMs = 3000;\n let attempts = 0;\n const timeoutText = betterPayment.custom_texts && betterPayment.custom_texts.paypal_payment_timeout ? betterPayment.custom_texts.paypal_payment_timeout : 'Payment verification timed out. Please contact support if your payment was charged.';\n function showTimeout() {\n $pending.addClass('bp-paypal-pending--timeout');\n $pending.find('.bp-paypal-pending__heading').text(betterPayment.custom_texts && betterPayment.custom_texts.paypal_timeout_heading ? betterPayment.custom_texts.paypal_timeout_heading : 'Verification timed out');\n $pending.find('.bp-paypal-pending__sub').text(timeoutText);\n }\n const poller = setInterval(function () {\n attempts++;\n $.post(betterPayment.ajax_url, {\n action: 'better_payment_check_paypal_status',\n security: betterPayment.nonce,\n order_id: orderId\n }, function (response) {\n if (response.success && response.data.status === 'completed') {\n clearInterval(poller);\n // Navigate to the original return URL captured before remove_arg()\n // strips the PayPal params via history.replaceState.\n window.location.href = returnUrl;\n } else if (attempts >= maxAttempts) {\n clearInterval(poller);\n showTimeout();\n }\n }).fail(function () {\n if (attempts >= maxAttempts) {\n clearInterval(poller);\n showTimeout();\n }\n });\n }, intervalMs);\n })();\n})(jQuery);\n\n//# sourceURL=webpack://better-payment/./src/js/better-payment.js_+_1_modules?\n}");
20
21 /***/ }
22
23 /******/ });
24 /************************************************************************/
25 /******/
26 /******/ // startup
27 /******/ // Load entry module and return exports
28 /******/ // This entry module can't be inlined because the eval devtool is used.
29 /******/ var __webpack_exports__ = {};
30 /******/ __webpack_modules__["./src/js/better-payment.js"]();
31 /******/
32 /******/ })()
33 ;