mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 18:16:38 +08:00
Add ability in WidgetBuilder to have multiple buttons rendered per wrapper.
This commit is contained in:
parent
cc79f62cab
commit
0fed872c13
4 changed files with 104 additions and 15 deletions
|
@ -40,8 +40,7 @@ class SingleProductActionHandler {
|
||||||
}).then((res)=>{
|
}).then((res)=>{
|
||||||
return res.json();
|
return res.json();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
const id = document.querySelector('[name="add-to-cart"]').value;
|
const products = this.getSubscriptionProducts();
|
||||||
const products = [new Product(id, 1, null)];
|
|
||||||
|
|
||||||
fetch(this.config.ajax.change_cart.endpoint, {
|
fetch(this.config.ajax.change_cart.endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -71,6 +70,12 @@ class SingleProductActionHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSubscriptionProducts()
|
||||||
|
{
|
||||||
|
const id = document.querySelector('[name="add-to-cart"]').value;
|
||||||
|
return [new Product(id, 1, null)];
|
||||||
|
}
|
||||||
|
|
||||||
configuration()
|
configuration()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -163,6 +163,13 @@ class SingleProductBootstap {
|
||||||
this.errorHandler,
|
this.errorHandler,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const hasSubscriptions = PayPalCommerceGateway.data_client_id.has_subscriptions
|
||||||
|
&& PayPalCommerceGateway.data_client_id.paypal_subscriptions_enabled;
|
||||||
|
|
||||||
|
const products = hasSubscriptions
|
||||||
|
? actionHandler.getSubscriptionProducts()
|
||||||
|
: actionHandler.getProducts();
|
||||||
|
|
||||||
(new SimulateCart(
|
(new SimulateCart(
|
||||||
this.gateway.ajax.simulate_cart.endpoint,
|
this.gateway.ajax.simulate_cart.endpoint,
|
||||||
this.gateway.ajax.simulate_cart.nonce,
|
this.gateway.ajax.simulate_cart.nonce,
|
||||||
|
@ -198,7 +205,7 @@ class SingleProductBootstap {
|
||||||
|
|
||||||
this.handleButtonStatus(false);
|
this.handleButtonStatus(false);
|
||||||
|
|
||||||
}, actionHandler.getProducts());
|
}, products);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ class Renderer {
|
||||||
renderButtons(wrapper, style, contextConfig, hasEnabledSeparateGateways, fundingSource = null) {
|
renderButtons(wrapper, style, contextConfig, hasEnabledSeparateGateways, fundingSource = null) {
|
||||||
if (! document.querySelector(wrapper) || this.isAlreadyRendered(wrapper, fundingSource, hasEnabledSeparateGateways) ) {
|
if (! document.querySelector(wrapper) || this.isAlreadyRendered(wrapper, fundingSource, hasEnabledSeparateGateways) ) {
|
||||||
// Try to render registered buttons again in case they were removed from the DOM by an external source.
|
// Try to render registered buttons again in case they were removed from the DOM by an external source.
|
||||||
widgetBuilder.renderButtons(wrapper);
|
widgetBuilder.renderButtons([wrapper, fundingSource]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,14 +99,20 @@ class Renderer {
|
||||||
|
|
||||||
jQuery(document)
|
jQuery(document)
|
||||||
.off(this.reloadEventName, wrapper)
|
.off(this.reloadEventName, wrapper)
|
||||||
.on(this.reloadEventName, wrapper, (event, settingsOverride = {}) => {
|
.on(this.reloadEventName, wrapper, (event, settingsOverride = {}, triggeredFundingSource) => {
|
||||||
|
|
||||||
|
// Only accept events from the matching funding source
|
||||||
|
if (fundingSource && triggeredFundingSource && (triggeredFundingSource !== fundingSource)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const settings = merge(this.defaultSettings, settingsOverride);
|
const settings = merge(this.defaultSettings, settingsOverride);
|
||||||
let scriptOptions = keysToCamelCase(settings.url_params);
|
let scriptOptions = keysToCamelCase(settings.url_params);
|
||||||
scriptOptions = merge(scriptOptions, settings.script_attributes);
|
scriptOptions = merge(scriptOptions, settings.script_attributes);
|
||||||
|
|
||||||
loadScript(scriptOptions).then((paypal) => {
|
loadScript(scriptOptions).then((paypal) => {
|
||||||
widgetBuilder.setPaypal(paypal);
|
widgetBuilder.setPaypal(paypal);
|
||||||
widgetBuilder.registerButtons(wrapper, buttonsOptions());
|
widgetBuilder.registerButtons([wrapper, fundingSource], buttonsOptions());
|
||||||
widgetBuilder.renderAll();
|
widgetBuilder.renderAll();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -114,8 +120,8 @@ class Renderer {
|
||||||
this.renderedSources.add(wrapper + (fundingSource ?? ''));
|
this.renderedSources.add(wrapper + (fundingSource ?? ''));
|
||||||
|
|
||||||
if (typeof paypal !== 'undefined' && typeof paypal.Buttons !== 'undefined') {
|
if (typeof paypal !== 'undefined' && typeof paypal.Buttons !== 'undefined') {
|
||||||
widgetBuilder.registerButtons(wrapper, buttonsOptions());
|
widgetBuilder.registerButtons([wrapper, fundingSource], buttonsOptions());
|
||||||
widgetBuilder.renderButtons(wrapper);
|
widgetBuilder.renderButtons([wrapper, fundingSource]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
|
/**
|
||||||
|
* Handles the registration and rendering of PayPal widgets: Buttons and Messages.
|
||||||
|
* To have several Buttons per wrapper, an array should be provided, ex: [wrapper, fundingSource].
|
||||||
|
*/
|
||||||
class WidgetBuilder {
|
class WidgetBuilder {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -19,14 +22,18 @@ class WidgetBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
registerButtons(wrapper, options) {
|
registerButtons(wrapper, options) {
|
||||||
this.buttons.set(wrapper, {
|
wrapper = this.sanitizeWrapper(wrapper);
|
||||||
|
|
||||||
|
this.buttons.set(this.toKey(wrapper), {
|
||||||
wrapper: wrapper,
|
wrapper: wrapper,
|
||||||
options: options
|
options: options,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderButtons(wrapper) {
|
renderButtons(wrapper) {
|
||||||
if (!this.buttons.has(wrapper)) {
|
wrapper = this.sanitizeWrapper(wrapper);
|
||||||
|
|
||||||
|
if (!this.buttons.has(this.toKey(wrapper))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,14 +41,21 @@ class WidgetBuilder {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const entry = this.buttons.get(wrapper);
|
const entry = this.buttons.get(this.toKey(wrapper));
|
||||||
const btn = this.paypal.Buttons(entry.options);
|
const btn = this.paypal.Buttons(entry.options);
|
||||||
|
|
||||||
if (!btn.isEligible()) {
|
if (!btn.isEligible()) {
|
||||||
|
this.buttons.delete(this.toKey(wrapper));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
btn.render(entry.wrapper);
|
let target = this.buildWrapperTarget(wrapper);
|
||||||
|
|
||||||
|
if (!target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.render(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderAllButtons() {
|
renderAllButtons() {
|
||||||
|
@ -84,7 +98,64 @@ class WidgetBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
hasRendered(wrapper) {
|
hasRendered(wrapper) {
|
||||||
return document.querySelector(wrapper).hasChildNodes();
|
let selector = wrapper;
|
||||||
|
|
||||||
|
if (Array.isArray(wrapper)) {
|
||||||
|
selector = wrapper[0];
|
||||||
|
for (const item of wrapper.slice(1)) {
|
||||||
|
selector += ' .item-' + item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const element = document.querySelector(selector);
|
||||||
|
return element && element.hasChildNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
sanitizeWrapper(wrapper) {
|
||||||
|
if (Array.isArray(wrapper)) {
|
||||||
|
wrapper = wrapper.filter(item => !!item);
|
||||||
|
if (wrapper.length === 1) {
|
||||||
|
wrapper = wrapper[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildWrapperTarget(wrapper) {
|
||||||
|
let target = wrapper;
|
||||||
|
|
||||||
|
if (Array.isArray(wrapper)) {
|
||||||
|
const $wrapper = jQuery(wrapper[0]);
|
||||||
|
|
||||||
|
if (!$wrapper.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemClass = 'item-' + wrapper[1];
|
||||||
|
|
||||||
|
// Check if the parent element exists and it doesn't already have the div with the class
|
||||||
|
let $item = $wrapper.find('.' + itemClass);
|
||||||
|
|
||||||
|
if (!$item.length) {
|
||||||
|
$item = jQuery(`<div class="${itemClass}"></div>`);
|
||||||
|
$wrapper.append($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
target = $item.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jQuery(target).length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
toKey(wrapper) {
|
||||||
|
if (Array.isArray(wrapper)) {
|
||||||
|
return JSON.stringify(wrapper);
|
||||||
|
}
|
||||||
|
return wrapper;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue