credit.jaxoff.tv/js/main.js

146 lines
9.2 KiB
JavaScript

(() => {
document.addEventListener("DOMContentLoaded", init);
async function init() {
document.getElementById("currentYear").textContent = new Date().getFullYear();
await loadArtists();
}
async function loadArtists() {
const loadingEl = document.getElementById("loading");
const errorEl = document.getElementById("error");
const gridEl = document.getElementById("artistGrid");
errorEl.style.display = "none";
loadingEl.style.display = "block";
try {
const url = `./data/artists.json?v=${Date.now()}`;
const res = await fetch(url, {
cache: "no-store",
headers: { "Accept": "application/json" }
});
if (!res.ok) {
throw new Error(`artists.json fetch failed: ${res.status} ${res.statusText}`);
}
const artists = await res.json();
loadingEl.style.display = "none";
if (!Array.isArray(artists) || artists.length === 0) {
gridEl.innerHTML = '<p class="error">Keine Künstler-Daten verfügbar.</p>';
return;
}
const frag = document.createDocumentFragment();
for (const artist of artists) {
frag.appendChild(createArtistCardNode(artist));
}
gridEl.replaceChildren(frag);
} catch (err) {
console.error("Error loading artists:", err);
loadingEl.style.display = "none";
errorEl.style.display = "block";
gridEl.textContent = "";
}
}
function createArtistCardNode(artist) {
const article = document.createElement("article");
article.className = "artist-card";
const inner = document.createElement("div");
inner.className = "card-inner";
const imageContainer = document.createElement("div");
imageContainer.className = "image-container";
if (artist.orientation) {
imageContainer.classList.add(artist.orientation);
}
const img = document.createElement("img");
img.className = "artist-image";
img.src = artist.image;
img.alt = `${artist.role} von ${artist.name}`;
img.loading = "lazy";
img.decoding = "async";
img.dataset.orientation = artist.orientation || 'auto';
imageContainer.appendChild(img);
const content = document.createElement("div");
content.className = "content";
const name = document.createElement("h2");
name.className = "artist-name";
name.textContent = artist.name;
const role = document.createElement("div");
role.className = "artist-role";
role.textContent = artist.role;
const desc = document.createElement("p");
desc.className = "artist-description";
desc.textContent = artist.description ?? "";
content.appendChild(name);
content.appendChild(role);
content.appendChild(desc);
const links = createSocialLinksNode(artist.links);
if (links) content.appendChild(links);
inner.appendChild(imageContainer);
inner.appendChild(content);
article.appendChild(inner);
return article;
}
function createSocialLinksNode(links) {
if (!links) return null;
const wrap = document.createElement("div");
wrap.className = "social-links";
const order = ["vgen", "twitter", "bluesky", "youtube", "twitch", "instagram", "fiverr", "website"];
for (const platform of order) {
if (!links[platform]) continue;
wrap.appendChild(createIconLink(platform, links[platform]));
}
return wrap.childElementCount ? wrap : null;
}
function createIconLink(platform, url) {
const a = document.createElement("a");
a.href = url;
a.className = `social-link ${platform}`;
a.target = "_blank";
a.rel = "noopener";
a.ariaLabel = platform;
a.innerHTML = getPlatformSvg(platform);
return a;
}
function getPlatformSvg(platform) {
const svgs = {
vgen: `<svg width="20" height="20" viewBox="18.3 34.08 166.6 150" fill="currentColor" aria-hidden="true" focusable="false"><g transform="translate(0 200) scale(.1 -.1)"><path d="m1151 1644c-184-49-336-213-374-403l-13-64-58 72c-31 39-74 82-94 96-136 88-327 36-396-108-75-157-30-265 222-529 220-230 387-330 572-345 234-18 483 152 731 498 99 138 112 173 107 275-4 75-9 93-52 180-39 78-63 111-129 177-121 121-227 167-382 166-44 0-104-7-134-15zm246-157c73-38 115-77 172-162 51-76 75-151 64-196-15-59-203-303-299-388-229-202-400-212-631-35-86 66-236 220-318 328-50 65-60 85-60 118s7 46 33 69c18 16 44 29 58 29 35 0 78-24 98-55 39-60 199-235 265-290 88-74 176-125 217-125 30 0 91 20 106 35 4 4-29 48-73 98-94 108-119 164-119 267 0 152 92 280 233 326 68 22 191 13 254-19z"></path><path d="m1183 1304c-46-23-73-71-73-129 0-46 3-50 79-128 43-45 83-77 89-73 27 17 132 169 132 192 0 34-22 73-64 113-43 41-111 52-163 25z"></path></g></svg>`,
twitter: `<svg width="20" height="20" viewBox="0.98 1.48 246.2 200.05" fill="currentColor" aria-hidden="true" focusable="false"><path d="M221.95 51.29c.15 2.17.15 4.34.15 6.53 0 66.73-50.8 143.69-143.69 143.69v-.04c-27.44.04-54.31-7.82-77.41-22.64 3.99.48 8 .72 12.02.73 22.74.02 44.83-7.61 62.72-21.66-21.61-.41-40.56-14.5-47.18-35.07 7.57 1.46 15.37 1.16 22.8-.87-23.56-4.76-40.51-25.46-40.51-49.5v-.64c7.02 3.91 14.88 6.08 22.92 6.32C11.58 63.31 4.74 33.79 18.14 10.71c25.64 31.55 63.47 50.73 104.08 52.76-4.07-17.54 1.49-35.92 14.61-48.25 20.34-19.12 52.33-18.14 71.45 2.19 11.31-2.23 22.15-6.38 32.07-12.26-3.77 11.69-11.66 21.62-22.2 27.93 10.01-1.18 19.79-3.86 29-7.95-6.78 10.16-15.32 19.01-25.2 26.16z"></path></svg>`,
bluesky: `<svg width="20" height="20" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M3.468 1.948C5.303 3.325 7.276 6.118 8 7.616c.725-1.498 2.698-4.29 4.532-5.668C13.855.955 16 .186 16 2.632c0 .489-.28 4.105-.444 4.692-.572 2.04-2.653 2.561-4.504 2.246 3.236.551 4.06 2.375 2.281 4.2-3.376 3.464-4.852-.87-5.23-1.98-.07-.204-.103-.3-.103-.218 0-.081-.033.014-.102.218-.379 1.11-1.855 5.444-5.231 1.98-1.778-1.825-.955-3.65 2.28-4.2-1.85.315-3.932-.205-4.503-2.246C.28 6.737 0 3.12 0 2.632 0 .186 2.145.955 3.468 1.948"/></svg>`,
youtube: `<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"></path></svg>`,
twitch: `<svg width="20" height="20" viewBox="24.27 0 463.45 512" fill="currentColor" aria-hidden="true" focusable="false"><path d="M391.2 103.5H352.5v109.7h38.6zM285 103H246.4V212.8H285zM120.8 0 24.3 91.4V420.6H140.1V512l96.5-91.4h77.3L487.7 256V0zM449.1 237.8l-77.2 73.1H294.6l-67.6 64v-64H140.1V36.6H449.1z"></path></svg>`,
instagram: `<svg width="20" height="20" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true" focusable="false"><path d="M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141zm0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7zm146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8zm76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"></path></svg>`,
fiverr: `<svg width="20" height="20" viewBox="-2.5 -2 24 24" fill="currentColor" aria-hidden="true" focusable="false"><path d="M16.25 16.25v-10h-10v-.625c0-1.034.841-1.875 1.875-1.875H10V0H8.125A5.632 5.632 0 0 0 2.5 5.625v.625H0V10h2.5v6.25H0V20h8.75v-3.75h-2.5V10h6.285v6.25H10V20h8.75v-3.75h-2.5z"/><circle cx="14.375" cy="1.875" r="1.875"/></svg>`,
website: `<svg width="20" height="20" viewBox="0 0 640 640" fill="currentColor" aria-hidden="true" focusable="false"><path d="M415.9 344L225 344C227.9 408.5 242.2 467.9 262.5 511.4C273.9 535.9 286.2 553.2 297.6 563.8C308.8 574.3 316.5 576 320.5 576C324.5 576 332.2 574.3 343.4 563.8C354.8 553.2 367.1 535.8 378.5 511.4C398.8 467.9 413.1 408.5 416 344zM224.9 296L415.8 296C413 231.5 398.7 172.1 378.4 128.6C367 104.2 354.7 86.8 343.3 76.2C332.1 65.7 324.4 64 320.4 64C316.4 64 308.7 65.7 297.5 76.2C286.1 86.8 273.8 104.2 262.4 128.6C242.1 172.1 227.8 231.5 224.9 296zM176.9 296C180.4 210.4 202.5 130.9 234.8 78.7C142.7 111.3 74.9 195.2 65.5 296L176.9 296zM65.5 344C74.9 444.8 142.7 528.7 234.8 561.3C202.5 509.1 180.4 429.6 176.9 344L65.5 344zM463.9 344C460.4 429.6 438.3 509.1 406 561.3C498.1 528.6 565.9 444.8 575.3 344L463.9 344zM575.3 296C565.9 195.2 498.1 111.3 406 78.7C438.3 130.9 460.4 210.4 463.9 296L575.3 296z"/></svg>`
}
return svgs[platform] || "";
}
})();