// Delegated handlers extracted from inline on* attributes for CSP compliance. // These are the named wrappers referenced by data-action / data-change / // data-input / data-submit in the pages templates. The action dispatcher in // the core module invokes each with `this` bound to the dispatching element, so the // bodies read args from the element (this.value, this.dataset, this itself) // exactly as the original inline handlers did. // No-op verb: used where the original inline handler only stopped propagation // (the data-stop modifier does the actual work; this satisfies the dispatcher's // requirement for a data-action value). window.noop = function () {}; // cart.html: onclick="removeCartGroup(this)" window.onRemoveCartGroup = function () { removeCartGroup(this); }; // discover.html: onclick="document.querySelector('.discover-sidebar').classList.toggle('show'); this.classList.toggle('active');" window.toggleDiscoverFilters = function () { // The state lives on .discover-layout, not on the sidebar itself: the // sidebar is replaced wholesale by an out-of-band swap on every filter // change, which would drop a class set on it and snap the mobile panel // shut mid-interaction. var layout = document.querySelector('.discover-layout'); if (!layout) return; var open = layout.classList.toggle('filters-open'); this.classList.toggle('active', open); this.setAttribute('aria-expanded', open ? 'true' : 'false'); }; // index.html: onsubmit="return submitNotify(event)" (data-submit auto-prevents; // submitNotify only uses the event for preventDefault). window.onNotifySubmit = function () { submitNotify({ preventDefault: function () {} }); }; // item.html: onclick="openCollectionPicker('{{ item.id }}', this)" window.onOpenCollectionPicker = function () { openCollectionPicker(this.getAttribute('data-arg'), this); }; // item.html / library_downloads.html / project.html: // onclick="switchSectionTab(this, 'section-{{ section.slug }}')" window.onSwitchSectionTab = function () { switchSectionTab(this, this.getAttribute('data-arg')); }; // library.html: onclick="setActiveTab(this)" window.onSetActiveTab = function () { setActiveTab(this); }; // purchase.html: oninput="updatePwywButton(this.value)" window.onPwywInput = function () { updatePwywButton(this.value); }; // purchase.html: onclick="fetch('/api/cart/{{ item.id }}',{...}).then(...);return false;" window.onAddToCartLink = function () { fetch('/api/cart/' + this.getAttribute('data-arg'), {method:'POST',headers:csrfHeaders()}).then(function(r){if(!r.ok)throw new Error('Failed');return r.json()}).then(function(){window.location.href='/cart'}).catch(function(){alert('Could not add to cart. Please try again.')}); }; // purchase.html: onclick="window.history.back()" window.historyBack = function () { window.history.back(); }; // receipt.html: onclick="window.print()" window.printPage = function () { window.print(); };