 {"id":10264,"date":"2025-04-04T17:46:44","date_gmt":"2025-04-04T15:46:44","guid":{"rendered":"https:\/\/printafrique.com\/?post_type=product&#038;p=10264"},"modified":"2025-07-10T12:50:02","modified_gmt":"2025-07-10T10:50:02","slug":"rainbow-banner","status":"publish","type":"product","link":"https:\/\/printafrique.com\/?product=rainbow-banner","title":{"rendered":"Rain Bow Banner Complete + Frame (6.5*4) (excl. VAT)"},"content":{"rendered":"\t\t<div data-elementor-type=\"product-post\" data-elementor-id=\"10264\" class=\"elementor elementor-10264\" data-elementor-post-type=\"product\">\n\t\t\t\t        <section class=\"elementor-section elementor-top-section elementor-element elementor-element-48f98e5 elementor-section-boxed elementor-section-height-default elementor-section-height-default pxl-type-header-none pxl-bg-color-none pxl-row-scroll-none\" data-id=\"48f98e5\" data-element_type=\"section\">\n\n                \n                <div class=\"elementor-container elementor-column-gap-default \">\n                <div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-734e5d62 pxl-col-none pxl-column-none\" data-id=\"734e5d62\" data-element_type=\"column\">\r\n        <div class=\"elementor-widget-wrap elementor-element-populated\">\r\n                     \r\n        \t\t<div class=\"elementor-element elementor-element-76db968a elementor-widget elementor-widget-text-editor\" data-id=\"76db968a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<div class=\"specs-widget\" style=\"border-radius: 12px; padding: 16px; max-width: 500px; font-family: sans-serif;\">\r\n<div class=\"widget-header\" style=\"font-size: 20px; font-weight: bold; margin-bottom: 12px;\">Specifications<\/div>\r\n<div class=\"widget-section\" style=\"margin-bottom: 10px;\">\r\n<div class=\"label\" style=\"font-weight: bold;\">Dimensions:<\/div>\r\n<div class=\"value\">Standard sizes available; custom dimensions can be provided upon request.<\/div>\r\n<\/div>\r\n<div class=\"widget-section\" style=\"margin-bottom: 10px;\">\r\n<div class=\"label\" style=\"font-weight: bold;\">Material:<\/div>\r\n<div class=\"value\">High-quality, fade-resistant vinyl or fabric.<\/div>\r\n<\/div>\r\n<div class=\"widget-section\" style=\"margin-bottom: 10px;\">\r\n<div class=\"label\" style=\"font-weight: bold;\">Weight:<\/div>\r\n<div class=\"value\">Lightweight for easy handling and portability.<\/div>\r\n<\/div>\r\n<div class=\"widget-section\">\r\n<div class=\"label\" style=\"font-weight: bold;\">Finishing:<\/div>\r\n<div class=\"value\">Reinforced edges with pre-installed grommets or pole pockets for secure installation.<\/div>\r\n<\/div>\r\n<\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t            <\/div>\r\n        <\/div>\r\n        \t\t\t<\/div>\n\t\t<\/section>\n\t\t        <section class=\"elementor-section elementor-top-section elementor-element elementor-element-34ccf50 elementor-section-boxed elementor-section-height-default elementor-section-height-default pxl-type-header-none pxl-bg-color-none pxl-row-scroll-none\" data-id=\"34ccf50\" data-element_type=\"section\">\n\n                \n                <div class=\"elementor-container elementor-column-gap-default \">\n                <div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4b2661f pxl-col-none pxl-column-none\" data-id=\"4b2661f\" data-element_type=\"column\">\r\n        <div class=\"elementor-widget-wrap elementor-element-populated\">\r\n                     \r\n        \t\t<div class=\"elementor-element elementor-element-2046bf1 elementor-widget elementor-widget-html\" data-id=\"2046bf1\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\n    jQuery(function ($) {\n    'use strict';\n\n    \/\/ Check if the localized parameters object exists\n    if (typeof wcdpu_params === 'undefined') {\n        console.error('WCDPU Error: Localized parameters not found.');\n        return;\n    }\n\n    \/\/ Selectors from localized parameters\n    const qtySelector = wcdpu_params.qtySelector || 'input.qty';\n    const priceHolderSelector = wcdpu_params.priceHolderSelector || '.product .price';\n\n    \/\/ Find the quantity input and price holder\n    const $qtyInput = $(qtySelector).first(); \/\/ Assuming one main qty input per product page\n    const $priceHolder = $(priceHolderSelector).first(); \/\/ Target the first price element\n\n    \/\/ Basic validation\n    if (!$qtyInput.length) {\n        \/\/ console.log('WCDPU Info: Quantity input not found on this page.');\n        return; \/\/ Exit if no quantity input found\n    }\n    if (!$priceHolder.length) {\n        console.warn('WCDPU Warning: Price holder element not found using selector:', priceHolderSelector);\n        return; \/\/ Exit if no price holder found\n    }\n    if (typeof wcdpu_params.basePrice === 'undefined' || wcdpu_params.basePrice === null) {\n        \/\/ console.log('WCDPU Info: Base price not available (possibly variable product).');\n        return; \/\/ Exit if no base price provided (e.g., for variable products before selection)\n    }\n\n    \/\/ Store the original price HTML (including currency symbol, etc.)\n    const originalPriceHTML = $priceHolder.html();\n    \/\/ Store the base price from localized params\n    const basePrice = parseFloat(wcdpu_params.basePrice);\n\n    if (isNaN(basePrice)) {\n        console.error('WCDPU Error: Invalid base price received:', wcdpu_params.basePrice);\n        return;\n    }\n\n    \/\/ --- Price Formatting Function (mimics wc_price) ---\n    function formatPrice(price) {\n        const numDecimals = parseInt(wcdpu_params.numberOfDecimals, 10);\n        const decimalSeparator = wcdpu_params.decimalSeparator;\n        const thousandSeparator = wcdpu_params.thousandSeparator;\n        const currencySymbol = wcdpu_params.currencySymbol;\n        const currencyPos = wcdpu_params.currencyPos;\n\n        let formattedPrice = parseFloat(price).toFixed(numDecimals);\n        formattedPrice = formattedPrice.replace('.', decimalSeparator);\n\n        \/\/ Add thousand separators (basic implementation)\n        let parts = formattedPrice.split(decimalSeparator);\n        parts[0] = parts[0].replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, thousandSeparator);\n        formattedPrice = parts.join(decimalSeparator);\n\n        let priceString;\n        switch (currencyPos) {\n            case 'left':\n                priceString = currencySymbol + formattedPrice;\n                break;\n            case 'right':\n                priceString = formattedPrice + currencySymbol;\n                break;\n            case 'left_space':\n                priceString = currencySymbol + ' ' + formattedPrice;\n                break;\n            case 'right_space':\n                priceString = formattedPrice + ' ' + currencySymbol;\n                break;\n            default:\n                priceString = currencySymbol + formattedPrice;\n        }\n\n        \/\/ Wrap in standard WooCommerce price amount span\n        return '<span class=\"woocommerce-Price-amount amount\"><bdi>' + priceString + '<\/bdi><\/span>';\n    }\n\n    \/\/ --- Event Listener --- \/\/\n    function updatePrice() {\n        console.log('WCDPU: updatePrice function started.');\n        const qty = parseFloat($qtyInput.val());\n        console.log('WCDPU: Quantity read:', qty);\n\n        \/\/ Validate quantity\n        if (isNaN(qty) || qty <= 0) {\n            console.log('WCDPU: Invalid quantity (' + qty + '), reverting or doing nothing.');\n             \/\/ Optionally revert to original price or show nothing if qty is invalid\/zero\n             \/\/ Let's revert to original for now if qty is 0 or less\n             if(qty <= 0) {\n                 $priceHolder.html(originalPriceHTML);\n             } else {\n                 \/\/ If NaN (e.g., empty input), maybe keep current price or revert?\n                 \/\/ Reverting might be confusing. Let's just do nothing if NaN.\n             }\n             return;\n        }\n\n        \/\/ Calculate new price\n        const newPrice = basePrice * qty;\n        console.log('WCDPU: Calculated new price:', newPrice);\n\n        \/\/ Format the new price\n        const formattedNewPrice = formatPrice(newPrice);\n        console.log('WCDPU: Formatted new price:', formattedNewPrice);\n\n        \/\/ Update the price display\n        \/\/ Replace the entire content of the price holder for simplicity\n        console.log('WCDPU: Attempting to update HTML for:', $priceHolder);\n        $priceHolder.html(formattedNewPrice);\n        console.log('WCDPU: HTML update complete.');\n    }\n\n    \/\/ Attach event listener using event delegation on a static parent (document)\n    \/\/ This ensures the listener works even if the input element is replaced\/modified by other scripts.\n    $(document).on('input change', qtySelector, function(event) {\n        \/\/ --- NEW DEBUG LOG --- \/\/\n        console.log('WCDPU: Delegated event fired! Type:', event.type, 'Target:', event.target);\n        \/\/ --- END NEW DEBUG LOG --- \/\/\n\n        \/\/ Note: Inside the delegated event handler, 'this' refers to the quantity input\n        \/\/ that triggered the event. We still use the cached $qtyInput and $priceHolder\n        \/\/ found earlier, assuming there's only one main price\/qty block targeted.\n        \/\/ If multiple blocks existed, we'd need to find the relevant $priceHolder relative to 'this'.\n        updatePrice();\n    });\n\n    \/\/ --- NEW: Listen for clicks on theme's +\/- buttons ---\n    \/\/ These buttons often change the input value programmatically without triggering 'input' or 'change'\n    \/\/ So, we listen for clicks on them and then trigger the 'change' event on the input ourselves.\n    $(document).on('click', '.quantity .quantity-up, .quantity .quantity-down', function() {\n        \/\/ 'this' is the clicked icon (<i>)\n        \/\/ Find the quantity input field related to the clicked button\n        const $relatedQtyInput = $(this).closest('.quantity').find(qtySelector);\n\n        \/\/ Check if we found the input\n        if ($relatedQtyInput.length) {\n            \/\/ Use a tiny timeout to ensure the input's value has likely been updated by the theme's JS\n            setTimeout(function() {\n                \/\/ Manually trigger the 'change' event on the input field\n                $relatedQtyInput.trigger('change');\n                console.log('WCDPU: Triggered change after icon click'); \/\/ Debug log\n            }, 50); \/\/ 50ms delay\n        }\n    });\n    \/\/ --- END NEW --- \/\/\n\n    \/\/ Initial update in case the quantity is pre-filled with > 1 or for initial setup.\n    \/\/ Find the input again and trigger the 'change' event on it to run the updatePrice once.\n    $(qtySelector).first().trigger('change');\n\n    \/\/ --- Handling Variations --- \/\/\n    \/\/ A more robust solution would also listen for variation changes\n    \/\/ This requires finding the variation price and updating the basePrice accordingly\n    \/\/ Example (requires careful adaptation to theme structure):\n    \/\/ $(document).on('found_variation', 'form.variations_form', function(event, variation) {\n    \/\/     if (variation && variation.display_price) {\n    \/\/         basePrice = parseFloat(variation.display_price);\n    \/\/         updatePrice(); \/\/ Update price based on new variation price and current quantity\n    \/\/     } else {\n    \/\/         \/\/ Variation not found or no price, revert to original\/placeholder\n    \/\/         $priceHolder.html(originalPriceHTML); \/\/ Or show a 'select options' message\n    \/\/         basePrice = null; \/\/ Reset base price\n    \/\/     }\n    \/\/ });\n\n    \/\/ \/\/ Handle reset when variation is cleared\n    \/\/ $(document).on('reset_data', 'form.variations_form', function() {\n    \/\/     $priceHolder.html(originalPriceHTML); \/\/ Revert to original price display\n    \/\/     basePrice = parseFloat(wcdpu_params.basePrice); \/\/ Reset to initial base price if available\n    \/\/ });\n\n}); \n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t            <\/div>\r\n        <\/div>\r\n        \t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p class=\"\" data-start=\"0\" data-end=\"300\">The Rainbow Banner is a vibrant display solution designed to infuse energy and positivity into any space. Featuring a seamless gradient of colors, this banner is perfect for events, celebrations, and promotional displays where a burst of creativity and diversity is needed.<\/p>\n<p class=\"\" data-start=\"302\" data-end=\"321\">\n","protected":false},"featured_media":10260,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"product_brand":[],"product_cat":[31,32],"product_tag":[],"class_list":{"0":"post-10264","1":"product","2":"type-product","3":"status-publish","4":"has-post-thumbnail","6":"product_cat-banners-banner-walls","7":"product_cat-flags","9":"first","10":"instock","11":"shipping-taxable","12":"purchasable","13":"product-type-simple"},"_links":{"self":[{"href":"https:\/\/printafrique.com\/index.php?rest_route=\/wp\/v2\/product\/10264","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/printafrique.com\/index.php?rest_route=\/wp\/v2\/product"}],"about":[{"href":"https:\/\/printafrique.com\/index.php?rest_route=\/wp\/v2\/types\/product"}],"replies":[{"embeddable":true,"href":"https:\/\/printafrique.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10264"}],"version-history":[{"count":21,"href":"https:\/\/printafrique.com\/index.php?rest_route=\/wp\/v2\/product\/10264\/revisions"}],"predecessor-version":[{"id":10458,"href":"https:\/\/printafrique.com\/index.php?rest_route=\/wp\/v2\/product\/10264\/revisions\/10458"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/printafrique.com\/index.php?rest_route=\/wp\/v2\/media\/10260"}],"wp:attachment":[{"href":"https:\/\/printafrique.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10264"}],"wp:term":[{"taxonomy":"product_brand","embeddable":true,"href":"https:\/\/printafrique.com\/index.php?rest_route=%2Fwp%2Fv2%2Fproduct_brand&post=10264"},{"taxonomy":"product_cat","embeddable":true,"href":"https:\/\/printafrique.com\/index.php?rest_route=%2Fwp%2Fv2%2Fproduct_cat&post=10264"},{"taxonomy":"product_tag","embeddable":true,"href":"https:\/\/printafrique.com\/index.php?rest_route=%2Fwp%2Fv2%2Fproduct_tag&post=10264"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}