185 lines
6.6 KiB
JavaScript
185 lines
6.6 KiB
JavaScript
/* ==========================================================================
|
|
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 =
|
|
'<button type="button" class="lightbox-close" aria-label="Close image preview">✕ Close (Esc)</button>' +
|
|
'<img class="lightbox-Backdrop-img" src="" alt="">' +
|
|
'<div class="lightbox-caption"></div>';
|
|
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();
|
|
});
|
|
}
|
|
})();
|