/* ========================================================================== Ertunç Özbay — Workshop & Portfolio Script (Plain JS, No Dependencies) Handles: 1. Prominent Multi-Theme Switcher (🎨 Colorful Studio [Default] | 🌈 Neon | 📐 Blueprint) 2. Accessible mobile navigation menu toggle (with Escape key support) 3. Static blog category filtering on the Blog page 4. One-click copy buttons for Email addresses and Code/Command blocks 5. Image lightbox for hardware prototype photos and schematics ========================================================================== */ (function () { "use strict"; // 1. Multi-Theme Switcher (Colorful Default, Cyber Neon, Blueprint Lab) var rootEl = document.documentElement; var validThemes = ["colorful", "neon", "blueprint"]; var savedTheme = "colorful"; try { var stored = localStorage.getItem("eo-studio-theme"); if (stored && validThemes.indexOf(stored) !== -1) { savedTheme = stored; } } catch (e) {} function applyTheme(themeName) { if (validThemes.indexOf(themeName) === -1) { themeName = "colorful"; } rootEl.setAttribute("data-theme", themeName); try { localStorage.setItem("eo-studio-theme", themeName); } catch (e) {} var buttons = document.querySelectorAll("[data-set-theme]"); buttons.forEach(function (btn) { var isTarget = btn.getAttribute("data-set-theme") === themeName; btn.setAttribute("aria-pressed", isTarget ? "true" : "false"); }); } applyTheme(savedTheme); document.addEventListener("click", function (event) { var themeBtn = event.target.closest("[data-set-theme]"); if (themeBtn) { applyTheme(themeBtn.getAttribute("data-set-theme")); } }); // 2. Mobile Navigation Toggle var navToggle = document.querySelector("[data-nav-toggle]"); var siteNav = document.querySelector("[data-site-nav]"); if (navToggle && siteNav) { navToggle.addEventListener("click", function () { var isExpanded = navToggle.getAttribute("aria-expanded") === "true"; var nextState = !isExpanded; navToggle.setAttribute("aria-expanded", String(nextState)); siteNav.classList.toggle("is-open", nextState); var labelSpan = navToggle.querySelector("[data-nav-label]"); if (labelSpan) { labelSpan.textContent = nextState ? "Close" : "Menu"; } }); document.addEventListener("keydown", function (event) { if (event.key === "Escape" && siteNav.classList.contains("is-open")) { navToggle.setAttribute("aria-expanded", "false"); siteNav.classList.remove("is-open"); var labelSpan = navToggle.querySelector("[data-nav-label]"); if (labelSpan) { labelSpan.textContent = "Menu"; } navToggle.focus(); } }); } // 3. Blog Category Filter var filterButtons = document.querySelectorAll("[data-blog-filter]"); var blogCards = document.querySelectorAll("[data-blog-category]"); var filterStatus = document.getElementById("blog-filter-status"); if (filterButtons.length > 0 && blogCards.length > 0) { filterButtons.forEach(function (button) { button.addEventListener("click", function () { var selectedCategory = button.getAttribute("data-blog-filter"); filterButtons.forEach(function (btn) { btn.setAttribute("aria-pressed", btn === button ? "true" : "false"); }); var visibleCount = 0; blogCards.forEach(function (card) { var categories = (card.getAttribute("data-blog-category") || "").split(","); var match = selectedCategory === "all" || categories.indexOf(selectedCategory) !== -1; card.hidden = !match; if (match) { visibleCount += 1; } }); if (filterStatus) { filterStatus.textContent = "Showing " + visibleCount + (visibleCount === 1 ? " entry" : " entries") + (selectedCategory === "all" ? "." : " in selected category."); } }); }); } // 4. Copy Email to Clipboard Buttons var copyEmailButtons = document.querySelectorAll("[data-copy-email]"); copyEmailButtons.forEach(function (btn) { btn.addEventListener("click", function () { var email = btn.getAttribute("data-copy-email"); if (!email || !navigator.clipboard) return; var originalText = btn.textContent; navigator.clipboard.writeText(email).then(function () { btn.textContent = "✓ Copied: " + email; setTimeout(function () { btn.textContent = originalText; }, 2200); }); }); }); // 5. Copy Code / Terminal Commands Buttons var copyCodeButtons = document.querySelectorAll("[data-copy-code]"); copyCodeButtons.forEach(function (btn) { btn.addEventListener("click", function () { var windowEl = btn.closest(".code-window"); if (!windowEl || !navigator.clipboard) return; var preEl = windowEl.querySelector("pre"); if (!preEl) return; var originalText = btn.textContent; navigator.clipboard.writeText(preEl.innerText).then(function () { btn.textContent = "✓ Copied!"; setTimeout(function () { btn.textContent = originalText; }, 2000); }); }); }); // 6. Image Lightbox for Hardware Photos & Schematics var zoomImages = document.querySelectorAll(".zoomable-img"); if (zoomImages.length > 0) { var backdrop = document.createElement("div"); backdrop.className = "lightbox-backdrop"; backdrop.hidden = true; backdrop.innerHTML = '' + '' + ''; document.body.appendChild(backdrop); var lbImg = backdrop.querySelector(".lightbox-Backdrop-img"); var lbCap = backdrop.querySelector(".lightbox-caption"); var lbClose = backdrop.querySelector(".lightbox-close"); function closeLightbox() { backdrop.hidden = true; lbImg.src = ""; } zoomImages.forEach(function (img) { img.addEventListener("click", function () { lbImg.src = img.src; lbImg.alt = img.alt || ""; lbCap.textContent = img.alt || ""; backdrop.hidden = false; }); }); lbClose.addEventListener("click", closeLightbox); backdrop.addEventListener("click", function (e) { if (e.target === backdrop) closeLightbox(); }); document.addEventListener("keydown", function (e) { if (e.key === "Escape" && !backdrop.hidden) closeLightbox(); }); } // 7. Upgrade self-hosted Git links when accessed via ertuncozbay.dev domain if (window.location.hostname.indexOf("ertuncozbay.dev") !== -1) { document.querySelectorAll('a[href*="34.57.151.250:3000"]').forEach(function (a) { a.href = a.href.replace("http://34.57.151.250:3000", "https://git.ertuncozbay.dev"); }); document.querySelectorAll(".code-window pre code").forEach(function (codeEl) { codeEl.textContent = codeEl.textContent .replace(/http:\/\/34\.57\.151\.250:3000/g, "https://git.ertuncozbay.dev") .replace(/http:\/\/34\.57\.151\.250/g, "https://ertuncozbay.dev"); }); } })();