Skip to content
- Choosing a selection results in a full page refresh.
- Opens in a new window.
(() => {
document.addEventListener('DOMContentLoaded', function() {
const ATC_BUTTON_SELECTORS = ['button[type="submit"][name="add"]', 'button[type="submit"][data-add-to-cart]', 'button[type="submit"][data-action="add-to-cart"]', 'button[type="submit"][aria-label*="add to cart" i]'];
function hasVisibleAtcButton(form) {
return ATC_BUTTON_SELECTORS.some(sel => {
const btn = form.querySelector(sel);
return btn && btn.offsetParent !== null; // visible
});
}
function inferFormProductId(form) {
const withData = form.closest('[data-product-id]');
if (withData?.dataset?.productId) return String(withData.dataset.productId);
const withClass = form.closest('[class*="product-id-"]');
if (withClass) {
const match = Array.from(withClass.classList)
.map(c => c.match(/^product-id-(\d+)$/))
.find(Boolean);
if (match) return match[1];
}
const hidden = form.querySelector('input[name="product-id"], input[name="product[id]"]');
if (hidden?.value) return String(hidden.value);
return null;
}
function isFormForProduct(form, productId) {
const inferred = inferFormProductId(form);
return inferred ? String(inferred) === String(productId) : false;
}
function ensureBundleInput(form, bundleId) {
if (!form || form.querySelector('.appstle-bundle-properties')) return;
const input = document.createElement('input');
input.type = 'hidden';
input.className = 'appstle-bundle-properties';
input.name = 'properties[_appstle-bb-id]';
input.value = bundleId;
form.appendChild(input);
}
const pingClassicBundleVisitorAnalytics = bundleId => {
if (!bundleId || typeof window === 'undefined') return;
const sessionTokenName = 'appstle-bundles-visitor-session-token';
let sessionToken = sessionStorage.getItem(sessionTokenName);
if (!sessionToken) {
sessionToken = crypto.randomUUID();
sessionStorage.setItem(sessionTokenName, sessionToken);
}
const bundlePingKey = `pinged_${bundleId}`;
if (sessionStorage.getItem(bundlePingKey) === 'true') return;
sessionStorage.setItem(bundlePingKey, 'true');
const payload = {
sessionToken,
bundleId,
};
try {
fetch(`${location.origin}/apps/bundles/cp/api/ping-visitor`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
} catch (error) {
sessionStorage.removeItem(bundlePingKey);
}
}
const executeClassicBundleBlock = ({ blockElement, productId }) => {
const classicBundles = [{"id":21527,"shop":"jd-sound.myshopify.com","name":"Fixed height stage panel 1.0M x 1.0M size CHOOSE HEIGHT","description":"","status":"ACTIVE","customerIncludeTags":null,"discountType":"NO_DISCOUNT","discountValue":null,"products":"[{\"productId\":7397481742434,\"variantId\":null,\"price\":null,\"name\":\"Fixed height stage panel 1.0M x 1.0M\",\"productHandle\":\"fixed-height-stage-panel-1-0m-x-1-0m\",\"imageSrc\":\"https://cdn.shopify.com/s/files/1/0620/3781/9490/files/1x1_stage_panel_400legs_small_2_1.jpg?v=1752739784\",\"quantity\":1,\"status\":\"ACTIVE\",\"options\":[]},{\"productId\":7397465784418,\"variantId\":null,\"price\":null,\"name\":\"Fixed Height Stage Leg With Rubber Foot (Choose Size)\",\"productHandle\":\"fixed-height-stage-leg-with-rubber-foot-choose-size\",\"imageSrc\":\"https://cdn.shopify.com/s/files/1/0620/3781/9490/files/200mm.jpg?v=1752134368\",\"quantity\":\"4\",\"status\":\"ACTIVE\",\"options\":[{\"value\":[{\"name\":\"200mm\",\"selected\":true},{\"name\":\"300mm\",\"selected\":true},{\"name\":\"400mm\",\"selected\":true},{\"name\":\"600mm\",\"selected\":true}],\"name\":\"CHOOSE REQUIRED LEG HEIGHT (SET OF 4 LEGS)\"}]}]","variants":"[]","sequenceNo":null,"bundleType":"CLASSIC","settings":"{\"showClassicBundleWidgetInChildProduct\":false}","bundleProductId":7397483184226,"bundleVariantId":null,"productHandle":"fixed-height-stage-panel-1-0m-x-1-0m-size-choose-height-1","discountId":null,"price":null,"numberOfProducts":0,"subscriptionBundlingEnabled":false,"subscriptionId":null,"minProductCount":null,"maxProductCount":null,"uniqueRef":"gOYaDvWKeO","bundleRedirect":"CART","customRedirectURL":null,"minOrderAmount":null,"tieredDiscount":null,"productViewStyle":"QUICK_ADD","singleProductSettings":"null","trackInventory":false,"sellingPlanType":"BUNDLE_LEVEL","clearCart":"ENABLED","minPrice":379.0,"maxPrice":435.0,"externalBuildABoxId":null,"variantVisibilityType":"SHOW_VARIANTS_AS_INDIVIDUAL","subTitle":null,"freeShipping":false,"themeType":"THEME_TWO","showBundleInProductPage":true,"combinedWithProductDiscount":true,"combinedWithShippingDiscount":true,"combinedWithOrderDiscount":true,"allowedTags":null,"restrictTags":null,"selectionType":"FLEXIBLE","bundleHtml":"null","discountedVariants":"null","allowedCountries":null,"appliesOn":"BOTH","purchaseRequirement":"NO_REQUIREMENT","productDiscountType":"EACH_PRODUCT","countrySelectionType":"ALL_COUNTRY","discountApplyApproach":"SHOPIFY_DISCOUNT_FUNCTION","discountedProductChooseType":"CHOOSE_ALL","internalName":"Fixed height stage panel 1.0M x 1.0M size CHOOSE HEIGHT","sections":"[{\"id\":1,\"name\":\"\",\"description\":\"\",\"minProductCount\":0,\"maxProductCount\":0,\"variants\":[]}]","limitToUsePerCustomer":null,"discountedVariantSelectionLimit":null,"hideOneTimePurchase":false,"hideSubscriptionPurchase":false,"maxOrderAmount":null,"collectionData":null,"productSelectionType":"PRODUCT","tag":null,"productChooseType":"CHOOSE_ALL","variantSelectionLimit":null,"discountTargetType":"PRODUCT","enableSubscription":false,"subscriptionWidgetPosition":"BELOW","subscribeTitle":null,"subscribeSubtitle":null,"subscriptionPreselected":true,"getYAppliesOn":null,"announcementBarMessage":null,"automaticDiscountNodeId":null,"recurringCycleLimit":null,"automaticShippingDiscountNodeId":null,"scheduledBundleRule":null,"bundleActiveFrom":null,"bundleActiveTo":null,"bundleSubType":null,"discountAppliesOn":null,"layoutType":null,"style":"{\"productCardBackgroundColor\":\"#ffffff\",\"disabledTextColor\":\"#6B7280\",\"buttonBackgroundColor\":\"#000000\",\"bundlePageBackgroundColor\":\"#FAFAF9\",\"headingTextColor\":\"#000000\",\"primaryHoverColor\":\"#000000\",\"primaryTextColor\":\"#000000\",\"primaryColor\":\"#000000\",\"primaryDisabledColor\":\"#333333\",\"primaryDisabledTextColor\":\"#ffffff\",\"secondaryTextColor\":\"#ffffff\",\"fieldDisabledBackgroundColor\":\"#D1D5DB\"}","labels":"{}","upsells":null,"enableVolumeDiscountUpsell":false,"combos":null}];
const bundleSettings = {"id":9940,"shop":"jd-sound.myshopify.com","showOnProductPage":null,"selector":null,"placement":"AFTER","customCss":null,"customizeBundleOptionType":"RADIO","buyButtonSelector":null,"labels":"{\"productDiscountCombinedWithOrderDiscount\":true,\"bundleListViewDetailsButtonLabel\":\"View Details\",\"topBarFixedDiscountTitlePostfix\":\"{{currency}}{{discount}} off on shipping\",\"requiredLoginValidationLabel\":\"Please log in to purchase this bundle!\",\"volumeDiscountTypeLabel\":\"Volume Discount\",\"loginAlertLinkLabel\":\"Click here to login\",\"includedSubscriptionPlans\":\"\",\"breadCrumbProductsLabel\":\"Choose Products\",\"enableClassicBundleRecreation\":true,\"emptyProductImage\":\"https://cdn.shopify.com/s/files/1/0661/9224/4900/files/EmptyImage.jpg?v=1718447038\",\"enableAnnouncementBarAutoRotate\":true,\"reviewOrderInfoLabel\":\"\",\"productDiscountCombinedWithProductDiscount\":true,\"bundleMaximumQuantityLabel\":\"Add maximum up to {{maximum_quantity}} product\",\"volumeDiscountAppliesOnOneTimePurchase\":true,\"buyXGetYDiscountCodeText\":\"BUY_X_GET_Y_{{bundle_id}}\",\"productAddToBundleLabel\":\"Add\",\"defaultSelectedPurchaseOptionSwitch\":\"ONE_TIME\",\"breadCrumbReviewBundleLabel\":\"Review Bundle\",\"enableScrollingToBundleSection\":false,\"orderNoteLabel\":\"Order Note\",\"showProductPerPage\":50,\"requiresSubscriptionMessage\":\"Requires subscription\",\"dynamicBundleDiscountCombinedWithShippingDiscount\":true,\"hidePurchaseOptionSelectLabel\":false,\"showPriceAsDecimals\":false,\"fixedDiscountText\":\"Enjoy a fixed discount of {{currency}}{{discount_value}} on your purchase!\",\"sectionTotalLabel\":\"Section Total\",\"fieldDisabledBackgroundColor\":\"#D1D5DB\",\"enableShippingDiscountBar\":false,\"bundleTotalLabel\":\"Total\",\"disableRefreshSellingPlan\":false,\"checkInventoryQuantity\":false,\"showSubscriptionPlanDescription\":false,\"disableProductDescription\":false,\"fixedPricingBundleTypeLabel\":\"Fixed Pricing Bundle\",\"subscriptionAvailableLabel\":\"Subscription Available\",\"excludeSubscriptionPlans\":\"\",\"readLessText\":\"Read Less\",\"buyXGetYDiscountAppliesOnSubscription\":true,\"shippingDiscountLabel\":\"{{discount}}{{discount_type}} Shipping Discount\",\"selectedGiftProductProgressLabelText\":\"{{selected_product_quantity}} gift products added. The required quantity is {{required_product_quantity}}.\",\"disableFitImage\":false,\"secondaryTextColor\":\"#ffffff\",\"bundleProductsQuantityLabel\":\"{{quantity}}x quantity\",\"buyXGetYDiscountCombinedWithProductDiscount\":true,\"tieredDiscountLabel\":\"{{discount_amount}}{{discount_type}}
Discount\",\"buyXGetYQuantityValidationLabel\":\"Add {{product_quantity}} quantities of the gift product (Get Y)\",\"primaryTextColor\":\"#000000\",\"modalOpenOnAddToCart\":true,\"notApplicableForSubscribeAndSaveNotificationTitle\":\"Not applicable for subscribe & save\",\"customSignInLink\":\"\",\"volumeDiscountChooseProductLabel\":\"Choose Product\",\"productDiscountAppliesOnOneTimePurchase\":true,\"topBarDiscountUnlockTitlePrefix\":\"You've unlocked \",\"loginAlertTextLabel\":\"You need to login to purchase this bundle.\",\"buyXGetYChooseProductLabel\":\"Choose Product\",\"chooseAPlanLabel\":\"Choose Plan\",\"singleParentProductDirectRedirectToChildProducts\":true,\"buyXGetYFixedDiscountText\":\"Enjoy a fixed discount of {{discount_value}} {{currency}}\",\"notAvailableSubscriptionMessage\":\"Not available for subscription\",\"primaryColor\":\"#000000\",\"buyXGetYGiftProductPriceVisibilityType\":\"UNIT_PRICE\",\"shippingDiscountRecurringCycleLimit\":0,\"volumeDiscountVariantSelectLabel\":\"Denominations\",\"chooseSourceProductValidationLabel\":\"Please choose source product!\",\"shippingDiscountAppliesOnSubscription\":true,\"headingTextColor\":\"#000000\",\"volumeDiscountSpentAmountRewardsLabel\":\"Spend {{currency}}{{spent_amount}} and get {{discount}}{{discount_type}} discount!\",\"hideBundleToastNotification\":false,\"classicBundleTypeLabel\":\"Classic Bundle\",\"oneTimeAvailableHintLabel\":\"One-time purchase available.\",\"volumeDiscountRecurringCycleLimit\":0,\"bundleListDescription\":\"Explore our Bundles and Discounted Pricing and enjoy exclusive discounts when you buy products together\",\"getYNoProductSelectedLabel\":\"No gift product selected (Get Y)\",\"prepaidPerDeliveryPriceLabel\":\"{{prepaid_per_delivery_price}}/delivery\",\"hideVariantSelectLabel\":false,\"availableOnlySubscriptionLabel\":\"Available Only On Subscription\",\"enableParentProductDetailButton\":false,\"bundleListTitle\":\"List of Bundles and Discounted Pricing\",\"chooseAssociatedProductsValidationLabel\":\"Please choose associated products!\",\"selectedSourceProductLabel\":\"Selected\",\"enableBuyXGetYWidgetMergeAsOptions\":false,\"volumeDiscountNextApplicableSpentAmountRewardsLabel\":\"Spend {{spent_amount}}{{currency}} get {{discount}}{{discount_type}}\",\"sectionNoProductSelectedValidationLabel\":\"No product selected for: {{section_name}}!\",\"bundlePageBackgroundColor\":\"#FAFAF9\",\"showVendorName\":false,\"buyXQuantityValidationLabel\":\"Add {{product_quantity}} quantities of the product (Bux X)\",\"sectionMaximumQuantityValidationLabel\":\"Maximum quantity not selected for: {{section_name}}!\",\"enableMaxDiscountCap\":false,\"enableVolumeDiscountBar\":false,\"volumeAmountDiscountSaveRewardsLabel\":\"Save {{currency}}{{discount}}!\",\"sectionLabel\":\"Section\",\"disabledTextColor\":\"#6B7280\",\"primaryHoverColor\":\"#000000\",\"shippingDiscountCombinedWithOrderDiscount\":true,\"defaultDiscountBarMessage\":\"Welcome to our store\",\"enableBundleProductFilter\":false,\"buyXGetYDiscountCombinedWithOrderDiscount\":true,\"bundleSubtotalLabel\":\"Subtotal\",\"reviewOrderDescription\":\"Check your items and select your required frequency plan\",\"dynamicBundleDiscountCombinedWithOrderDiscount\":true,\"volumeDiscountSaveRewardsLabel\":\"Save {{discount}}{{discount_type}}!\",\"addingProductsToBundle\":\"Adding products to bundle\",\"buyXGetYMergedWidgetTitle\":\"Select Buy X Get Y Discount\",\"bundleModalHeaderLabel\":\"Your Bundle({{total_quantity}})\",\"productAddedToBundleNotificationDescription\":\"{{product_title}} added to bundle.\",\"dynamicBundleDiscountAppliesOnSubscription\":true,\"productDiscountTypeLabel\":\"Product Discount\",\"bundleSearchBarPlaceholder\":\"Search product by name or title\",\"bundleTopHtml\":\"\",\"proceedToCheckoutButtonText\":\"\",\"defaultSelectedPurchaseOption\":\"ONE_TIME\",\"showDraftProduct\":false,\"switchSubscriptionLabel\":\"Subscribe & Save\",\"percentDiscountText\":\"Get {{discount_value}}% off on your purchase!\",\"discountUsageLimitExceedLabel\":\"You have exceeded the bundle usage limit\",\"reviewOrderLabel\":\"Review Bundle\",\"chooseSectionProductsLabel\":\"Choose Section Products\",\"primaryDisabledColor\":\"#333333\",\"bundleMinimumOrderAmountLabel\":\"Add minimum {{minimum_amount}} order amount\",\"dynamicBundleDiscountRecurringCycleLimit\":0,\"breadCrumbSelectSectionLabel\":\"Select Section\",\"loadMoreButtonLabel\":\"Load More\",\"addedBundleToTheCart\":\"Added bundle to the cart\",\"bundleQuantityRewardsLabel\":\"Add {{quantity}} item, get {{discount}}{{discount_type}} discount\",\"shippingDiscountCombinedWithProductDiscount\":true,\"sellingPlanNameSortOrder\":\"ASC\",\"switchOnTimeLabel\":\"One Time\",\"volumeDiscountCombinedWithProductDiscount\":true,\"chooseProductsText\":\"Products\",\"productDetailsViewType\":\"SHOW_PRODUCT_POPUP\",\"enableManualBundleBlockIntegration\":false,\"volumeDiscountNextApplicableQuantityRewardsLabel\":\"Buy {{quantity}} get {{discount}}{{discount_type}}\",\"bundleCheckoutLabel\":\"Checkout\",\"productDiscountCombinedWithShippingDiscount\":true,\"skipSelectSectionPage\":false,\"productCardBackgroundColor\":\"#ffffff\",\"buyXGetYFreeLabel\":\"Free\",\"buttonBackgroundColor\":\"#000000\",\"dockbarHeadingLabel\":\"Bundle\",\"discountMessageInterval\":3000,\"sectionedBundleTypeLabel\":\"Sectioned Bundle\",\"buyXGetYAddToCartLabel\":\"Add to cart\",\"volumeDiscountChooseButtonLabel\":\"Choose\",\"buyXGetYDiscountCombinedWithShippingDiscount\":true,\"dynamicBundleDiscountCodeText\":\"BUNDLE_DISCOUNT_{{bundle_id}}\",\"switchPurchaseModeLabel\":\"Switch\",\"productDiscountAppliesOnSubscription\":true,\"selectedProgressLabelText\":\"{{total_bundle_items}} item added with a minimum quantity of {{minimum_quantity}}\",\"requiredBundleProductLabel\":\"Your bundle needs {{min_product_count}} more item(s).\",\"sellingPlanSelectionDropDownLabel\":\"Purchase Options\",\"buyXGetYPercentDiscountText\":\"Enjoy a percentage discount of {{discount_value}}%\",\"dockbarDescriptionLabel\":\"You're getting the most rewards!\",\"productDiscountRecurringCycleLimit\":0,\"preventClickableProductsOnCart\":false,\"showPrepaidPerDeliveryPrice\":true,\"enableProductDetailButton\":false,\"discountTargetType\":\"VARIANT\",\"buyXGetYDiscountTypeLabel\":\"Buy X Get Y Discount\",\"customOfferLink\":\"collections/all\",\"noItemsInBundle\":\"No items added to the bundle\",\"topBarPercentDiscountTitlePostfix\":\"{{discount}}% off on shipping\",\"variantSelectionDropDownLabel\":\"Variants\",\"chooseSectionLabel\":\"Choose Section\",\"dynamicPricingBundleTypeLabel\":\"Dynamic Pricing Bundle\",\"breadCrumbPlanLabel\":\"Select Plan\",\"showDynamicBundleOrderNote\":false,\"showOutOfStockProduct\":true,\"disabledSellingPlanSelectionValidation\":false,\"disableViewShopifyProduct\":false,\"bundleDiscountLabel\":\"Discount\",\"topBarDiscountRequiredAmountTitlePrefix\":\"Add {{currency}}{{remainingAmount}} more to unlock \",\"volumeDiscountAppliedQuantityRewardsLabel\":\"Applied: buy {{quantity}} get {{discount}}{{discount_type}}\",\"bundleNotEligibleLabel\":\"You're not eligible to purchase this bundle!\",\"reviewOrderProductsLabel\":\"Bundle Products\",\"outOfStockLabel\":\"Out Of Stock\",\"showUnitPrice\":false,\"buyXGetYFreeGiftDiscountText\":\"Enjoy the free product\",\"showDescriptionPopup\":true,\"maxDiscountCapValue\":0,\"readMoreText\":\"Read More\",\"totalBundleProductsAddedLabel\":\"{{total_bundle_items}} Products Added\",\"bundleMinimumQuantityLabel\":\"Add minimum {{minimum_quantity}} product\",\"noSourceProductSelectedLabel\":\"No source product selected.\",\"nonListedProductText\":\"Non-Listed\",\"buyXNoProductSelectedLabel\":\"No product selected (Buy X)\",\"volumeDiscountQuantityRewardsLabel\":\"Buy {{quantity}} quantity and get {{discount}}{{discount_type}} discount!\",\"freeShippingLabel\":\"Free Shipping\",\"previousButtonLabel\":\"Previous Step\",\"draftBundlePageTitle\":\"Oops! This bundle is temporarily unavailable.\",\"productDetailsMaximumDescriptionCount\":300,\"oneTimeOnlyLabel\":\"One time only\",\"buyXAnyNumberOfProductChooseLabel\":\"Choose any number of products\",\"productFilterConfig\":\"{\\\"enabled\\\":false,\\\"filters\\\":[]}\",\"volumeAmountDiscountQuantityRewardsLabel\":\"Buy {{quantity}} quantity and get {{currency}}{{discount}} discount!\",\"disableDiscountedPricingRedirectToCart\":false,\"volumeDiscountCombinedWithOrderDiscount\":true,\"dynamicBundleDiscountAppliesOnOneTimePurchase\":true,\"choosePlanButtonLabel\":\"Choose Plan\",\"enableAnnouncementBar\":false,\"bundleQuantityLabel\":\"{{quantity}}x\",\"showClassicBundleWidgetInChildProduct\":false,\"shippingDiscountAppliesOnOneTimePurchase\":true,\"classicBundleLinkLabel\":\"Go to the Classic Bundle\",\"topBarDiscountRequiredQuantityTitlePrefix\":\"Add {{remainingQuantity}} more item(s) to unlock \",\"bundleDetailsLabel\":\"Your bundle:\",\"buyXGetYDiscountAppliesOnOneTimePurchase\":true,\"volumeDiscountAppliedSpentAmountRewardsLabel\":\"Applied: spend {{spent_amount}}{{currency}} get {{discount}}{{discount_type}}\",\"enableAutoRemoveRelevantBundleItemInCart\":false,\"bundleModalShowRewardsLabel\":\"Show all rewards\",\"topBarFreeShippingTitlePostfix\":\"free shipping\",\"buyXGetYDiscountRecurringCycleLimit\":0,\"cartAndCheckoutMandatoryProductValidationMessage\":\"This bundle or discount must include all required products and they cannot be removed.\",\"enableSequentialProductLoading\":false,\"volumeAmountDiscountSpentAmountRewardsLabel\":\"Spend {{currency}}{{spent_amount}} and get {{currency}}{{discount}} discount!\",\"notApplicableForOneTimeNotificationTitle\":\"Not applicable for one time\",\"showDiscountToNonEligibleCustomers\":false,\"primaryDisabledTextColor\":\"#ffffff\",\"draftBundlePageSubTitle\":\"In the meantime, check out our latest offers and discounts!\",\"volumeDiscountCombinedWithShippingDiscount\":true,\"bundleSpentAmountRewardsLabel\":\"Spent {{spent_amount}} worth of items, get {{discount}}{{discount_type}} discount\",\"nextButtonLabel\":\"Next Step\",\"classicBundleDescriptionLabel\":\"Your bundle contains the following products.\",\"bundleBottomHtml\":\"\",\"sectionMinimumQuantityValidationLabel\":\"Minimum quantity not selected for: {{section_name}}!\",\"volumeDiscountAppliesOnSubscription\":true,\"dynamicBundleDiscountCombinedWithProductDiscount\":true,\"buyXGetYAnyNumberOfGiftProductLabel\":\"Choose any number of gift products\",\"subscriptionAvailableHintLabel\":\"Subscribe & save available.\",\"descriptionLength\":200,\"bundleDiscountNote\":\"Discounts will be applied at checkout.\",\"bundleModalCloseRewardsLabel\":\"Close all rewards\",\"dockbarCurrentRewardLabel\":\"You got {{discount_amount}}{{discount_type}} discount\",\"productDetailsAddToBundleLabel\":\"Add to bundle\",\"cartAndCheckoutQuantityValidationMessage\":\"Orders must match the quantity range: Min {{min_quantity}}, Max {{max_quantity}}\",\"bundleNoProductSelectedLabel\":\"No product selected\",\"checkoutInfoLabel\":\"Add products from each section to enable the add to cart button.\",\"enableShowMultipleImages\":false,\"redirectToCartPageOnCartIconClick\":true,\"freeShippingDiscountCodeText\":\"FREE_SHIPPING_{{bundle_id}}\",\"customOfferLinkButtonLabel\":\"Explore Offers\",\"oneTimePurchaseLabel\":\"One Time Purchase\",\"bundleMaximumOrderAmountLabel\":\"Add maximum {{maximum_amount}} order amount\",\"enableBundleProductAscOrderView\":true,\"productAddedToBundleNotificationTitle\":\"Added to bundle\",\"showClassicBundleProductVariant\":false,\"customHtmlInject\":\"[]\",\"sectionedBundleDiscountCodeText\":\"SECTIONED_DISCOUNT_{{bundle_id}}\",\"breadCrumbReviewSectionLabel\":\"Review Section\"}","bundleTopHtml":"","bundleBottomHtml":"","proceedToCheckoutButtonText":"","chooseProductsText":"Products","productAddToBundleLabel":"Add","productDetailsAddToBundleLabel":"Add to bundle","productDetailsMaximumDescriptionCount":300,"variantSelectionDropDownLabel":"Variants","sellingPlanSelectionDropDownLabel":"Purchase Options","dockbarHeadingLabel":"Bundle","dockbarCurrentRewardLabel":"You got {{discount_amount}}{{discount_type}} discount","dockbarDescriptionLabel":"You're getting the most rewards!","bundleModalHeaderLabel":"Your Bundle({{total_quantity}})","bundleModalShowRewardsLabel":"Show all rewards","bundleModalCloseRewardsLabel":"Close all rewards","bundleQuantityRewardsLabel":"Add {{quantity}} item, get {{discount}}{{discount_type}} discount","bundleSpentAmountRewardsLabel":"Spent {{spent_amount}} worth of items, get {{discount}}{{discount_type}} discount","bundleQuantityLabel":"{{quantity}}x","bundleSubtotalLabel":"Subtotal","bundleDiscountLabel":"Discount","bundleTotalLabel":"Total","bundleCheckoutLabel":"Checkout","bundleMinimumQuantityLabel":"Add minimum {{minimum_quantity}} product","bundleMaximumQuantityLabel":"Add maximum up to {{maximum_quantity}} product","bundleMinimumOrderAmountLabel":"Add minimum {{minimum_amount}} order amount","oneTimePurchaseLabel":"One Time Purchase","noItemsInBundle":"No items added to the bundle","modalOpenOnAddToCart":true,"productAddedToBundleNotificationTitle":"Added to bundle","productAddedToBundleNotificationDescription":"{{product_title}} added to bundle.","chooseAPlanLabel":"Choose Plan","nextButtonLabel":"Next Step","previousButtonLabel":"Previous Step","chooseSourceProductValidationLabel":"Please choose source product!","chooseAssociatedProductsValidationLabel":"Please choose associated products!","choosePlanButtonLabel":"Choose Plan","selectedSourceProductLabel":"Selected","noSourceProductSelectedLabel":"No source product selected.","reviewOrderLabel":"Review Bundle","reviewOrderDescription":"Check your items and select your required frequency plan","reviewOrderProductsLabel":"Bundle Products","reviewOrderInfoLabel":"","orderNoteLabel":"Order Note","selectedProgressLabelText":"{{total_bundle_items}} item added with a minimum quantity of {{minimum_quantity}}","availableOnlySubscriptionLabel":"Available Only On Subscription","subscriptionAvailableLabel":"Subscription Available","oneTimeOnlyLabel":"One time only","switchOnTimeLabel":"One Time","switchSubscriptionLabel":"Subscribe & Save","breadCrumbPlanLabel":"Select Plan","breadCrumbProductsLabel":"Choose Products","breadCrumbReviewBundleLabel":"Review Bundle","showDescriptionPopup":true,"tieredDiscountQuantityLabel":null,"tieredDiscountAmountLabel":null,"tieredDiscountLabel":"{{discount_amount}}{{discount_type}}
Discount","emptyProductImage":"https://cdn.shopify.com/s/files/1/0661/9224/4900/files/EmptyImage.jpg?v=1718447038","outOfStockLabel":"Out Of Stock","notApplicableForOneTimeNotificationTitle":"Not applicable for one time","notApplicableForSubscribeAndSaveNotificationTitle":"Not applicable for subscribe & save","disableProductDescription":false,"descriptionLength":200,"readLessText":"Read Less","readMoreText":"Read More","bundleNoProductSelectedLabel":"No product selected","customHtmlInject":"[]","bundleDetailsLabel":"Your bundle:","bundleDiscountNote":"Discounts will be applied at checkout.","fixedDiscountText":"Enjoy a fixed discount of {{currency}}{{discount_value}} on your purchase!","percentDiscountText":"Get {{discount_value}}% off on your purchase!","hideVariantSelectLabel":false,"hidePurchaseOptionSelectLabel":false,"showMainToggleForProductLevel":null,"hideProductPurchaseModeAwarenessHint":null,"hideIncompatibleProductMessage":null,"subscriptionAvailableHintLabel":"Subscribe & save available.","oneTimeAvailableHintLabel":"One-time purchase available.","switchPurchaseModeLabel":"Switch","notAvailableSubscriptionMessage":"Not available for subscription","requiresSubscriptionMessage":"Requires subscription","primaryColor":"#000000","primaryTextColor":"#000000","secondaryTextColor":"#ffffff","primaryHoverColor":"#000000","primaryDisabledColor":"#333333","primaryDisabledTextColor":"#ffffff","fieldDisabledBackgroundColor":"#D1D5DB","disabledTextColor":"#6B7280","volumeDiscountSaveRewardsLabel":"Save {{discount}}{{discount_type}}!","volumeDiscountQuantityRewardsLabel":"Buy {{quantity}} quantity and get {{discount}}{{discount_type}} discount!","volumeDiscountSpentAmountRewardsLabel":"Spend {{currency}}{{spent_amount}} and get {{discount}}{{discount_type}} discount!","volumeDiscountAppliedQuantityRewardsLabel":"Applied: buy {{quantity}} get {{discount}}{{discount_type}}","volumeDiscountAppliedSpentAmountRewardsLabel":"Applied: spend {{spent_amount}}{{currency}} get {{discount}}{{discount_type}}","volumeDiscountNextApplicableQuantityRewardsLabel":"Buy {{quantity}} get {{discount}}{{discount_type}}","volumeDiscountNextApplicableSpentAmountRewardsLabel":"Spend {{spent_amount}}{{currency}} get {{discount}}{{discount_type}}","addingProductsToBundle":"Adding products to bundle","freeShippingLabel":"Free Shipping","requiredBundleProductLabel":"Your bundle needs {{min_product_count}} more item(s).","enableProductDetailButton":false,"requiredLoginValidationLabel":"Please log in to purchase this bundle!","bundleNotEligibleLabel":"You're not eligible to purchase this bundle!","loginAlertTextLabel":"You need to login to purchase this bundle.","loginAlertLinkLabel":"Click here to login","customSignInLink":"","shippingDiscountLabel":"{{discount}}{{discount_type}} Shipping Discount","classicBundleDescriptionLabel":"Your bundle contains the following products.","singleParentProductDirectRedirectToChildProducts":true,"buyXGetYFixedDiscountText":"Enjoy a fixed discount of {{discount_value}} {{currency}}","buyXGetYPercentDiscountText":"Enjoy a percentage discount of {{discount_value}}%","buyXGetYFreeGiftDiscountText":"Enjoy the free product","buyXGetYAddToCartLabel":"Add to cart","buyXGetYFreeLabel":"Free","disableDiscountedPricingRedirectToCart":false,"nonListedProductText":"Non-Listed","preventClickableProductsOnCart":false,"buyXGetYChooseProductLabel":"Choose Product","showSubscriptionPlanDescription":false,"volumeAmountDiscountSaveRewardsLabel":"Save {{currency}}{{discount}}!","volumeAmountDiscountQuantityRewardsLabel":"Buy {{quantity}} quantity and get {{currency}}{{discount}} discount!","volumeAmountDiscountSpentAmountRewardsLabel":"Spend {{currency}}{{spent_amount}} and get {{currency}}{{discount}} discount!","enableManualBundleBlockIntegration":false,"cartAndCheckoutQuantityValidationMessage":"Orders must match the quantity range: Min {{min_quantity}}, Max {{max_quantity}}","dynamicBundleDiscountCodeText":"BUNDLE_DISCOUNT_{{bundle_id}}","discountUsageLimitExceedLabel":"You have exceeded the bundle usage limit","disableViewShopifyProduct":false,"redirectToCartPageOnCartIconClick":true,"sectionLabel":"Section","chooseSectionLabel":"Choose Section","chooseSectionProductsLabel":"Choose Section Products","breadCrumbSelectSectionLabel":"Select Section","breadCrumbReviewSectionLabel":"Review Section","checkoutInfoLabel":"Add products from each section to enable the add to cart button.","sectionNoProductSelectedValidationLabel":"No product selected for: {{section_name}}!","sectionMinimumQuantityValidationLabel":"Minimum quantity not selected for: {{section_name}}!","sectionMaximumQuantityValidationLabel":"Maximum quantity not selected for: {{section_name}}!","dynamicBundleDiscountCombinedWithProductDiscount":true,"dynamicBundleDiscountCombinedWithShippingDiscount":true,"dynamicBundleDiscountCombinedWithOrderDiscount":true,"volumeDiscountCombinedWithProductDiscount":true,"volumeDiscountCombinedWithShippingDiscount":true,"volumeDiscountCombinedWithOrderDiscount":true,"productDiscountCombinedWithProductDiscount":true,"productDiscountCombinedWithShippingDiscount":true,"productDiscountCombinedWithOrderDiscount":true,"buyXGetYDiscountCombinedWithProductDiscount":true,"buyXGetYDiscountCombinedWithShippingDiscount":true,"buyXGetYDiscountCombinedWithOrderDiscount":true,"shippingDiscountCombinedWithProductDiscount":true,"shippingDiscountCombinedWithOrderDiscount":true,"showDynamicBundleOrderNote":false,"bundleMaximumOrderAmountLabel":"Add maximum {{maximum_amount}} order amount","buyXGetYQuantityValidationLabel":"Add {{product_quantity}} quantities of the gift product (Get Y)","selectedGiftProductProgressLabelText":"{{selected_product_quantity}} gift products added. The required quantity is {{required_product_quantity}}.","draftBundlePageTitle":"Oops! This bundle is temporarily unavailable.","draftBundlePageSubTitle":"In the meantime, check out our latest offers and discounts!","customOfferLink":"collections/all","customOfferLinkButtonLabel":"Explore Offers","enableParentProductDetailButton":false,"sectionTotalLabel":"Section Total","skipSelectSectionPage":false,"buyXGetYGiftProductPriceVisibilityType":"UNIT_PRICE","defaultSelectedPurchaseOptionSwitch":"ONE_TIME","defaultSelectedPurchaseOption":"ONE_TIME","discountTargetType":"VARIANT","enableShowMultipleImages":false,"buyXGetYAnyNumberOfGiftProductLabel":"Choose any number of gift products","showDiscountToNonEligibleCustomers":false,"dynamicBundleDiscountRecurringCycleLimit":0,"dynamicBundleDiscountAppliesOnOneTimePurchase":true,"dynamicBundleDiscountAppliesOnSubscription":true,"volumeDiscountRecurringCycleLimit":0,"volumeDiscountAppliesOnOneTimePurchase":true,"volumeDiscountAppliesOnSubscription":true,"productDiscountRecurringCycleLimit":0,"productDiscountAppliesOnOneTimePurchase":true,"productDiscountAppliesOnSubscription":true,"buyXGetYDiscountRecurringCycleLimit":0,"buyXGetYDiscountAppliesOnOneTimePurchase":true,"buyXGetYDiscountAppliesOnSubscription":true,"shippingDiscountRecurringCycleLimit":0,"shippingDiscountAppliesOnOneTimePurchase":true,"shippingDiscountAppliesOnSubscription":true,"buyXNoProductSelectedLabel":"No product selected (Buy X)","getYNoProductSelectedLabel":"No gift product selected (Get Y)","buyXQuantityValidationLabel":"Add {{product_quantity}} quantities of the product (Bux X)","buyXAnyNumberOfProductChooseLabel":"Choose any number of products","freeShippingDiscountCodeText":"FREE_SHIPPING_{{bundle_id}}","includedSubscriptionPlans":"","excludeSubscriptionPlans":"","enableBuyXGetYWidgetMergeAsOptions":false,"buyXGetYMergedWidgetTitle":"Select Buy X Get Y Discount","showClassicBundleProductVariant":false,"showProductPerPage":50,"loadMoreButtonLabel":"Load More","enableBundleProductAscOrderView":true,"cartAndCheckoutMandatoryProductValidationMessage":"This bundle or discount must include all required products and they cannot be removed.","sellingPlanNameSortOrder":"ASC","showVendorName":false,"disableFitImage":false,"enableAutoRemoveRelevantBundleItemInCart":false,"enableBundleProductFilter":false,"productFilterConfig":"{\"enabled\":false,\"filters\":[]}","enableMaxDiscountCap":false,"maxDiscountCapValue":0,"classicBundleLinkLabel":"Go to the Classic Bundle","childProductInfoBannerText":null,"showPriceAsDecimals":false,"showClassicBundleWidgetInChildProduct":false,"showOutOfStockProduct":true,"showDraftProduct":false,"totalBundleProductsAddedLabel":"{{total_bundle_items}} Products Added","bundleProductsQuantityLabel":"{{quantity}}x quantity","showUnitPrice":false,"productDetailsViewType":"SHOW_PRODUCT_POPUP","disableRefreshSellingPlan":false,"enableShippingDiscountBar":false,"enableVolumeDiscountBar":false,"defaultDiscountBarMessage":"Welcome to our store","discountMessageInterval":3000,"addedBundleToTheCart":"Added bundle to the cart","disabledSellingPlanSelectionValidation":false,"volumeDiscountVariantSelectLabel":"Denominations","enableScrollingToBundleSection":false,"enableClassicBundleRecreation":true,"topBarDiscountUnlockTitlePrefix":"You've unlocked ","topBarDiscountRequiredAmountTitlePrefix":"Add {{currency}}{{remainingAmount}} more to unlock ","topBarDiscountRequiredQuantityTitlePrefix":"Add {{remainingQuantity}} more item(s) to unlock ","topBarPercentDiscountTitlePostfix":"{{discount}}% off on shipping","topBarFixedDiscountTitlePostfix":"{{currency}}{{discount}} off on shipping","topBarFreeShippingTitlePostfix":"free shipping","checkInventoryQuantity":false,"hideBundleToastNotification":false,"enableBundleRecreation":null,"enableAnnouncementBar":false,"enableAnnouncementBarAutoRotate":true,"bundleListTitle":"List of Bundles and Discounted Pricing","bundleListDescription":"Explore our Bundles and Discounted Pricing and enjoy exclusive discounts when you buy products together","bundleListViewDetailsButtonLabel":"View Details","classicBundleTypeLabel":"Classic Bundle","dynamicPricingBundleTypeLabel":"Dynamic Pricing Bundle","fixedPricingBundleTypeLabel":"Fixed Pricing Bundle","sectionedBundleTypeLabel":"Sectioned Bundle","volumeDiscountTypeLabel":"Volume Discount","productDiscountTypeLabel":"Product Discount","buyXGetYDiscountTypeLabel":"Buy X Get Y Discount","bundlePageBackgroundColor":"#FAFAF9","productCardBackgroundColor":"#ffffff","buttonBackgroundColor":"#000000","showPrepaidPerDeliveryPrice":true,"prepaidPerDeliveryPriceLabel":"{{prepaid_per_delivery_price}}/delivery","bundleSearchBarPlaceholder":"Search product by name or title","headingTextColor":"#000000","volumeDiscountChooseButtonLabel":"Choose","volumeDiscountChooseProductLabel":"Choose Product","sectionedBundleDiscountCodeText":"SECTIONED_DISCOUNT_{{bundle_id}}","buyXGetYDiscountCodeText":"BUY_X_GET_Y_{{bundle_id}}","volumeDiscountBuyXGetYFreeRewardsCodeText":null,"volumeDiscountFreeGiftDiscountCodeText":null};
let isClassicBundleProductPage = true;
const classicBundle = Array.isArray(classicBundles) && classicBundles?.length > 0 && classicBundles.find((rule) => {
if (rule?.bundleType === 'CLASSIC' && rule?.status === 'ACTIVE') {
try {
const targetProductId = parseInt(productId);
const ruleProductId = parseInt(rule?.bundleProductId);
if (ruleProductId === targetProductId) return true;
const bundleProducts = rule?.products ? JSON.parse(rule?.products) : [];
const foundInChildProduct = bundleProducts.some(
product => parseInt(product?.productId) === targetProductId
);
const bundleRuleSettings = rule?.settings ? JSON.parse(rule?.settings || '{}') : { showClassicBundleWidgetInChildProduct: false };
if (foundInChildProduct && (bundleRuleSettings?.showClassicBundleWidgetInChildProduct === true || bundleSettings?.showClassicBundleWidgetInChildProduct === true)) {
isClassicBundleProductPage = false;
return true;
}
return false;
} catch (e) {
console.error('Failed to parse JSON:', e);
return false;
}
}
return false;
}) || null;
if (classicBundle && blockElement) {
const classicBundleProducts = classicBundle?.products ? JSON.parse(classicBundle?.products) : null;
const candidateForms = Array.from(document.querySelectorAll('form[action*="/cart/add"]'))?.filter(f => isFormForProduct(f, productId));
const targetForm = candidateForms.find(hasVisibleAtcButton) || candidateForms[0] || null;
if (targetForm) {
ensureBundleInput(targetForm, classicBundle?.uniqueRef);
}
if (classicBundleProducts && classicBundleProducts.length > 0) {
const classicBundleProductContainer = document.createElement('div');
classicBundleProductContainer.className = 'ab-classic-bundle-products';
if (!isClassicBundleProductPage) {
const infoBanner = document.createElement('div');
infoBanner.className = 'ab-classic-bundle-info-banner';
const iconSpan = document.createElement('span');
iconSpan.className = 'ab-classic-bundle-info-icon';
iconSpan.innerHTML = 'ⓘ';
const textSpan = document.createElement('span');
textSpan.className = 'ab-classic-bundle-info-text';
textSpan.innerText = bundleSettings?.childProductInfoBannerText || 'This product is part of a bundle';
infoBanner.appendChild(iconSpan);
infoBanner.appendChild(textSpan);
classicBundleProductContainer.appendChild(infoBanner);
classicBundleProductContainer.classList.add('ab-on-child-product');
}
const classicBundleDescription = document.createElement('div');
classicBundleDescription.className = 'ab-classic-bundle-description';
if (bundleSettings?.headingTextColor) {
classicBundleDescription.style.color = bundleSettings.headingTextColor;
}
classicBundleDescription.innerText = bundleSettings?.classicBundleDescriptionLabel || classicBundle?.description || 'Your bundle contains the following products.';
classicBundleProductContainer.appendChild(classicBundleDescription);
let currentOptionIndex = 0;
const productOptionMap = {};
classicBundleProducts?.forEach((bundle, index) => {
const hasOptions = bundle?.options?.length > 0 && bundle?.options.some(opt => opt?.value?.length > 0);
if (hasOptions) {
const optionIndices = [];
bundle?.options.forEach(() => {
optionIndices.push(currentOptionIndex++);
});
productOptionMap[bundle?.productId] = optionIndices;
}
const productWrapper = document.createElement('div');
productWrapper.className = 'ab-classic-bundle-product-wrapper';
const classicBundleProduct = document.createElement('div');
classicBundleProduct.className = hasOptions ? 'ab-classic-bundle-product ab-has-variants' : 'ab-classic-bundle-product';
const image = document.createElement('img');
image.className = 'ab-classic-bundle-product-image';
image.src = bundle?.imageSrc || 'https://cdn.shopify.com/s/files/1/0661/9224/4900/files/EmptyImage.jpg?v=1718447038';
image.alt = bundle?.name || 'Product Image';
classicBundleProduct.appendChild(image);
const classicBundleProductInfo = document.createElement('div');
classicBundleProductInfo.className = 'ab-classic-bundle-product-info';
const productNameAndQuantity = document.createElement('div');
productNameAndQuantity.className = 'ab-classic-bundle-product-name-quantity';
const quantity = document.createElement('span');
quantity.className = 'ab-classic-bundle-product-quantity';
quantity.textContent = bundle?.quantity || 0;
const name = document.createElement('a');
name.className = 'ab-classic-bundle-product-name';
name.textContent = bundle?.name || '';
name.href = `https://${classicBundle?.shop}/products/${bundle?.productHandle}` || '#';
name.target = '_blank';
name.rel = 'noopener noreferrer';
if (bundleSettings?.disableViewShopifyProduct) {
name.href = 'javascript:void(0)';
name.style.pointerEvents = 'none';
name.removeAttribute('target');
}
productNameAndQuantity.appendChild(quantity);
productNameAndQuantity.appendChild(name);
classicBundleProductInfo.appendChild(productNameAndQuantity);
if (hasOptions) {
// Collect all selected variant names for this product
const selectedVariants = [];
bundle?.options.forEach(option => {
const selected = option?.value?.find(val => val?.selected);
if (selected) {
selectedVariants.push(selected.name);
}
});
// Show all selected variants for this product inline with product name
if (selectedVariants.length > 0) {
const variantSpan = document.createElement('span');
variantSpan.className = 'ab-classic-bundle-product-variant-inline';
variantSpan.setAttribute('data-product-id', bundle?.productId);
variantSpan.setAttribute('data-option-indices', productOptionMap[bundle?.productId].join(','));
variantSpan.textContent = `(${selectedVariants.join(' / ')})`;
name.appendChild(variantSpan);
}
}
classicBundleProduct.appendChild(classicBundleProductInfo);
productWrapper.appendChild(classicBundleProduct);
// Add separator "+" between products (not after the last one)
if (index < classicBundleProducts.length - 1) {
const separator = document.createElement('div');
separator.className = 'ab-classic-bundle-product-separator';
separator.textContent = '+';
productWrapper.appendChild(separator);
}
classicBundleProductContainer.appendChild(productWrapper);
});
if (!isClassicBundleProductPage) {
const classicBundleLink = document.createElement('a');
classicBundleLink.className = 'ab-classic-bundle-product-link ab-bundle-cta-button';
const linkIcon = document.createElement('span');
linkIcon.className = 'ab-bundle-link-icon';
linkIcon.innerHTML = '→';
const linkText = document.createElement('span');
linkText.innerText = bundleSettings?.classicBundleLinkLabel || 'View Complete Bundle';
classicBundleLink.appendChild(linkText);
classicBundleLink.appendChild(linkIcon);
classicBundleLink.href = `/products/${classicBundle?.productHandle || ''}`;
classicBundleLink.target = '_self';
classicBundleLink.rel = 'noopener noreferrer';
const copyButtonStyles = () => {
const atcButton = targetForm?.querySelector('button[type="submit"]') ||
document.querySelector('button[name="add"]') ||
document.querySelector('form[action*="/cart/add"] button[type="submit"]');
if (atcButton) {
const computedStyle = window.getComputedStyle(atcButton);
const backgroundColor = computedStyle.backgroundColor;
const color = computedStyle.color;
const borderRadius = computedStyle.borderRadius;
const fontFamily = computedStyle.fontFamily;
const fontWeight = computedStyle.fontWeight;
if (backgroundColor && backgroundColor !== 'rgba(0, 0, 0, 0)' && backgroundColor !== 'transparent') {
classicBundleLink.style.setProperty('--ab-cta-bg', backgroundColor);
}
if (color) {
classicBundleLink.style.setProperty('--ab-cta-text', color);
}
if (borderRadius) {
classicBundleLink.style.borderRadius = borderRadius;
}
if (fontFamily) {
classicBundleLink.style.fontFamily = fontFamily;
}
if (fontWeight) {
classicBundleLink.style.fontWeight = fontWeight;
}
}
};
requestAnimationFrame(copyButtonStyles);
setTimeout(copyButtonStyles, 100);
classicBundleProductContainer.appendChild(classicBundleLink);
}
blockElement.innerHTML = '';
blockElement.appendChild(classicBundleProductContainer);
pingClassicBundleVisitorAnalytics(classicBundle?.id);
const matchWidth = () => {
let referenceWidth = null;
let matchedSource = null;
// Strategy 1: Use the product form width (most universal)
const productForm = targetForm || document.querySelector('form[action*="/cart/add"]');
if (productForm && productForm.offsetParent !== null && productForm.offsetWidth > 0) {
referenceWidth = productForm.offsetWidth;
matchedSource = 'product-form';
}
// Strategy 2: Match sibling elements in the same container
if (!referenceWidth && blockElement?.parentElement) {
const siblings = Array.from(blockElement.parentElement.children).filter(el => el !== blockElement);
for (const sibling of siblings) {
if (sibling.offsetParent !== null && sibling.offsetWidth > 100) {
referenceWidth = sibling.offsetWidth;
matchedSource = 'sibling-element';
break;
}
}
}
// Strategy 3: Find submit button and its parent container
if (!referenceWidth) {
const submitButton = productForm?.querySelector('button[type="submit"]') ||
document.querySelector('button[name="add"]') ||
document.querySelector('form[action*="/cart/add"] button[type="submit"]');
if (submitButton && submitButton.offsetParent !== null) {
// Walk up the DOM to find a container that wraps the button
let parent = submitButton.parentElement;
let attempts = 0;
while (parent && attempts < 5) {
if (parent.offsetWidth > submitButton.offsetWidth * 1.1) {
referenceWidth = parent.offsetWidth;
matchedSource = 'button-container';
break;
}
parent = parent.parentElement;
attempts++;
}
// Fallback to button width if no suitable container
if (!referenceWidth) {
referenceWidth = submitButton.offsetWidth;
matchedSource = 'submit-button';
}
}
}
// Strategy 4: Use Shopify payment button as reference (standard across themes)
if (!referenceWidth) {
const paymentButton = document.querySelector('.shopify-payment-button') ||
document.querySelector('[data-shopify="payment-button"]');
if (paymentButton && paymentButton.offsetParent !== null && paymentButton.offsetWidth > 0) {
referenceWidth = paymentButton.offsetWidth;
matchedSource = 'shopify-payment-button';
}
}
// Strategy 5: Match parent container width (ultimate fallback)
if (!referenceWidth && blockElement?.parentElement) {
const parent = blockElement.parentElement;
if (parent.offsetWidth > 0) {
referenceWidth = parent.offsetWidth;
matchedSource = 'parent-container';
}
}
// Apply the width
if (referenceWidth && referenceWidth > 0) {
classicBundleProductContainer.style.width = `${referenceWidth}px`;
classicBundleProductContainer.style.maxWidth = `${referenceWidth}px`;
if (window._ABConfig?.debug) {
console.log('[Appstle Bundle] Matched width:', referenceWidth, 'px from:', matchedSource);
}
} else {
// No width found - use 100% of container
classicBundleProductContainer.style.width = '100%';
classicBundleProductContainer.style.maxWidth = 'none';
if (window._ABConfig?.debug) {
console.warn('[Appstle Bundle] No reference found, using 100% width');
}
}
};
requestAnimationFrame(matchWidth);
setTimeout(matchWidth, 50);
setTimeout(matchWidth, 150);
setTimeout(matchWidth, 300);
setTimeout(matchWidth, 600);
setTimeout(matchWidth, 1000);
if (window.ResizeObserver) {
const resizeObserver = new ResizeObserver(() => {
matchWidth();
});
// Observe generic elements that are likely to resize
const observeElements = [
targetForm || document.querySelector('form[action*="/cart/add"]'),
blockElement?.parentElement,
document.querySelector('.shopify-payment-button')
].filter(el => el && el.offsetParent !== null);
observeElements.forEach(el => {
try {
resizeObserver.observe(el);
} catch (e) {
// Ignore errors if element can't be observed
}
});
}
}
}
};
const productId = "7324653355106";
const disableAppFunctionality = window?._ABConfig?.['disableAppFunctionality'] || false;
const blockElement = document.getElementById('classicBundleContainer');
const blockElements = document.querySelectorAll('.ab-classic-bundle-custom-placement-selector');
function setupVariantDetection() {
const d=window._ABConfig?.debug,f=document.querySelector('form[action*="/cart/add"]');
document.querySelectorAll('select[name="id"],input[name="id"],select.single-option-selector,select[id*="Option"],select[name*="option"],input[type="radio"][name*="option"]').forEach(s=>s.addEventListener('change',()=>setTimeout(updateVariantDisplay,10)));
document.addEventListener('click',e=>{const t=e.target;if(t&&(t.matches('button[data-option-value]')||t.closest('.swatch-element, .variant-option, [data-option], [class*="variant"]')))setTimeout(updateVariantDisplay,50);});
['variant:changed','variantChange','variant:change'].forEach(e=>document.addEventListener(e,updateVariantDisplay));
window.addEventListener('popstate',()=>setTimeout(updateVariantDisplay,10));
if(f){const i=f.querySelector('input[name="id"],select[name="id"]');if(i)new MutationObserver(()=>setTimeout(updateVariantDisplay,10)).observe(i,{attributes:!0,attributeFilter:['value']});}
}
function updateVariantDisplay() {
const d=window._ABConfig?.debug,f=document.querySelector('form[action*="/cart/add"]');
if(!f){if(d)console.warn('[AB] No form');return;}
const g=s=>Array.from(s).map(x=>x.options?.[x.selectedIndex]?.value||x.value||x.textContent?.trim()||x.getAttribute('data-option-value')||x.getAttribute('aria-label')).filter(Boolean);
// Collect ALL variant options as an array
let allOptions=[];
let s=f.querySelectorAll('select.single-option-selector');
if(s.length){allOptions=g(s);}
if(!allOptions.length){s=f.querySelectorAll('select[id*="Option"],select[name*="option"]');if(s.length){allOptions=g(s);}}
if(!allOptions.length){s=f.querySelectorAll('input[type="radio"][name*="option"]:checked');if(s.length){allOptions=g(s);}}
if(!allOptions.length){s=f.querySelectorAll('button.selected,button.active,.swatch-element.selected,.swatch.selected,[data-option-value].selected,[data-option-value].active');if(s.length){allOptions=g(s);}}
// Variant ID lookup as fallback
if(!allOptions.length){
const vid=f.querySelector('input[name="id"]')?.value||new URLSearchParams(window.location.search).get('variant');
if(d)console.log('[AB] VID:',vid,'Variants:',!!window._ABConfig?.product?.variants);
if(vid&&window._ABConfig?.product?.variants){
const v=window?._ABConfig?.product?.variants.find(x=>String(x.id)===String(vid));
if(v?.title&&v.title!=='Default Title'){
allOptions=v.title.split(' / ');
if(d)console.log('[AB] Found variant:',v.title);
}
}
}
// Update each product with only its relevant options
if(allOptions.length){
if(d)console.log('[AB] All options:',allOptions);
const spans=document.querySelectorAll('.ab-classic-bundle-product-variant-inline');
spans.forEach(span=>{
const optionIndices=span.getAttribute('data-option-indices');
if(optionIndices){
const indices=optionIndices.split(',').map(i=>parseInt(i));
const productOptions=indices.map(i=>allOptions[i]).filter(Boolean);
if(productOptions.length){
span.textContent=`(${productOptions.join(' / ')})`;
if(d)console.log('[AB] Updated product',span.getAttribute('data-product-id'),'with options:',productOptions);
}
}
});
}else if(d)console.warn('[AB] No options found');
}
if(blockElement&&!disableAppFunctionality){
blockElement.classList.add(`product-id-${productId}`);
executeClassicBundleBlock({blockElement,productId});
setupVariantDetection();
[100,300,500,1000].forEach(d=>setTimeout(updateVariantDisplay,d));
}
if(blockElements&&blockElements.length>0&&!disableAppFunctionality){
blockElements.forEach(e=>{
const pid=e?.getAttribute('data-product-id');
e.classList.add(`product-id-${pid}`);
executeClassicBundleBlock({blockElement:e,productId:pid});
});
setupVariantDetection();
[100,300,500,1000].forEach(d=>setTimeout(updateVariantDisplay,d));
}
});
})();