import Listener from "./listener";
/**
* 'choose_your_delivery' - triggered when the user clicks on a delivery option on the product page.
* Supports the new and old PDP widgets.
* @class
* @extends Listener
*/
export class ChooseYourDeliveryListener extends Listener {
eventName = "choose_your_delivery";
/**
* Depending on the product page, the scent buttons may have different selectors.
* This array contains all the selectors we're interested in.
* @type {string[]} - CSS selectors for the scent buttons on the page.
*/
selectors = [
'.op-sub-select', // new PDP
'.cof-sub-select', // old PDP
'input[name="purchase_type"]' // Power Pebbles
];
constructor(productName) {
super();
this.productName = productName;
}
listen() {
const buttons = this.getOptionButtons();
for (const btn of buttons) {
btn.addEventListener('click',
(event) => {
// Ignore the automated click events dispatched by other scripts
if (event.isTrusted) this.trigger(btn.option);
}
);
}
}
/**
* Gets the option buttons on the page.
* Uses the selectors array to find the buttons.
* Uses the `createOptionButton` method to create the button instances.
* @memberof ChooseYourDeliveryListener
* @returns {DeliveryOptionButton[]} - An array of DeliveryOptionButton instances.
*/
getOptionButtons() {
for (const selector of this.selectors) {
const buttonElements = document.querySelectorAll(selector);
const buttons = Array.from(buttonElements).map(
btn => this.createOptionButton(selector, btn)
);
if (buttons.length > 0) return buttons;
}
return [];
}
/**
* Abstract factory method for creating DeliveryOptionButton instances.
* This allows the subclasses to create different types of OptionButtons. (ie Scent, Delivery)
* @param {string} selector - The selector used to find the button.
* @param {HTMLElement} element - The button element.
* @returns {DeliveryOptionButton} - An instance of DeliveryOptionButton.
*/
createOptionButton(selector, element) {
switch (selector) {
case '.cof-sub-select':
return new DeliveryButtonOldVariant(element);
case 'input[name="purchase_type"]':
return new DeliveryButtonPebbles(element);
default:
return new DeliveryOptionButton(element);
}
}
createPayload(delivery) {
return {
selected_item: this.productName,
selected_item2: delivery
};
}
}
/**
* Wrapper class for the delivery option buttons.
* Exposes the option property which is used to create the payload.
* @class
* @param {HTMLElement} btn - The button element.
*/
export class DeliveryOptionButton {
constructor(btn) {
this.btn = btn;
}
/**
* The option value for the button.
* @type {string}
*/
get option() {
return this.btn.dataset.subtype === 'sub'
? 'subscription'
: 'onetime';
}
/**
* Wrapper for the native addEventListener method.
* @param {...any} args - Arguments to pass to the addEventListener method.
*/
addEventListener(...args) {
this.btn.addEventListener(...args);
}
}
/**
* Variation on the {@link DeliveryOptionButton} that supports the Power Pebbles product page.
* @class
* @param {HTMLElement} btn - The button element.
* @extends DeliveryOptionButton
*/
export class DeliveryButtonPebbles extends DeliveryOptionButton {
get option() {
return this.btn.value === 'onetime'
? 'onetime'
: 'subscription';
}
}
/**
* Variation on the {@link DeliveryOptionButton} that supports the old PDP widget.
* Useful for backward compatibility between product page variations.
* @class
* @param {HTMLElement} btn - The button element.
* @extends DeliveryOptionButton
*/
class DeliveryButtonOldVariant extends DeliveryOptionButton {
get option() {
const isSubOption = this.btn.classList.contains('cof-sub');
return isSubOption ? 'subscription' : 'onetime';
}
}