1/** 2 * Matrix BOGO â Gift Popup JS 3 * Manages the gift-selector modal on cart/checkout pages. 4 */ 5/* global matrixBogoFrontend */ 6(function ($) { 7 'use strict'; 8 9 const $popup = $('#matrix-bogo-gift-popup'); 10 const $overlay = $popup.find('.matrix-bogo-popup-overlay'); 11 const $products = $popup.find('#matrix-bogo-popup-products'); 12 const $addBtn = $popup.find('#matrix-bogo-popup-add-btn'); 13 14 let currentRuleId = null; 15 let currentNonce = null; 16 17 // ââ Open popup if choice gifts exist ââââââââââââââââââââââââââââ 18 19 function maybeOpenPopup() { 20 if (!$popup.length) return; 21 if (!matrixBogoFrontend.hasChoiceGifts) return; 22 23 // Avoid re-showing if already dismissed this session. 24 if (sessionStorage.getItem('matrix_bogo_popup_dismissed')) return; 25 26 openPopup(matrixBogoFrontend.choiceRuleId, matrixBogoFrontend.nonce); 27 } 28 29 function openPopup(ruleId, nonce) { 30 currentRuleId = ruleId; 31 currentNonce = nonce; 32 loadGiftProducts(ruleId, nonce); 33 $popup.fadeIn(200).attr('aria-hidden', 'false'); 34 $('body').addClass('matrix-bogo-popup-open'); 35 } 36 37 function closePopup() { 38 $popup.fadeOut(200).attr('aria-hidden', 'true'); 39 $('body').removeClass('matrix-bogo-popup-open'); 40 sessionStorage.setItem('matrix_bogo_popup_dismissed', '1'); 41 } 42 43 // ââ Load gift product options ââââââââââââââââââââââââââââââââââââ 44 45 function loadGiftProducts(ruleId, nonce) { 46 $products.html('<div class="matrix-bogo-popup-loading"><span class="spinner is-active"></span></div>'); 47 48 $.post(matrixBogoFrontend.ajaxUrl, { 49 action: 'matrix_bogo_search_gifts', 50 nonce, 51 rule_id: ruleId, 52 }).done(function (res) { 53 if (!res.success || !res.data.products.length) { 54 $products.html('<p>' + matrixBogoFrontend.i18n.noGifts + '</p>'); 55 return; 56 } 57 renderProducts(res.data.products); 58 }).fail(function () { 59 $products.html('<p>' + matrixBogoFrontend.i18n.error + '</p>'); 60 }); 61 } 62 63 function renderProducts(products) { 64 let html = '<div class="matrix-bogo-gift-products">'; 65 products.forEach(function (p) { 66 html += ` 67 <div class="matrix-bogo-gift-item"> 68 <label> 69 <input type="radio" name="matrix_bogo_popup_choice" 70 value="${p.id}" data-quantity="1"> 71 <img src="${p.thumbnail}" alt="${p.name}" width="80"> 72 <span class="matrix-bogo-gift-name">${p.name}</span> 73 <span class="matrix-bogo-gift-free-label">${matrixBogoFrontend.i18n.free}</span> 74 </label> 75 </div>`; 76 }); 77 html += '</div>'; 78 $products.html(html); 79 } 80 81 // ââ Add selected gift ââââââââââââââââââââââââââââââââââââââââââââ 82 83 $addBtn.on('click', function () { 84 const $checked = $products.find('input[type="radio"]:checked'); 85 if (!$checked.length) { 86 alert(matrixBogoFrontend.i18n.selectGift); 87 return; 88 } 89 90 const productId = $checked.val(); 91 const quantity = $checked.data('quantity') || 1; 92 93 $addBtn.prop('disabled', true); 94 95 $.post(matrixBogoFrontend.ajaxUrl, { 96 action: 'matrix_bogo_apply_gift', 97 nonce: currentNonce, 98 rule_id: currentRuleId, 99 product_id: productId, 100 quantity, 101 }).done(function (res) { 102 if (res.success) { 103 $(document.body).trigger('wc_fragment_refresh'); 104 closePopup(); 105 } else { 106 alert(res.data.message || matrixBogoFrontend.i18n.error); 107 $addBtn.prop('disabled', false); 108 } 109 }); 110 }); 111 112 // ââ Enable Add button when a product is selected âââââââââââââââââ 113 114 $(document).on('change', '#matrix-bogo-popup-products input[type="radio"]', function () { 115 $addBtn.prop('disabled', false); 116 }); 117 118 // ââ Close handlers ââââââââââââââââââââââââââââââââââââââââââââââ */ 119 120 $popup.find('.matrix-bogo-popup-close, .matrix-bogo-popup-skip').on('click', closePopup); 121 $overlay.on('click', closePopup); 122 123 $(document).on('keydown', function (e) { 124 if (e.key === 'Escape') closePopup(); 125 }); 126 127 // ââ Init âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 128 129 $(function () { 130 // Small delay so cart fragments have loaded. 131 setTimeout(maybeOpenPopup, 800); 132 }); 133 134})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.