PageSourceSearch

https://samuraiswordtokyo.com/wp-content/themes/samurai-sword/assets/sticky-cart.8b1030f0dbd0.js?ver=0.1.0

js samuraiswordtokyo.com collected 2026-10-06 04:17:53 UTC 4,204 bytes, 90 lines download raw bytes

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.