Added color switching, moved scripts into dedicated files
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const overlay = document.getElementById('lightbox-overlay');
|
||||
const mediaContainer = document.getElementById('lightbox-media');
|
||||
const overlayCaption = document.getElementById('lightbox-caption');
|
||||
|
||||
function openLightboxWithImg(src, alt, figureNumber, captionText) {
|
||||
mediaContainer.innerHTML = '';
|
||||
const img = document.createElement('img');
|
||||
img.src = src;
|
||||
img.alt = alt;
|
||||
mediaContainer.appendChild(img);
|
||||
setCaption(figureNumber, captionText);
|
||||
overlay.classList.add('active');
|
||||
}
|
||||
|
||||
function openLightboxWithSvg(svgEl, figureNumber, captionText) {
|
||||
mediaContainer.innerHTML = '';
|
||||
const svgClone = svgEl.cloneNode(true);
|
||||
mediaContainer.appendChild(svgClone);
|
||||
setCaption(figureNumber, captionText);
|
||||
overlay.classList.add('active');
|
||||
}
|
||||
|
||||
function setCaption(figureNumber, captionText) {
|
||||
overlayCaption.innerHTML = captionText
|
||||
? '<span class="fig-number">Figure ' + figureNumber + ':</span> ' + captionText
|
||||
: '';
|
||||
}
|
||||
|
||||
document.querySelectorAll('.entry-content img').forEach(function (img, index) {
|
||||
const figureNumber = index + 1;
|
||||
const originalSrc = img.src;
|
||||
const originalAlt = img.alt;
|
||||
const captionEl = img.nextElementSibling;
|
||||
const captionText = (captionEl && captionEl.tagName === 'EM') ? captionEl.textContent : '';
|
||||
|
||||
img.addEventListener('click', function () {
|
||||
openLightboxWithImg(originalSrc, originalAlt, figureNumber, captionText);
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('svg-injected', function (e) {
|
||||
const svgEl = e.detail.svgEl;
|
||||
svgEl.style.cursor = 'zoom-in';
|
||||
svgEl.addEventListener('click', function () {
|
||||
openLightboxWithSvg(svgEl, e.detail.figureNumber, e.detail.captionText);
|
||||
});
|
||||
});
|
||||
|
||||
overlay.addEventListener('click', function () {
|
||||
overlay.classList.remove('active');
|
||||
mediaContainer.innerHTML = '';
|
||||
overlayCaption.innerHTML = '';
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape') {
|
||||
overlay.classList.remove('active');
|
||||
mediaContainer.innerHTML = '';
|
||||
overlayCaption.innerHTML = '';
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,94 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const injectedSvgs = [];
|
||||
|
||||
function parseColorMap(cssText, prop) {
|
||||
const map = {};
|
||||
const regex = new RegExp('\\[' + prop + '="([^"]+)"\\]\\s*{\\s*' + prop + ':\\s*([^;]+);', 'g');
|
||||
let m;
|
||||
while ((m = regex.exec(cssText)) !== null) {
|
||||
map[m[1]] = m[2].trim();
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
function applyThemeToSvg(entry, isDark) {
|
||||
const { svgEl, fillMap, strokeMap } = entry;
|
||||
|
||||
Object.keys(fillMap).forEach(function (lightColor) {
|
||||
svgEl.querySelectorAll('[fill="' + lightColor + '"]').forEach(function (el) {
|
||||
el.setAttribute('fill', isDark ? fillMap[lightColor] : lightColor);
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(strokeMap).forEach(function (lightColor) {
|
||||
svgEl.querySelectorAll('[stroke="' + lightColor + '"]').forEach(function (el) {
|
||||
el.setAttribute('stroke', isDark ? strokeMap[lightColor] : lightColor);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getIsDark() {
|
||||
const attr = document.documentElement.getAttribute('data-theme');
|
||||
if (attr) return attr === 'dark';
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
}
|
||||
|
||||
function applyThemeToAll() {
|
||||
const isDark = getIsDark();
|
||||
injectedSvgs.forEach(function (entry) {
|
||||
applyThemeToSvg(entry, isDark);
|
||||
});
|
||||
}
|
||||
|
||||
const svgImages = document.querySelectorAll('.entry-content img[src$=".svg"]');
|
||||
|
||||
svgImages.forEach(function (img, index) {
|
||||
const figureNumber = index + 1;
|
||||
const originalSrc = img.src;
|
||||
const originalAlt = img.alt;
|
||||
const captionEl = img.nextElementSibling;
|
||||
const captionText = (captionEl && captionEl.tagName === 'EM') ? captionEl.textContent : '';
|
||||
|
||||
fetch(img.src)
|
||||
.then(function (response) { return response.text(); })
|
||||
.then(function (svgText) {
|
||||
const parser = new DOMParser();
|
||||
const svgDoc = parser.parseFromString(svgText, 'image/svg+xml');
|
||||
const svgEl = svgDoc.querySelector('svg');
|
||||
|
||||
if (!svgEl) return;
|
||||
|
||||
if (img.alt) {
|
||||
svgEl.setAttribute('role', 'img');
|
||||
svgEl.setAttribute('aria-label', img.alt);
|
||||
}
|
||||
|
||||
svgEl.classList.add('injected-svg');
|
||||
|
||||
// Dark-Farbzuordnung aus dem internen <style>-Block auslesen, dann Block entfernen
|
||||
const styleEl = svgEl.querySelector('style');
|
||||
let fillMap = {};
|
||||
let strokeMap = {};
|
||||
if (styleEl) {
|
||||
fillMap = parseColorMap(styleEl.textContent, 'fill');
|
||||
strokeMap = parseColorMap(styleEl.textContent, 'stroke');
|
||||
styleEl.remove();
|
||||
}
|
||||
|
||||
img.replaceWith(svgEl);
|
||||
|
||||
const entry = { svgEl: svgEl, fillMap: fillMap, strokeMap: strokeMap };
|
||||
injectedSvgs.push(entry);
|
||||
applyThemeToSvg(entry, getIsDark());
|
||||
|
||||
document.dispatchEvent(new CustomEvent('svg-injected', {
|
||||
detail: { svgEl: svgEl, originalSrc: originalSrc, originalAlt: originalAlt, figureNumber: figureNumber, captionText: captionText }
|
||||
}));
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.error('SVG injection failed for', img.src, err);
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('themechange', applyThemeToAll);
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
(function () {
|
||||
const storedTheme = localStorage.getItem('theme');
|
||||
if (storedTheme === 'dark' || storedTheme === 'light') {
|
||||
document.documentElement.setAttribute('data-theme', storedTheme);
|
||||
}
|
||||
const storedFont = localStorage.getItem('font');
|
||||
if (storedFont === 'sans' || storedFont === 'serif') {
|
||||
document.documentElement.setAttribute('data-font', storedFont);
|
||||
}
|
||||
const storedAccent = localStorage.getItem('accent');
|
||||
if (storedAccent === 'alt' || storedAccent === 'default') {
|
||||
document.documentElement.setAttribute('data-accent', storedAccent);
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,51 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const root = document.documentElement;
|
||||
|
||||
// Theme toggle
|
||||
const toggleBtn = document.getElementById('theme-toggle');
|
||||
|
||||
function getCurrentTheme() {
|
||||
const attr = root.getAttribute('data-theme');
|
||||
if (attr) return attr;
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
function updateIcon() {
|
||||
toggleBtn.textContent = getCurrentTheme() === 'dark' ? '☀' : '☾';
|
||||
}
|
||||
updateIcon();
|
||||
toggleBtn.addEventListener('click', function () {
|
||||
const next = getCurrentTheme() === 'dark' ? 'light' : 'dark';
|
||||
root.setAttribute('data-theme', next);
|
||||
localStorage.setItem('theme', next);
|
||||
updateIcon();
|
||||
document.dispatchEvent(new CustomEvent('themechange'));
|
||||
});
|
||||
|
||||
// Accent toggle
|
||||
const accentToggleBtn = document.getElementById('accent-toggle');
|
||||
|
||||
function getCurrentAccent() {
|
||||
return root.getAttribute('data-accent') === 'alt' ? 'alt' : 'default';
|
||||
}
|
||||
|
||||
accentToggleBtn.addEventListener('click', function () {
|
||||
const next = getCurrentAccent() === 'alt' ? 'default' : 'alt';
|
||||
root.setAttribute('data-accent', next);
|
||||
localStorage.setItem('accent', next);
|
||||
document.dispatchEvent(new CustomEvent('themechange'));
|
||||
});
|
||||
|
||||
// Font toggle
|
||||
const fontToggleBtn = document.getElementById('font-toggle');
|
||||
|
||||
function getCurrentFont() {
|
||||
return root.getAttribute('data-font') === 'sans' ? 'sans' : 'serif';
|
||||
}
|
||||
|
||||
fontToggleBtn.addEventListener('click', function () {
|
||||
const next = getCurrentFont() === 'sans' ? 'serif' : 'sans';
|
||||
root.setAttribute('data-font', next);
|
||||
localStorage.setItem('font', next);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user