mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 16:24:33 +08:00
♻️ Fix logic in preview button base classes
- Promise-based initialization is executed in correct order - Support to redraw single APM type of button - Fix the button style - Simplify the PreviewButton code
This commit is contained in:
parent
202f308850
commit
180afaad89
2 changed files with 73 additions and 58 deletions
|
@ -50,6 +50,10 @@ class PreviewButton {
|
||||||
this.buttonConfig.button.wrapper = this.selector
|
this.buttonConfig.button.wrapper = this.selector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.ppcpConfig && this.buttonConfig) {
|
||||||
|
this.buttonConfig.button.style = this.ppcpConfig.button.style;
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,38 +72,29 @@ class PreviewButton {
|
||||||
* Will always create a new button in the DOM.
|
* Will always create a new button in the DOM.
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.remove();
|
if (!this.domWrapper) {
|
||||||
|
if (!this.buttonConfig?.button?.wrapper) {
|
||||||
|
console.error('Skip render, button is not configured yet');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.domWrapper = this.createNewWrapper();
|
||||||
|
|
||||||
if (!this.buttonConfig?.button?.wrapper) {
|
this.domWrapper.insertAfter(this.ppcpConfig.button.wrapper)
|
||||||
console.error('Skip render, button is not configured yet');
|
} else {
|
||||||
return;
|
this.domWrapper.empty().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isVisible = true;
|
this.isVisible = true;
|
||||||
|
|
||||||
const newDomWrapper = this.createNewWrapper();
|
this.createButton()
|
||||||
|
|
||||||
if (this.domWrapper?.length) {
|
|
||||||
this.domWrapper.replaceWith(newDomWrapper);
|
|
||||||
} else {
|
|
||||||
jQuery(this.ppcpConfig.button.wrapper).after(newDomWrapper);
|
|
||||||
}
|
|
||||||
this.domWrapper = newDomWrapper;
|
|
||||||
|
|
||||||
this.payButton = this.createButton();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remove() {
|
remove() {
|
||||||
this.isVisible = false;
|
this.isVisible = false;
|
||||||
|
|
||||||
// The current payButtons have no remove/cleanup function.
|
if (this.domWrapper) {
|
||||||
this.payButton = null;
|
this.domWrapper.hide().empty();
|
||||||
|
|
||||||
if (this.domWrapper?.remove) {
|
|
||||||
this.domWrapper.remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.domWrapper = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,23 @@ import merge from "deepmerge";
|
||||||
* Manages all PreviewButton instances of a certain payment method on the page.
|
* Manages all PreviewButton instances of a certain payment method on the page.
|
||||||
*/
|
*/
|
||||||
class PreviewButtonManager {
|
class PreviewButtonManager {
|
||||||
constructor({buttonConfig, widgetBuilder, defaultAttributes}) {
|
/**
|
||||||
|
* Resolves the promise.
|
||||||
|
* Used by `this.boostrap()` to process enqueued initialization logic.
|
||||||
|
*/
|
||||||
|
#onInitResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A deferred Promise that is resolved once the page is ready.
|
||||||
|
* Deferred init logic can be added by using `this.#onInit.then(...)`
|
||||||
|
*
|
||||||
|
* @param {Promise<void>|null}
|
||||||
|
*/
|
||||||
|
#onInit;
|
||||||
|
|
||||||
|
constructor({methodName, buttonConfig, widgetBuilder, defaultAttributes}) {
|
||||||
// Define the payment method name in the derived class.
|
// Define the payment method name in the derived class.
|
||||||
this.methodName = 'UNDEFINED';
|
this.methodName = methodName;
|
||||||
|
|
||||||
this.buttonConfig = buttonConfig;
|
this.buttonConfig = buttonConfig;
|
||||||
this.widgetBuilder = widgetBuilder;
|
this.widgetBuilder = widgetBuilder;
|
||||||
|
@ -17,11 +31,9 @@ class PreviewButtonManager {
|
||||||
this.buttons = {};
|
this.buttons = {};
|
||||||
this.configResponse = null;
|
this.configResponse = null;
|
||||||
|
|
||||||
// Empty promise that resolves instantly when called.
|
this.#onInit = new Promise(resolve => {
|
||||||
this.bootstrapping = Promise.resolve();
|
this.#onInitResolver = resolve;
|
||||||
|
});
|
||||||
// Add the bootstrap logic to the Promise chain. More `then`s are added by addButton().
|
|
||||||
this.bootstrapping = this.bootstrapping.then(() => this.bootstrap());
|
|
||||||
|
|
||||||
this.registerEventListeners();
|
this.registerEventListeners();
|
||||||
}
|
}
|
||||||
|
@ -49,8 +61,13 @@ class PreviewButtonManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
registerEventListeners() {
|
registerEventListeners() {
|
||||||
jQuery(document).on('ppcp_paypal_render_preview', (ev, ppcpConfig) => this.addButton(ppcpConfig));
|
jQuery(document).on('DOMContentLoaded', this.bootstrap.bind(this));
|
||||||
jQuery(document).on('DOMContentLoaded', () => this.bootstrapping);
|
|
||||||
|
// General event that all APM buttons react to.
|
||||||
|
jQuery(document).on('ppcp_paypal_render_preview', this.renderPreview.bind(this));
|
||||||
|
|
||||||
|
// Specific event to only (re)render the current APM button type.
|
||||||
|
jQuery(document).on(`ppcp_paypal_render_preview_${this.methodName}`, this.renderPreview.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,20 +105,41 @@ class PreviewButtonManager {
|
||||||
await Promise.all([customScriptPromise, paypalPromise]);
|
await Promise.all([customScriptPromise, paypalPromise]);
|
||||||
|
|
||||||
this.configResponse = await this.fetchConfig();
|
this.configResponse = await this.fetchConfig();
|
||||||
|
|
||||||
|
await this.#onInitResolver()
|
||||||
|
|
||||||
|
this.#onInit = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler, fires on `ppcp_paypal_render_preview`
|
||||||
|
*
|
||||||
|
* @param ev - Ignored
|
||||||
|
* @param ppcpConfig - The button settings for the preview.
|
||||||
|
*/
|
||||||
|
renderPreview(ev, ppcpConfig) {
|
||||||
|
const id = ppcpConfig.button.wrapper
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
this.error('Button did not provide a wrapper ID', ppcpConfig)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.buttons[id]) {
|
||||||
|
this.addButton(id, ppcpConfig);
|
||||||
|
} else {
|
||||||
|
this.buttons[id].config({
|
||||||
|
buttonConfig: this.buttonConfig,
|
||||||
|
ppcpConfig
|
||||||
|
}).render()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new preview button, that is rendered once the bootstrapping Promise resolves.
|
* Creates a new preview button, that is rendered once the bootstrapping Promise resolves.
|
||||||
*/
|
*/
|
||||||
addButton(ppcpConfig) {
|
addButton(id, ppcpConfig) {
|
||||||
if (!ppcpConfig.button.wrapper) {
|
|
||||||
this.error('Button did not provide a wrapper ID', ppcpConfig)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const createOrUpdateButton = () => {
|
const createOrUpdateButton = () => {
|
||||||
const id = ppcpConfig.button.wrapper;
|
|
||||||
|
|
||||||
if (!this.buttons[id]) {
|
if (!this.buttons[id]) {
|
||||||
this.buttons[id] = this.createButtonInst(id);
|
this.buttons[id] = this.createButtonInst(id);
|
||||||
}
|
}
|
||||||
|
@ -112,31 +150,13 @@ class PreviewButtonManager {
|
||||||
}).render()
|
}).render()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.bootstrapping) {
|
if (this.#onInit) {
|
||||||
this.bootstrapping.then(createOrUpdateButton);
|
this.#onInit.then(createOrUpdateButton);
|
||||||
} else {
|
} else {
|
||||||
createOrUpdateButton();
|
createOrUpdateButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the button configuration and re-renders all buttons.
|
|
||||||
*
|
|
||||||
* @return {this} Reference to self, for chaining.
|
|
||||||
*/
|
|
||||||
updateConfig(newConfig) {
|
|
||||||
if (!newConfig || 'object' !== typeof newConfig) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.buttonConfig = merge(this.buttonConfig, newConfig)
|
|
||||||
|
|
||||||
Object.values(this.buttons).forEach(button => button.config({buttonConfig: this.buttonConfig}))
|
|
||||||
this.renderButtons();
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes all buttons using the latest buttonConfig.
|
* Refreshes all buttons using the latest buttonConfig.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue