/* Gardenas - site.js.php (patched, ES5 only) * - Mobile nav: close on link click / ESC / desktop resize, backdrop close, scroll lock * - Anchor jump: header-height offset (no CSS var dependency during scroll) * - Photo uploader: D&D + picker, 64px thumbs, × remove, ★ primary (keeps input.files for non-DataTransfer) * - Global D&D guard * - UI niceties: counters (files/MB), consent checkbox gates submit */ (function(){ 'use strict'; /* ------------------------------- * Utilities * ------------------------------- */ function $(sel, root){ return (root||document).querySelector(sel); } function $all(sel, root){ return Array.prototype.slice.call((root||document).querySelectorAll(sel)); } function on(el, ev, fn, opts){ if(el){ el.addEventListener(ev, fn, opts||false); } } function hasClass(el, c){ return el && (' '+el.className+' ').indexOf(' '+c+' ') > -1; } function addClass(el, c){ if(el && !hasClass(el,c)){ el.className = (el.className ? el.className+' ' : '') + c; } } function remClass(el, c){ if(el && hasClass(el,c)){ el.className = (' '+el.className+' ').replace(' '+c+' ',' ').trim(); } } // Element.matches polyfill if(!Element.prototype.matches){ Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector || function(s){ var m = (this.document || this.ownerDocument).querySelectorAll(s), i = 0; while(m[i] && m[i] !== this){ i++; } return !!m[i]; }; } /* ------------------------------- * Anchor offset + scrolling * ------------------------------- */ function setAnchorOffset(){ var header = $('header.site'); var h = header ? header.getBoundingClientRect().height : 0; var offset = Math.round(h + 6); try{ document.documentElement.style.setProperty('--anchor-offset', offset + 'px'); }catch(_){} } window.setAnchorOffset = setAnchorOffset; function prefersReduced(){ try{ return !!(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches); } catch(_){ return false; } } function scrollToWithOffset(targetEl){ if(!targetEl){ return; } var header = $('header.site'); var off = header ? Math.round(header.getBoundingClientRect().height + 6) : 0; var rect = targetEl.getBoundingClientRect(); var y = (window.pageYOffset || document.documentElement.scrollTop) + rect.top - off; if(prefersReduced()){ window.scrollTo(0, y); }else{ try{ window.scrollTo({ top: y, behavior: 'smooth' }); } catch(_){ window.scrollTo(0, y); } } } /* ------------------------------- * Mobile navigation * ------------------------------- */ function syncMenuState(){ var navc = $('#navc') || $('input.navc[type="checkbox"]'); var label = $('#menuToggle') || $('.nav-toggle'); var open = !!(navc && navc.checked); if(label){ try{ label.setAttribute('aria-expanded', open ? 'true' : 'false'); }catch(_){ } } var root = document.documentElement; if(open){ addClass(root, 'menu-open'); } else { remClass(root, 'menu-open'); } setTimeout(setAnchorOffset, 0); } function initMobileNav(){ var navc = $('#navc') || $('input.navc[type="checkbox"]'); var backdrop = $('label.backdrop'); if(backdrop){ on(backdrop, 'click', function(){ if(navc){ navc.checked = false; syncMenuState(); } }); } on(document, 'keydown', function(e){ e = e || window.event; if((e.key && e.key.toLowerCase() === 'escape') || e.keyCode === 27){ if(navc && navc.checked){ navc.checked = false; syncMenuState(); } } }); on(window, 'resize', function(){ setAnchorOffset(); if(window.innerWidth >= 1024 && navc && navc.checked){ navc.checked = false; syncMenuState(); } }); if(navc){ on(navc, 'change', syncMenuState); } syncMenuState(); } /* ------------------------------- * Anchor links * ------------------------------- */ function initAnchorLinks(){ var links = $all('a[href^=\"#\"]'); var navc = $('#navc') || $('input.navc[type=\"checkbox\"]'); function handleHash(href){ if(!href || href === '#'){ return; } var id = href.charAt(0) === '#' ? href.slice(1) : href; var el = document.getElementById(id); if(!el){ try{ location.hash = href; }catch(_){ } return; } scrollToWithOffset(el); try{ history.pushState(null, '', '#' + id); }catch(_){ location.hash = '#' + id; } } for(var i=0;i= 0 && v < files.length){ starIndex = v; } } // build thumbs for(var i=0;i idx){ starHidden.value = Math.max(0, currentStar - 1); } } rebuildPreview(); }else{ if(item && item.parentNode){ item.parentNode.removeChild(item); } } }); on(btnStar, 'click', function(){ var all = $all('.thumb', grid); for(var k=0;k= 0) ? newIdx : 0; } rebuildPreview(); }); } item.appendChild(img); item.appendChild(btnX); item.appendChild(btnStar); grid.appendChild(item); })(i); } updateCounters(); syncSubmitEnabled(); } on(inp, 'change', function(){ rebuildPreview(); }); if(dz){ on(dz, 'dragenter', function(e){ e.preventDefault(); addClass(dz, 'is-dragover'); }); on(dz, 'dragover', function(e){ e.preventDefault(); addClass(dz, 'is-dragover'); }); on(dz, 'dragleave', function(e){ if(e.target === dz){ remClass(dz, 'is-dragover'); } }); on(dz, 'drop', function(e){ e.preventDefault(); remClass(dz, 'is-dragover'); if(e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length){ if(supportsDT){ var dt = new DataTransfer(); var existing = inp.files, i; if(existing){ for(i=0;i