1
0
Files
PonyWave-Tools/gronkh_games/index.html

573 lines
20 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gronkh Games Suche</title>
<!-- Open Graph Tags -->
<meta property="og:title" content="Gronkh Games Suche">
<meta property="og:description" content="Durchsuche Spiele, die Gronkh auf seinem YouTube-Kanal gespielt hat.">
<meta property="og:url" content="https://tools.ponywave.de/gronkh_games">
<meta property="og:type" content="website">
<meta property="og:image" content="https://tools.ponywave.de/gronkh_games/gronkh.jpg">
<link rel="icon" href="https://tools.ponywave.de/gronkh_games/gronkh.jpg" type="image/jpg">
<!-- Analytics -->
<script defer src="https://stats.ponywave.de/script" data-website-id="9ef713d2-adb9-4906-9df5-708d8a8b9131" data-tag="gronkh_games"></script>
<style>
:root {
--primary-color: #6a329f;
--secondary-color: #8a5cb5;
--accent-color: #4a1979;
--background-color: #f5f0fa;
--canvas-background: #ffffff;
--text-color: #333333;
--footer-background: #333333;
--footer-text: #ffffff;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: var(--background-color);
color: var(--text-color);
line-height: 1.6;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
background-color: var(--primary-color);
color: white;
text-align: center;
padding: 2rem 1rem;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
main {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
flex: 1;
width: 100%;
}
.search-container {
margin-bottom: 2rem;
display: flex;
flex-direction: column;
align-items: center;
}
.search-box {
display: flex;
width: 100%;
max-width: 600px;
margin-bottom: 1rem;
}
#search-input {
flex: 1;
padding: 12px 20px;
font-size: 1rem;
border: 2px solid var(--secondary-color);
border-radius: 4px 0 0 4px;
outline: none;
}
#search-button {
background-color: var(--primary-color);
color: white;
border: none;
border-radius: 0 4px 4px 0;
padding: 0 20px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s;
}
#search-button:hover {
background-color: var(--accent-color);
}
.channel-selector {
margin-bottom: 1.5rem;
text-align: center;
width: 100%;
max-width: 600px;
}
.channel-selector h3 {
margin-bottom: 0.5rem;
font-size: 1.2rem;
}
.channel-buttons {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 10px;
}
.channel-button {
background-color: var(--canvas-background);
color: var(--primary-color);
border: 2px solid var(--secondary-color);
border-radius: 4px;
padding: 8px 15px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s;
}
.channel-button:hover {
background-color: var(--secondary-color);
color: white;
}
.channel-button.active {
background-color: var(--primary-color);
color: white;
}
.update-info {
color: #666;
font-style: italic;
text-align: center;
margin-bottom: 1rem;
margin-top: 1rem;
}
.game-section {
margin-bottom: 3rem;
}
.game-container {
background-color: var(--canvas-background);
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
margin-bottom: 1rem;
}
.game-list {
list-style-type: none;
}
.game-item {
padding: 12px 15px;
border-bottom: 1px solid #eee;
transition: background-color 0.2s;
}
.game-item:last-child {
border-bottom: none;
}
.game-item:hover {
background-color: #f5f5f5;
}
.game-item a {
color: var(--primary-color);
text-decoration: none;
display: block;
font-weight: 500;
}
.game-item a:hover {
text-decoration: underline;
}
footer {
background-color: var(--footer-background);
color: var(--footer-text);
text-align: center;
padding: 1.5rem;
margin-top: auto;
}
footer a {
color: #ccc;
text-decoration: none;
}
footer a:hover {
color: white;
text-decoration: underline;
}
.heart {
color: #ff6b6b;
}
.loading {
text-align: center;
padding: 20px;
font-style: italic;
color: #666;
}
.load-more-btn {
display: block;
background-color: var(--primary-color);
color: white;
border: none;
border-radius: 4px;
padding: 10px 15px;
margin: 15px auto 5px;
cursor: pointer;
font-size: 0.9rem;
transition: background-color 0.3s;
width: fit-content;
}
.load-more-btn:hover {
background-color: var(--accent-color);
}
.load-more-btn:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
@media (max-width: 768px) {
header {
padding: 1.5rem 1rem;
}
h1 {
font-size: 2rem;
}
main {
padding: 1.5rem;
}
.game-container {
padding: 1rem;
}
.channel-buttons {
flex-direction: column;
align-items: center;
}
.channel-button {
width: 100%;
max-width: 200px;
margin-bottom: 5px;
}
}
</style>
</head>
<body>
<header>
<h1>Gronkh Games Suche</h1>
<p>Finde alle Spiele, die Gronkh auf YouTube gespielt hat</p>
</header>
<main>
<div class="search-container">
<div class="channel-selector">
<h3>Wähle einen Kanal:</h3>
<div class="channel-buttons">
<button class="channel-button active" data-channel="all">Alle Kanäle</button>
<button class="channel-button" data-channel="gronkh">Gronkh</button>
<button class="channel-button" data-channel="gronkhretro">GronkhRetro</button>
<button class="channel-button" data-channel="gronkhrpgs">GronkhRPGs</button>
<button class="channel-button" data-channel="gronkhtv">GronkhTV</button>
<button class="channel-button" data-channel="gronkhzeugs">GronkhZeugs</button>
</div>
</div>
<div class="search-box">
<input type="text" id="search-input" placeholder="Spielname eingeben..." aria-label="Spielname eingeben">
<button id="search-button">Suchen</button>
</div>
<p class="update-info">Spieleliste zuletzt aktualisiert am 11.03.2025</p>
</div>
<div class="game-section">
<h2>Suchergebnisse</h2>
<div class="game-container" id="search-results">
<p id="no-results-message">Gib einen Suchbegriff ein, um Spiele zu finden.</p>
<ul class="game-list" id="results-list" style="display: none;"></ul>
<button id="load-more-btn" class="load-more-btn" style="display: none;">Lade 5 weitere</button>
</div>
</div>
<div class="game-section">
<h2>Neuste Spiele</h2>
<div class="game-container">
<ul class="game-list" id="newest-list">
<li class="loading">Lade neuste Spiele...</li>
</ul>
</div>
</div>
<div class="game-section">
<h2>Zufällige Spiele</h2>
<div class="game-container">
<ul class="game-list" id="random-list">
<li class="loading">Lade zufällige Spiele...</li>
</ul>
</div>
</div>
</main>
<footer>
<p><a href="https://tools.ponywave.de/">Zurück zur Startseite</a> | &copy; <span id="current-year"></span> Akamaru | Made with <span class="heart">❤️</span> by Claude</p>
</footer>
<script>
// Kanal-Optionen
const channels = {
all: 'playlists.json',
gronkh: 'gronkh_playlists.json',
gronkhretro: 'gronkhretro_playlists.json',
gronkhrpgs: 'gronkhrpgs_playlists.json',
gronkhtv: 'gronkhtv_playlists.json',
gronkhzeugs: 'gronkhzeugs_playlists.json'
};
// Standard-Kanal
let currentChannel = 'all';
let allGames = {}; // Cache für alle geladenen Spiele
let currentSearchResults = []; // Speichert die aktuellen Suchergebnisse
let currentResultsPage = 1; // Aktuelle Seite der Suchergebnisse
const resultsPerPage = 5; // Anzahl der Ergebnisse pro Seite
// Daten aus JSON-Datei laden
async function loadGames(channel = currentChannel) {
try {
if (allGames[channel]) {
return allGames[channel]; // Cache nutzen, wenn Daten bereits geladen sind
}
const response = await fetch(channels[channel]);
if (!response.ok) {
throw new Error(`Fehler beim Laden der ${channel} Spieldaten`);
}
const games = await response.json();
allGames[channel] = games; // Ergebnisse im Cache speichern
return games;
} catch (error) {
console.error('Fehler:', error);
return [];
}
}
// Aktuelle Jahreszahl im Footer einfügen
document.getElementById('current-year').textContent = new Date().getFullYear();
// Kanalauswahl-Buttons einrichten
function setupChannelButtons() {
const channelButtons = document.querySelectorAll('.channel-button');
channelButtons.forEach(button => {
button.addEventListener('click', async () => {
// Aktiven Button markieren
channelButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
// Kanal wechseln und Listen neu laden
currentChannel = button.dataset.channel;
await updateLists();
// Suchergebnisse zurücksetzen
document.getElementById('results-list').style.display = 'none';
document.getElementById('no-results-message').textContent = 'Gib einen Suchbegriff ein, um Spiele zu finden.';
document.getElementById('no-results-message').style.display = 'block';
});
});
}
// Listen neu laden
async function updateLists() {
// Lade-Indikatoren anzeigen
document.getElementById('newest-list').innerHTML = '<li class="loading">Lade neuste Spiele...</li>';
document.getElementById('random-list').innerHTML = '<li class="loading">Lade zufällige Spiele...</li>';
const games = await loadGames();
if (!games || games.length === 0) {
document.getElementById('newest-list').innerHTML = '<li>Keine Spiele gefunden</li>';
document.getElementById('random-list').innerHTML = '<li>Keine Spiele gefunden</li>';
return;
}
updateNewestList(games);
updateRandomList(games);
}
// Neuste Spiele anzeigen
function updateNewestList(games) {
const newestList = document.getElementById('newest-list');
newestList.innerHTML = '';
const newestGames = games.slice(0, 5);
if (newestGames.length === 0) {
newestList.innerHTML = '<li>Keine neuen Spiele gefunden</li>';
return;
}
newestGames.forEach(game => {
const li = document.createElement('li');
li.className = 'game-item';
const videoCountText = game.videoCount === 0 ? "(Keine Videos)" : `(${game.videoCount} Video${game.videoCount !== 1 ? 's' : ''})`;
li.innerHTML = `<a href="${game.url}" target="_blank">${game.title} ${videoCountText}</a>`;
newestList.appendChild(li);
});
}
// Zufällige Spiele anzeigen
function updateRandomList(games) {
const randomList = document.getElementById('random-list');
randomList.innerHTML = '';
if (games.length === 0) {
randomList.innerHTML = '<li>Keine Spiele gefunden</li>';
return;
}
const shuffledGames = [...games].sort(() => 0.5 - Math.random());
const randomGames = shuffledGames.slice(0, 5);
randomGames.forEach(game => {
const li = document.createElement('li');
li.className = 'game-item';
const videoCountText = game.videoCount === 0 ? "(Keine Videos)" : `(${game.videoCount} Video${game.videoCount !== 1 ? 's' : ''})`;
li.innerHTML = `<a href="${game.url}" target="_blank">${game.title} ${videoCountText}</a>`;
randomList.appendChild(li);
});
}
// Suchfunktion
async function performSearch() {
const searchTerm = document.getElementById('search-input').value.trim().toLowerCase();
const resultsList = document.getElementById('results-list');
const noResultsMessage = document.getElementById('no-results-message');
const loadMoreBtn = document.getElementById('load-more-btn');
if (!searchTerm) {
resultsList.style.display = 'none';
noResultsMessage.textContent = 'Gib einen Suchbegriff ein, um Spiele zu finden.';
noResultsMessage.style.display = 'block';
loadMoreBtn.style.display = 'none';
return;
}
// Spiele für aktuellen Kanal laden
const games = await loadGames();
// Spiele filtern, die dem Suchbegriff entsprechen
const matchingGames = games.filter(game =>
game.title.toLowerCase().includes(searchTerm)
);
// Speichere die Suchergebnisse für späteres Nachladen
currentSearchResults = matchingGames;
currentResultsPage = 1;
resultsList.innerHTML = '';
if (matchingGames.length === 0) {
resultsList.style.display = 'none';
noResultsMessage.textContent = 'Keine Spiele gefunden, die zum Suchbegriff passen.';
noResultsMessage.style.display = 'block';
loadMoreBtn.style.display = 'none';
return;
}
// Zeige die ersten 5 Suchergebnisse an
displaySearchResults(matchingGames, 1);
noResultsMessage.style.display = 'none';
resultsList.style.display = 'block';
// "Lade mehr" Button einrichten
if (matchingGames.length > resultsPerPage) {
loadMoreBtn.style.display = 'block';
} else {
loadMoreBtn.style.display = 'none';
}
}
// Zeigt eine bestimmte Seite von Suchergebnissen an
function displaySearchResults(matchingGames, page) {
const resultsList = document.getElementById('results-list');
const startIndex = (page - 1) * resultsPerPage;
const endIndex = Math.min(startIndex + resultsPerPage, matchingGames.length);
// Wenn es eine neue Suche ist (Seite 1), leere die Liste
if (page === 1) {
resultsList.innerHTML = '';
}
// Spiele für die aktuelle Seite anzeigen
for (let i = startIndex; i < endIndex; i++) {
const game = matchingGames[i];
const li = document.createElement('li');
li.className = 'game-item';
const videoCountText = game.videoCount === 0 ? "(Keine Videos)" : `(${game.videoCount} Video${game.videoCount !== 1 ? 's' : ''})`;
li.innerHTML = `<a href="${game.url}" target="_blank">${game.title} ${videoCountText}</a>`;
resultsList.appendChild(li);
}
// "Lade mehr" Button Status aktualisieren
const loadMoreBtn = document.getElementById('load-more-btn');
if (endIndex >= matchingGames.length) {
loadMoreBtn.style.display = 'none';
} else {
loadMoreBtn.style.display = 'block';
}
}
// Funktion zum Laden weiterer Ergebnisse
function loadMoreResults() {
if (currentSearchResults.length <= currentResultsPage * resultsPerPage) {
return; // Keine weiteren Ergebnisse vorhanden
}
currentResultsPage++;
displaySearchResults(currentSearchResults, currentResultsPage);
}
// Seiteninitalisierung
async function initializePage() {
// Kanalauswahl einrichten
setupChannelButtons();
// Such-Button und Enter-Taste
document.getElementById('search-button').addEventListener('click', performSearch);
document.getElementById('search-input').addEventListener('keyup', event => {
if (event.key === 'Enter') performSearch();
});
// "Lade mehr" Button
document.getElementById('load-more-btn').addEventListener('click', loadMoreResults);
// Initiale Listen laden
await updateLists();
}
// Beim Laden der Seite initialisieren
document.addEventListener('DOMContentLoaded', initializePage);
</script>
</body>
</html>