Files
NewsSite/volumes/web/static/js/blog.js
hubble_dubble 3667c678e4 Please enter the commit message for your changes. Lines starting
with '#' will be ignored, and an empty message aborts the commit.

On branch main

Initial commit

Changes to be committed:
	new file:   .DS_Store
	new file:   .env
	new file:   .gitignore
	new file:   ai-worker/Dockerfile
	new file:   ai-worker/requirements.txt
	new file:   ai-worker/worker.py
	new file:   background-worker/Dockerfile
	new file:   background-worker/go.mod
	new file:   background-worker/go.sum
	new file:   background-worker/main.go
	new file:   background-worker/market.go
	new file:   background-worker/rmv.go
	new file:   background-worker/rss.go
	new file:   background-worker/sql_work.go
	new file:   db/Dockerfile
	new file:   db/init.sql
	new file:   docker-compose.yml
	new file:   server-app/dockerfile
	new file:   server-app/go.mod
	new file:   server-app/go.sum
	new file:   server-app/main.go
	new file:   volumes/.DS_Store
	new file:   volumes/db-init/.DS_Store
	new file:   volumes/db-init/data/news_rss_feeds.csv
	new file:   volumes/web/.DS_Store
	new file:   volumes/web/static/css/blog.css
	new file:   volumes/web/static/css/index-lite.css
	new file:   volumes/web/static/css/index.css
	new file:   volumes/web/static/css/mandelbrot.css
	new file:   volumes/web/static/img/minecraft.png
	new file:   volumes/web/static/js/blog.js
	new file:   volumes/web/static/js/index-lite.js
	new file:   volumes/web/static/js/index.js
	new file:   volumes/web/static/js/mandelbrot.js
	new file:   volumes/web/static/media/cantina.mp3
	new file:   volumes/web/static/media/countdowns.json
	new file:   volumes/web/static/media/gong.mp4
	new file:   volumes/web/template/blog.html
	new file:   volumes/web/template/index-lite.html
	new file:   volumes/web/template/index.html
	new file:   volumes/web/template/mandelbrot.html
2026-01-26 00:19:54 +01:00

90 lines
2.1 KiB
JavaScript

const grid = document.getElementById("grid");
function createTile(artikel) {
const tile = document.createElement("div");
tile.className = "tile";
const img = document.createElement("img");
img.src = artikel.image;
img.alt = artikel.title || "Artikelbild";
tile.appendChild(img);
const overlay = document.createElement("div");
overlay.className = "overlay";
const title = document.createElement("h3");
title.textContent = artikel.title || "Ohne Titel";
overlay.appendChild(title);
tile.appendChild(overlay);
tile.addEventListener("click", () => tile.classList.toggle("open"));
return tile;
}
async function ladeGalerie() {
grid.innerHTML = "";
let foundAny = false;
try {
const res = await fetch("/api/images", {
headers: { "Accept": "application/x-ndjson" }
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
if (!res.body) throw new Error("Streaming nicht unterstützt");
const reader = res.body.getReader();
const decoder = new TextDecoder("utf-8");
let buffer = "";
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() ?? "";
for (const line of lines) {
const s = line.trim();
if (!s) continue;
let artikel;
try {
artikel = JSON.parse(s);
} catch {
continue;
}
if (artikel?.image) {
grid.appendChild(createTile(artikel));
foundAny = true;
}
}
}
// Rest verarbeiten
const last = buffer.trim();
if (last) {
try {
const artikel = JSON.parse(last);
if (artikel?.image) {
grid.appendChild(createTile(artikel));
foundAny = true;
}
} catch {}
}
if (!foundAny) {
grid.innerHTML = '<div class="empty">Keine Bilder gefunden.</div>';
}
} catch (err) {
console.error(err);
grid.innerHTML = '<div class="empty">Fehler beim Laden der Galerie.</div>';
}
}
ladeGalerie();