const nameRaw = txt.slice(0, txt.indexOf('

Store Details

191 Ottawa St. N

Location map

191 Ottawa St. N

Hamilton, ON L8H 3z4

Hamilton

HOURS OF OPERATION

Mon: 10:00 am - 10:00 pm
Tue: 10:00 am - 10:00 pm
Wed: 10:00 am - 10:00 pm
Thu: 10:00 am - 10:00 pm
Fri: 10:00 am - 12:00 am
Sat: 10:00 am - 12:00 am
Sun: 10:00 am - 10:00 pm
INTRODUCING
Zero Contact Delivery & PICKUP
All delivery and pickup orders are now contactless to help keep everyone safe and healthy. Please choose to pay online for a smooth contactless experience. All the orders paid online will be contactless be delivered contactless. Thank you!
)).replace(/\s+/g, ' ').trim(); const cleaned = nameRaw.replace(/\b\d+\b\s*$/, '').trim(); // strip trailing qty digit if (cleaned) { items.push({ name: cleaned.slice(0, 120), price: parseFloat(priceMatch[1]) || 0, qty: Math.min(99, v), opts: '', }); return; } } row = row.parentElement; depth++; } }); return items; } // Try to extract product details from a pizza page or simple product page. // For add-on pages (drinks/dips/salads) returns an ARRAY of items, one per // row whose qty > 0. For pizza pages returns a single item. function extractCurrentProduct() { // Add-on pages with multiple qty rows. if (/^\/orders\/additional_items/i.test(location.pathname)) { const addOns = extractAddOnItems(); if (addOns.length) return addOns; } const h1 = document.querySelector('h1, h2.product-title, .product-name, .product_name'); let name = (document.title || '').replace(/\s*\|.*$/, '').trim() || (h1 && h1.textContent.trim()) || 'Item'; let price = 0; const opts = []; const sizeRadio = document.querySelector('input[name="product[pizza_size]"]:checked, input[type=radio][name*=size]:checked'); if (sizeRadio) { const lbl = sizeRadio.closest('label, .radio') || sizeRadio.parentElement; const txt = (lbl && lbl.textContent || ''); const m = txt.match(/\$\s*(\d+(?:\.\d{2})?)/); if (m) price = parseFloat(m[1]); const sm = txt.match(/^[^$]*?(?=\s*\$)/); if (sm) opts.push('Size: ' + sm[0].replace(/\s+/g,' ').trim()); } if (!price) { const ptxt = document.body.textContent || ''; const m = ptxt.match(/\$\s*(\d+\.\d{2})/); if (m) price = parseFloat(m[1]); } const qtyInput = document.querySelector('input[name="product[quantity]"], input[name=quantity], #quantity'); const qty = Math.max(1, parseInt((qtyInput && qtyInput.value) || '1', 10) || 1); return { name, price, opts: opts.join(', '), qty }; } function bindAddButtons() { document.querySelectorAll('button, input[type=submit], a').forEach(btn => { if (btn.dataset.lcBound) return; const t = (btn.textContent || btn.value || '').trim().toUpperCase(); if (t === 'ADD TO ORDER' || t === 'ADD TO CART' || t === 'ORDER ONE NOW.') { btn.dataset.lcBound = '1'; btn.addEventListener('click', async (e) => { // Pause navigation/submit so that our /local-cart/add request // actually reaches the server before the page unloads. Otherwise // the in-flight fetch is aborted and the cart stays empty. let resumed = false; const target = btn; const form = target.form || target.closest('form'); const href = target.tagName === 'A' ? target.getAttribute('href') : null; const isNavLike = !!form || (href && href !== '#' && !href.startsWith('javascript:')); if (isNavLike) { e.preventDefault(); e.stopPropagation(); } const resume = () => { if (resumed) return; resumed = true; if (!isNavLike) return; try { if (form) { // Submit without re-triggering our handler HTMLFormElement.prototype.submit.call(form); } else if (href) { window.location.href = href; } } catch(_) {} }; try { const extracted = extractCurrentProduct(); const items = Array.isArray(extracted) ? extracted : (extracted && extracted.name ? [extracted] : []); for (const item of items) { // keepalive lets the request survive a navigation as a fallback await fetch('/local-cart/add', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(item), keepalive: true, }); await syncCart(); } } catch(_) {} resume(); }, true); } }); } // Origin is the source of truth for removals. We reconcile in two ways: // 1) On the cart page (/orders/details), if origin shows "empty cart" // text/markup, force-clear the local cart. // 2) On any page, if origin's badge value is SMALLER than our local count // (user removed items elsewhere), trim the local cart to match. async function reconcileWithDomBadge() { // (1) Empty cart on the order details page → wipe local cart. if (/^\/orders\/details(\b|\/|$)/.test(location.pathname)) { const bodyText = (document.body && document.body.textContent || '').toLowerCase(); const looksEmpty = /please add items to your order|your cart is empty|here.s your order enjoy/.test(bodyText) && !document.querySelector('[id*="order_item_"], .order_item, .order-item, tr.cart_item'); if (looksEmpty && __lastCount > 0) { try { await fetch('/local-cart/clear', { method: 'POST', credentials: 'include' }); await syncCart(); } catch(_) {} return; } } // (2) Smaller badge → trim local cart down. const badges = document.querySelectorAll('.cart-item-counter'); if (!badges.length) return; let domCount = NaN; badges.forEach(el => { const n = parseInt((el.textContent || '').trim(), 10); if (Number.isFinite(n)) { if (!Number.isFinite(domCount) || n < domCount) domCount = n; } }); if (!Number.isFinite(domCount)) return; if (domCount < __lastCount) { try { await fetch('/local-cart/trim', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ count: domCount }), }); await syncCart(); } catch(_) {} } } function init() { rewriteCheckoutLinks(); bindAddButtons(); syncCart().then(reconcileWithDomBadge); // Watch DOM mutations — Pizzaiolo updates parts of the page via XHR // and may reset the cart counter to 0 after our sync. Re-apply on changes, // BUT only when origin's value is greater-or-equal to ours; if origin // shows a smaller number (user removed items), trust origin and reconcile. const mo = new MutationObserver(() => { if (__suppressMO) return; rewriteCheckoutLinks(); bindAddButtons(); document.querySelectorAll('.cart-item-counter').forEach(el => { const txt = (el.textContent || '').trim(); const n = parseInt(txt, 10); if (Number.isFinite(n) && n < __lastCount) { // Origin lowered the badge — likely user removed an item. Reconcile. reconcileWithDomBadge(); return; } const s = String(__lastCount); if (el.textContent !== s) { __suppressMO = true; el.textContent = s; __suppressMO = false; } }); }); mo.observe(document.documentElement, { childList: true, subtree: true }); // Re-sync on tab focus / bfcache restore. window.addEventListener('pageshow', () => { syncCart().then(reconcileWithDomBadge); }); window.addEventListener('focus', () => { syncCart().then(reconcileWithDomBadge); }); } if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); else init(); })();

Store Details

191 Ottawa St. N

Location map

191 Ottawa St. N

Hamilton, ON L8H 3z4

Hamilton

HOURS OF OPERATION

Mon: 10:00 am - 10:00 pm
Tue: 10:00 am - 10:00 pm
Wed: 10:00 am - 10:00 pm
Thu: 10:00 am - 10:00 pm
Fri: 10:00 am - 12:00 am
Sat: 10:00 am - 12:00 am
Sun: 10:00 am - 10:00 pm
INTRODUCING
Zero Contact Delivery & PICKUP
All delivery and pickup orders are now contactless to help keep everyone safe and healthy. Please choose to pay online for a smooth contactless experience. All the orders paid online will be contactless be delivered contactless. Thank you!