mobile support and shit

This commit is contained in:
sky
2025-11-14 21:53:45 -05:00
parent 896b2a0133
commit 7596d7283d
10 changed files with 436 additions and 74 deletions

243
js/games_improved.js Normal file
View File

@ -0,0 +1,243 @@
// this IS ai generated
// wanna test real world difference soon
document.addEventListener("DOMContentLoaded", loadGames);
let elements = [];
let isDev = [];
let starredGames = [];
// Cache DOM references
const domCache = {
games: null,
topGames: null,
starredGames: null,
gameCount: null,
loadingMsg: null,
allHeader: null,
topHeader: null,
starredHeader: null,
noResults: null,
gameSearch: null
};
function initDOMCache() {
domCache.games = document.getElementById("games");
domCache.topGames = document.getElementById("topGames");
domCache.starredGames = document.getElementById("starredgames");
domCache.gameCount = document.getElementById("gameCount");
domCache.loadingMsg = document.getElementById("loadingMsg");
domCache.allHeader = document.getElementById("allHeader");
domCache.topHeader = document.getElementById("topHeader");
domCache.starredHeader = document.getElementById("starredHeader");
domCache.noResults = document.getElementById("noResults");
domCache.gameSearch = document.getElementById("gamesearch");
}
async function loadGames() {
initDOMCache();
// Load starred games once
starredGames = JSON.parse(localStorage.getItem("selenite.starred") || '[]');
// Fetch and sort games
const data = await (await fetch("/resources/games.json")).json();
const sorted = data.sort((a, b) => {
const n1 = a.name.toUpperCase();
const n2 = b.name.toUpperCase();
return n1 < n2 ? -1 : n1 > n2 ? 1 : 0;
});
// Use DocumentFragments for batched DOM operations
const gamesFragment = document.createDocumentFragment();
const topGamesFragment = document.createDocumentFragment();
sorted.forEach(element => {
const isStarred = starredGames.includes(element.directory);
const newElement = createGameElement(element, isStarred);
elements.push(newElement);
if (element.tags?.includes("top")) {
topGamesFragment.appendChild(newElement);
} else {
gamesFragment.appendChild(newElement);
}
if (element.tags?.includes("tofinish")) {
isDev.push(element.directory);
}
});
// Append all elements at once (2 reflows instead of N)
domCache.games.appendChild(gamesFragment);
domCache.topGames.appendChild(topGamesFragment);
// Update UI
domCache.gameCount.innerText = `${data.length} games loaded!`;
domCache.loadingMsg.style.display = "none";
domCache.allHeader.style.display = "block";
domCache.topHeader.style.display = "block";
if (isDev.length > 0) {
sAlert("wip games", "dev message, shouldnt be seen");
console.log(isDev.join(","));
}
// Render starred games if any
if (starredGames.length > 0) {
renderStarredGames();
}
// Setup event delegation for game clicks and stars
setupEventDelegation();
}
function createGameElement(element, isStarred) {
const newElement = document.createElement("game");
newElement.setAttribute("data-target", element.directory);
newElement.setAttribute("data-image", element.image);
newElement.setAttribute("data-name", element.name);
const image = document.createElement("img");
image.src = `/resources/semag/${element.directory}/${element.image}`;
image.loading = "lazy";
const holder = document.createElement("div");
holder.id = "holder";
const title = document.createElement("h1");
title.innerText = element.name;
const warnings = document.createElement("warnings");
// Add warning tags if present
if (element.tags) {
if (element.tags.includes("13+")) {
const thirteenplus = document.createElement("warning");
thirteenplus.innerText = "13+";
thirteenplus.classList = "thirteen";
warnings.appendChild(thirteenplus);
}
if (element.tags.includes("horror")) {
const horror = document.createElement("warning");
horror.innerText = "😱";
horror.classList = "horror";
warnings.appendChild(horror);
}
if (element.tags.includes("gore")) {
const gore = document.createElement("warning");
gore.innerText = "🩸";
gore.classList = "gore";
warnings.appendChild(gore);
}
}
// Only add star for non-top games
if (!element.tags?.includes("top")) {
const star = document.createElement("img");
star.id = "star";
star.classList = "star";
star.src = isStarred ? "/img/star-fill.svg" : "/img/star.svg";
holder.appendChild(title);
holder.appendChild(star);
} else {
holder.appendChild(title);
}
newElement.appendChild(image);
newElement.appendChild(holder);
newElement.appendChild(warnings);
return newElement;
}
function setupEventDelegation() {
// Delegate game clicks on parent containers
const gameContainers = [domCache.games, domCache.topGames, domCache.starredGames];
gameContainers.forEach(container => {
container.addEventListener("click", (e) => {
const gameElement = e.target.closest("game");
if (!gameElement) return;
const clickedStar = e.target.id === "star" || e.target.classList.contains("star");
if (clickedStar) {
e.preventDefault();
e.stopPropagation();
handleStarClick(gameElement);
} else {
const name = gameElement.getAttribute("data-name");
const dir = gameElement.getAttribute("data-target");
const img = gameElement.getAttribute("data-image");
location.href = `/loader.html?title=${encodeURIComponent(name)}&dir=${dir}&img=${img}&type=g`;
}
});
});
}
function handleStarClick(gameElement) {
const game = gameElement.getAttribute("data-target");
const starImages = document.querySelectorAll(`game[data-target='${game}'] #star`);
starredGames = JSON.parse(localStorage.getItem("selenite.starred") || '[]');
if (!starredGames.includes(game)) {
starredGames.push(game);
starredGames.sort();
starImages.forEach(img => img.src = "/img/star-fill.svg");
} else {
starredGames.splice(starredGames.indexOf(game), 1);
starImages.forEach(img => img.src = "/img/star.svg");
}
localStorage.setItem("selenite.starred", JSON.stringify(starredGames));
renderStarredGames();
}
function renderStarredGames() {
domCache.starredHeader.style.display = starredGames.length > 0 ? "block" : "none";
domCache.starredGames.innerHTML = "";
if (starredGames.length === 0) return;
const fragment = document.createDocumentFragment();
starredGames.forEach((gameDir) => {
const originalElement = domCache.games.querySelector(`game[data-target='${gameDir}']`);
if (originalElement) {
const clonedElement = originalElement.cloneNode(true);
fragment.appendChild(clonedElement);
}
});
domCache.starredGames.appendChild(fragment);
}
// Search functionality
document.addEventListener("DOMContentLoaded", () => {
const gameSearch = document.getElementById("gamesearch");
if (!gameSearch) return;
gameSearch.addEventListener("input", () => {
const input = gameSearch.value.toUpperCase();
let hiddenCount = 0;
if (elements.length > 0) {
elements.forEach((element) => {
const title = element.getAttribute("data-name").toUpperCase();
if (title.includes(input)) {
element.style.display = "flex";
} else {
element.style.display = "none";
hiddenCount++;
}
});
}
const noResults = document.getElementById("noResults");
if (noResults) {
noResults.style.display = hiddenCount >= elements.length ? "flex" : "none";
}
});
});