1(function () { 2 'use strict'; 3 function ready() { 4 if (!document.body.classList.contains('single-product') || document.querySelector('.sst-sticky-cart')) return; 5 var form = document.querySelector('form.cart'); 6 var mainBtn = form && form.querySelector('.single_add_to_cart_button'); 7 // An inquiry-only / unavailable product has no authoritative purchase action. 8 if (!form || !mainBtn) return; 9 10 var bar = document.createElement('div'); 11 bar.className = 'sst-sticky-cart'; 12 var info = document.createElement('span'); 13 info.className = 'sst-sticky-cart__info'; 14 var name = document.createElement('span'); 15 name.className = 'sst-sticky-cart__name'; 16 name.textContent = (document.querySelector('.product_title') || {}).textContent || ''; 17 var price = document.createElement('span'); 18 price.className = 'sst-sticky-cart__price'; 19 var btn = document.createElement('button'); 20 btn.type = 'button'; 21 btn.className = 'sst-sticky-cart__btn button'; 22 info.appendChild(name); 23 info.appendChild(price); 24 bar.appendChild(info); 25 bar.appendChild(btn); 26 document.body.appendChild(bar); 27 28 var frame = 0; 29 function sync() { 30 frame = 0; 31 mainBtn = form.querySelector('.single_add_to_cart_button'); 32 if (!mainBtn || !document.contains(form)) { 33 bar.classList.remove('is-visible'); 34 btn.disabled = true; 35 return; 36 } 37 // WooCommerce owns variation and stock eligibility, including its disabled 38 // classes. The sticky control mirrors it instead of deriving a new price rule. 39 btn.disabled = mainBtn.disabled || mainBtn.classList.contains('disabled') || mainBtn.classList.contains('loading'); 40 var label = mainBtn.textContent.trim(); 41 if (btn.textContent !== label) btn.textContent = label; 42 var selectedPrice = form.querySelector('.woocommerce-variation-price .price'); 43 var summaryPrice = document.querySelector('div.product .summary .price, div.product p.price'); 44 var nextPrice = (selectedPrice || summaryPrice || {}).innerHTML || ''; 45 if (price.innerHTML !== nextPrice) price.innerHTML = nextPrice; 46 var rect = mainBtn.getBoundingClientRect(); 47 var viewport = window.visualViewport; 48 var top = viewport ? viewport.offsetTop : 0; 49 var bottom = top + (viewport ? viewport.height : window.innerHeight); 50 var available = mainBtn.getClientRects().length > 0 && getComputedStyle(mainBtn).visibility !== 'hidden'; 51 bar.classList.toggle('is-visible', available && (rect.bottom <= top || rect.top >= bottom)); 52 } 53 function schedule() { 54 if (!frame) frame = window.requestAnimationFrame(sync); 55 } 56 57 btn.addEventListener('click', function () { 58 sync(); 59 if (btn.disabled || !mainBtn) return; 60 // Use the exact main action: variations, quantity constraints, extension 61 // fields, native validation, AJAX handlers and server notices stay together. 62 if (typeof form.reportValidity === 'function' && !form.reportValidity()) { 63 form.scrollIntoView({ block: 'center', behavior: 'smooth' }); 64 return; 65 } 66 mainBtn.click(); 67 schedule(); 68 }); 69 70 form.addEventListener('change', schedule); 71 form.addEventListener('input', schedule); 72 window.addEventListener('scroll', schedule, { passive: true }); 73 window.addEventListener('resize', schedule, { passive: true }); 74 window.addEventListener('pageshow', schedule); 75 if (window.visualViewport) { 76 window.visualViewport.addEventListener('resize', schedule, { passive: true }); 77 window.visualViewport.addEventListener('scroll', schedule, { passive: true }); 78 } 79 if (window.MutationObserver) { 80 new MutationObserver(schedule).observe(form.closest('.summary') || form, { 81 subtree: true, childList: true, characterData: true, 82 attributes: true, attributeFilter: ['class', 'disabled', 'hidden', 'style'] 83 }); 84 } 85 if (window.jQuery) window.jQuery(form).on('found_variation reset_data hide_variation show_variation', schedule); 86 sync(); 87 } 88 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', ready, { once: true }); 89 else ready(); 90})();
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.