git / moonbite-network / static/site.js · raw
/* ========================================================================== MoonBite — Marketing Site behaviour (site.js) Loaded with `defer` by base.html on every page. Self-contained IIFE. Does NOT declare `htmlElement` / `themeToggle` — those live in base's inline theme script. Everything here is feature-detected so it is safe to load on the tool pages too (dashboard/wallet/mining/explorer). ========================================================================== */(function () { "use strict"; /* ------------------------------------------------ mega-nav dropdowns */ var navItems = document.querySelectorAll(".mb-nav-item"); navItems.forEach(function (item) { var trigger = item.querySelector(".mb-nav-trigger"); if (!trigger || !item.querySelector(".mb-dropdown")) return; // Click toggles (works on touch + keyboard); hover handled by CSS. trigger.addEventListener("click", function (e) { // Allow plain links without a dropdown to navigate normally. e.preventDefault(); var wasOpen = item.classList.contains("is-open"); closeAllDropdowns(); if (!wasOpen) item.classList.add("is-open"); }); }); function closeAllDropdowns() { navItems.forEach(function (i) { i.classList.remove("is-open"); }); } document.addEventListener("click", function (e) { if (!e.target.closest(".mb-nav-item")) closeAllDropdowns(); }); document.addEventListener("keydown", function (e) { if (e.key === "Escape") { closeAllDropdowns(); closeMobileSheet(); } }); /* ------------------------------------------------ mobile sheet */ var hamburger = document.querySelector(".mb-hamburger"); var sheet = document.querySelector(".mb-mobile-sheet"); var sheetClose = document.querySelector(".mb-mobile-close"); function openMobileSheet() { if (sheet) { sheet.classList.add("is-open"); document.body.style.overflow = "hidden"; } } function closeMobileSheet() { if (sheet) { sheet.classList.remove("is-open"); document.body.style.overflow = ""; } } if (hamburger) hamburger.addEventListener("click", openMobileSheet); if (sheetClose) sheetClose.addEventListener("click", closeMobileSheet); document.querySelectorAll(".mb-mobile-group > button").forEach(function (btn) { btn.addEventListener("click", function () { btn.parentElement.classList.toggle("is-open"); }); }); document.querySelectorAll(".mb-mobile-links a").forEach(function (a) { a.addEventListener("click", closeMobileSheet); }); /* ------------------------------------------------ live network ticker */ var ticker = document.querySelector("[data-mb-ticker]"); if (ticker) { var elHeight = document.getElementById("mbStatHeight"); var elSupply = document.getElementById("mbStatSupply"); var elTx = document.getElementById("mbStatTx"); var elMempool = document.getElementById("mbStatMempool"); var pull = function () { fetch("/api/blockchain/info") .then(function (r) { return r.json(); }) .then(function (d) { if (!d || d.status !== "success") return; if (elHeight) elHeight.textContent = d.height; if (elSupply) elSupply.textContent = Number(d.total_money_coins).toLocaleString(); if (elTx) elTx.textContent = Number(d.tx_count).toLocaleString(); if (elMempool) elMempool.textContent = d.mempool_size; }) .catch(function () { /* silent — marketing band is non-critical */ }); }; pull(); setInterval(pull, 10000); } /* ------------------------------------------------ scroll reveal */ var revealEls = document.querySelectorAll(".mb-reveal"); if (revealEls.length) { if ("IntersectionObserver" in window) { var io = new IntersectionObserver(function (entries) { entries.forEach(function (en) { if (en.isIntersecting) { en.target.classList.add("is-visible"); io.unobserve(en.target); } }); }, { rootMargin: "0px 0px -8% 0px", threshold: 0.08 }); revealEls.forEach(function (el) { io.observe(el); }); } else { revealEls.forEach(function (el) { el.classList.add("is-visible"); }); } } /* ------------------------------------------------ FAQ accordion */ document.querySelectorAll(".mb-faq-q").forEach(function (q) { q.addEventListener("click", function () { var item = q.closest(".mb-faq-item"); var ans = item.querySelector(".mb-faq-a"); var open = item.classList.toggle("is-open"); ans.style.maxHeight = open ? ans.scrollHeight + "px" : "0"; }); }); /* ------------------------------------------------ notify capture */ document.querySelectorAll(".mb-notify-form").forEach(function (form) { form.addEventListener("submit", function (e) { e.preventDefault(); var input = form.querySelector("input[type=email]"); var email = (input && input.value || "").trim(); var wrap = form.closest(".mb-notify") || form.parentElement; var okEl = wrap.querySelector(".mb-notify-ok"); if (!email || email.indexOf("@") < 1 || email.indexOf(".") < 0) { if (okEl) { okEl.style.color = ""; okEl.textContent = "Please enter a valid email address."; } return; } // Client-side fallback (Railway FS is ephemeral) — remember locally. try { var saved = JSON.parse(localStorage.getItem("mb_notify") || "[]"); if (saved.indexOf(email) === -1) { saved.push(email); localStorage.setItem("mb_notify", JSON.stringify(saved)); } } catch (err) { /* ignore storage errors */ } fetch("/api/notify", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: email, source: form.getAttribute("data-source") || "site" }) }).catch(function () { /* localStorage fallback already applied */ }) .finally(function () { form.reset(); if (okEl) { okEl.style.color = ""; okEl.textContent = "You're on the list. We'll email you when MBITE lists."; } }); }); }); /* ------------------------------------------------ footer year */ var yr = document.getElementById("mbYear"); if (yr) yr.textContent = new Date().getFullYear();})();