PageSourceSearch

https://kavsanspizza.com/src/js/modules/floating_cart.js?v=1790256818

js kavsanspizza.com collected 2026-09-24 14:46:19 UTC 4,055 bytes, 90 lines download raw bytes

1// Global floating cart FAB — CI3 #cart_icon parity.
2//
3// Reveals a circular cart button (with an item-count badge) on every page once:
4//   1. the user is logged in (localStorage `userdata`), AND
5//   2. an outlet is selected and its cart (localStorage `v4_cart`) has items.
6//
7// The cart is outlet-scoped — `v4_cart.bId` is the selected outlet — so a cart
8// with items inherently means an outlet was chosen. Click proceeds to checkout
9// for that outlet, mirroring menu.js `goToCheckout()`.
10//
11// Stays hidden on pages that already carry their own cart entry point: the
12// menu/grocery page (#floatingCartBar) and the cart/checkout funnel.
13(function () {
14    const fab = document.getElementById('cartFab');
15    if (!fab) return;
16
17    // Pages with their own cart entry point — never show the global (menu) FAB
18    // there, or it overlaps and links to the wrong cart. The menu/order pages use
19    // one of two bar ids; subscription & prepaid-pack pages carry their own FAB
20    // (#subCartFab / #pkgCartFab) driven by their own server cart. The v2 header
21    // carries a cart button on every page ([data-hdr2-cart], count kept by
22    // headerV2.js), so brands on that header never need the FAB — and would
23    // otherwise show two cart entry points at once. No effect on v1 brands: the
24    // attribute only exists in templates/header_v2.php.
25    const hasOwnCartUi = !!(document.getElementById('floatingCartBar')
26        || document.getElementById('floatingCart')
27        || document.getElementById('subCartFab')
28        || document.getElementById('pkgCartFab')
29        || document.querySelector('[data-hdr2-cart]'));
30    // Cart funnel + the whole subscription/prepaid-pack section (list, VIEW, and
31    // checkout) — those run their own server cart, so the menu FAB must never show.
32    const onOwnRoute = /^\/(cart|checkout|payments-page|order-polling|subscriptions?|package|store-locator)\b/.test(location.pathname);
33    if (hasOwnCartUi || onOwnRoute) return;
34
35    function isLoggedIn() {
36        const ud = localStorage.getItem('userdata');
37        if (!ud || ud === 'null' || ud === '') return false;
38        try { return !!JSON.parse(ud); } catch { return false; }
39    }
40
41    function readCart() {
42        try {
43            const c = JSON.parse(localStorage.getItem('v4_cart') || 'null');
44            if (c && c.bId && Array.isArray(c.items)) return c;
45        } catch {}
46        return null;
47    }
48
49    function refresh() {
50        const cart = readCart();
51        const count = isLoggedIn() && cart
52            ? cart.items.reduce((s, i) => s + (i.qty || 0), 0)
53            : 0;
54        if (count > 0) {
55            const badge = document.getElementById('cartFabCount');
56            if (badge) badge.textContent = count > 99 ? '99+' : String(count);
57            fab.dataset.bid = String(cart.bId);
58            fab.hidden = false;
59        } else {
60            fab.hidden = true;
61        }
62    }
63
64    // Proceed to checkout for the cart's outlet (mirrors menu.js goToCheckout).
65    fab.addEventListener('click', function () {
66        const bId = fab.dataset.bid;
67        if (!bId) return;
68        if (!isLoggedIn()) { if (window.showLogin) window.showLogin(); return; }
69        const ot = localStorage.getItem('orderType') || '1';
70        const tid = localStorage.getItem('tableId');
71        if (ot === '3' && tid && tid !== 'null' && Number(tid) > 0) {
72            location.href = '/checkout/' + bId + '/' + ot + '/' + tid;
73        } else {
74            location.href = '/checkout/' + bId + '/' + ot;
75        }
76    });
77
78    // Re-evaluate on cross-tab changes, cart.js's event, and bfcache restores.
79    window.addEventListener('storage', function (e) {
80        if (!e.key || e.key === 'v4_cart' || e.key === 'userdata') refresh();
81    });
82    window.addEventListener('cart:updated', refresh);
83    window.addEventListener('pageshow', refresh);
84    window.addEventListener('focus', refresh);
85
86    // Allow same-page updaters to force a refresh after writing v4_cart.
87    window.refreshCartFab = refresh;
88
89    refresh();
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.