Files
repa-woocommerce/theme/js/rar.js

312 lines
13 KiB
JavaScript

/**
* Reply All Regrets — Interactive features
* Filter sidebar, sort, view toggle, gallery switcher, qty controls
*/
(function () {
'use strict';
// ─── Gallery switcher ────────────────────────────────────────────────────
window.rarSwitchGallery = function (index, url) {
var img = document.getElementById('rar-gallery-img');
var counter = document.getElementById('rar-gallery-counter');
var label = document.getElementById('rar-gallery-label');
var thumbs = document.querySelectorAll('.rar-gallery__thumb');
if (img) img.src = url;
if (counter) counter.textContent = index + 1;
if (label) label.textContent = 'FIG. ' + (index + 1) + ' — PRODUCT VIEW';
thumbs.forEach(function (t, i) {
t.classList.toggle('active', i === index);
});
};
// ─── Grid / List view toggle ─────────────────────────────────────────────
window.rarSetView = function (view) {
var grid = document.getElementById('rar-product-grid');
var gridBtn = document.getElementById('rar-grid-btn');
var listBtn = document.getElementById('rar-list-btn');
if (!grid) return;
if (view === 'list') {
grid.classList.add('list-view');
if (gridBtn) gridBtn.classList.remove('active');
if (listBtn) listBtn.classList.add('active');
} else {
grid.classList.remove('list-view');
if (gridBtn) gridBtn.classList.add('active');
if (listBtn) listBtn.classList.remove('active');
}
try { localStorage.setItem('rar-view', view); } catch (e) {}
};
// Restore saved view preference
(function () {
try {
var saved = localStorage.getItem('rar-view');
if (saved === 'list') { rarSetView('list'); }
} catch (e) {}
})();
// ─── Sort menu close on outside click ────────────────────────────────────
document.addEventListener('click', function (e) {
var sortMenu = document.getElementById('rar-sort-menu');
var sortBtn = document.querySelector('.rar-sort-btn');
if (sortMenu && !sortMenu.contains(e.target) && sortBtn && !sortBtn.contains(e.target)) {
sortMenu.classList.remove('open');
}
});
// ─── Filter: category/attribute ──────────────────────────────────────────
window.rarApplyFilter = function (checkbox) {
var url = new URL(window.location.href);
if (checkbox.checked) {
url.searchParams.set(checkbox.name, checkbox.value);
} else {
url.searchParams.delete(checkbox.name);
}
window.location.href = url.toString();
};
window.rarPriceFilter = function (checkbox) {
var url = new URL(window.location.href);
// Uncheck siblings
document.querySelectorAll('[id^="price-"]').forEach(function (c) {
if (c !== checkbox) c.checked = false;
});
if (checkbox.checked) {
url.searchParams.set('min_price', checkbox.dataset.min);
url.searchParams.set('max_price', checkbox.dataset.max);
} else {
url.searchParams.delete('min_price');
url.searchParams.delete('max_price');
}
window.location.href = url.toString();
};
window.rarStockFilter = function (checkbox) {
var url = new URL(window.location.href);
if (checkbox.checked) {
url.searchParams.set('availability', 'instock');
} else {
url.searchParams.delete('availability');
}
window.location.href = url.toString();
};
window.rarApplyAllFilters = function () {
// Collect all checked filters and navigate
var url = new URL(window.location.href);
document.querySelectorAll('.rar-filter-item input[type=checkbox]:checked').forEach(function (c) {
if (c.name && c.value) url.searchParams.set(c.name, c.value);
});
window.location.href = url.toString();
};
// ─── Designs index: tag filter ──────────────────────────────────────────
window.rarFilterDesigns = function (tag, btn) {
var cards = document.querySelectorAll('[data-design-tag]');
var buttons = document.querySelectorAll('.rar-design-filter-btn');
buttons.forEach(function (b) { b.classList.remove('active'); });
btn.classList.add('active');
cards.forEach(function (card) {
if (tag === 'All' || card.dataset.designTag === tag) {
card.style.display = '';
} else {
card.style.display = 'none';
}
});
};
// ─── Qty controls ────────────────────────────────────────────────────────
document.addEventListener('click', function (e) {
if (e.target.matches('.rar-qty__btn')) {
var wrap = e.target.closest('.rar-qty');
if (!wrap) return;
var display = wrap.querySelector('.rar-qty__val');
var input = wrap.querySelector('input[type=number], input.qty');
var current = parseInt(display ? display.textContent : (input ? input.value : 1)) || 1;
if (e.target.dataset.action === 'plus') {
current++;
} else if (e.target.dataset.action === 'minus') {
current = Math.max(1, current - 1);
}
if (display) display.textContent = current;
if (input) {
input.value = current;
input.dispatchEvent(new Event('change', { bubbles: true }));
}
}
});
// ─── Nav: highlight current section ──────────────────────────────────────
(function () {
var path = window.location.pathname;
var links = document.querySelectorAll('.rar-nav__links a');
links.forEach(function (link) {
var href = link.getAttribute('href') || '';
if (href && href !== '/' && path.indexOf(href) === 0) {
link.style.color = 'var(--stamp)';
}
});
})();
// ─── Cart count update via WooCommerce fragments ──────────────────────────
document.addEventListener('wc_fragments_refreshed', function () {
// WooCommerce will update .rar-nav__cart via the fragments filter in functions.php
});
// ─── Announcement bar close ───────────────────────────────────────────────
var bar = document.querySelector('.rar-bar');
if (bar) {
bar.style.cursor = 'pointer';
bar.title = 'Click to dismiss';
bar.addEventListener('click', function () {
bar.style.display = 'none';
try { sessionStorage.setItem('rar-bar-dismissed', '1'); } catch (e) {}
});
try {
if (sessionStorage.getItem('rar-bar-dismissed') === '1') bar.style.display = 'none';
} catch (e) {}
}
// ─── Mobile nav drawer toggle ────────────────────────────────────────────────
window.rarToggleNav = function () {
var nav = document.getElementById('rar-nav');
var drawer = document.getElementById('rar-nav-drawer');
var toggle = document.getElementById('rar-nav-toggle');
if (!drawer) return;
var isOpen = drawer.classList.contains('is-open');
drawer.classList.toggle('is-open', !isOpen);
if (nav) nav.classList.toggle('is-open', !isOpen);
if (toggle) toggle.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
document.body.style.overflow = isOpen ? '' : 'hidden';
};
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') {
var drawer = document.getElementById('rar-nav-drawer');
if (drawer && drawer.classList.contains('is-open')) { rarToggleNav(); }
}
});
// ─── Search overlay toggle ───────────────────────────────────────────────────
window.rarToggleSearch = function () {
var overlay = document.getElementById('rar-search-overlay');
var btn = document.getElementById('rar-search-toggle');
if (!overlay) return;
var isHidden = overlay.hidden;
overlay.hidden = !isHidden;
if (btn) btn.setAttribute('aria-expanded', isHidden ? 'true' : 'false');
if (isHidden) {
var input = overlay.querySelector('input[type=search]');
if (input) { input.focus(); input.select(); }
}
};
// Close search overlay on Escape key
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') {
var overlay = document.getElementById('rar-search-overlay');
if (overlay && !overlay.hidden) {
overlay.hidden = true;
var btn = document.getElementById('rar-search-toggle');
if (btn) { btn.setAttribute('aria-expanded', 'false'); btn.focus(); }
}
}
});
// ─── Newsletter form submit ────────────────────────────────────────────────
window.rarNewsletterSubmit = function (e, form) {
e.preventDefault();
var emailInput = form.querySelector('input[type=email]');
if (!emailInput || !emailInput.value) return false;
var btn = form.querySelector('button[type=submit]');
var emailVal = emailInput.value;
if (btn) { btn.textContent = 'Filing…'; btn.disabled = true; }
var data = new FormData();
data.append('action', 'rar_subscribe');
data.append('email', emailVal);
data.append('nonce', (typeof rarData !== 'undefined' && rarData.nonce) ? rarData.nonce : '');
fetch((typeof rarData !== 'undefined' && rarData.ajaxUrl) ? rarData.ajaxUrl : '/wp-admin/admin-ajax.php', {
method: 'POST',
body: data
})
.then(function (r) { return r.json(); })
.catch(function () { return { success: true }; })
.finally(function () {
var wrapper = form.closest('.rar-footer__newsletter') || form.parentNode;
var msg = document.createElement('p');
msg.className = 'rar-newsletter-success';
msg.style.cssText = 'margin:12px 0 0;font-family:var(--mono);font-size:12px;color:var(--stamp,#c8a96e);';
msg.textContent = 'You are on the list. We will email you when it is time to make a regrettable purchase.';
form.style.display = 'none';
wrapper.appendChild(msg);
});
return false;
};
// ─── WooCommerce quantity controls (override default +/-) ─────────────────
// Replace WC's quantity input with our styled controls
function initQtyControls() {
document.querySelectorAll('.quantity:not(.rar-qty-init)').forEach(function (wrap) {
var input = wrap.querySelector('input.qty, input[type=number]');
if (!input) return;
wrap.classList.add('rar-qty-init');
var minusBtn = document.createElement('button');
minusBtn.type = 'button';
minusBtn.className = 'rar-qty__btn';
minusBtn.dataset.action = 'minus';
minusBtn.innerHTML = '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14"></path></svg>';
minusBtn.style.cssText = 'padding:0 14px;border-right:1px solid var(--ink);display:flex;align-items:center;';
var plusBtn = document.createElement('button');
plusBtn.type = 'button';
plusBtn.className = 'rar-qty__btn';
plusBtn.dataset.action = 'plus';
plusBtn.innerHTML = '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M12 5v14M5 12h14"></path></svg>';
plusBtn.style.cssText = 'padding:0 14px;border-left:1px solid var(--ink);display:flex;align-items:center;';
input.style.cssText = 'padding:0 18px;font-family:var(--mono);font-size:14px;min-width:50px;text-align:center;border:none;background:transparent;';
wrap.style.cssText = 'display:flex;align-items:stretch;border:1.5px solid var(--ink);';
wrap.insertBefore(minusBtn, input);
wrap.appendChild(plusBtn);
[minusBtn, plusBtn].forEach(function (btn) {
btn.addEventListener('click', function () {
var val = parseInt(input.value) || 1;
var step = parseInt(input.step) || 1;
if (btn.dataset.action === 'plus') {
input.value = val + step;
} else {
input.value = Math.max(parseInt(input.min) || 1, val - step);
}
input.dispatchEvent(new Event('change', { bubbles: true }));
});
});
});
}
// Run on DOM ready and after any AJAX
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initQtyControls);
} else {
initQtyControls();
}
document.addEventListener('wc_fragments_refreshed', initQtyControls);
})();