mirror of
https://github.com/Cametendo/devil-fruit-encyclopedia.git
synced 2026-09-14 00:09:47 +02:00
Rebuild site as a full One Piece character & Devil Fruit wiki
Replaces the 4-card quickstart mockup with a data-driven wiki covering the 100 most well-known One Piece characters and every Devil Fruit they carry (57 fruits total), each with its own linked detail page. - js/characters-data.js: 100 character profiles (stats, bio, abilities) - js/fruits-data.js: 57 Devil Fruit entries (history, powers, strengths/ weaknesses, full user lineage) cross-linked to character ids - index.html + main.js: searchable/filterable character grid - character.html + character.js: character detail template driven by ?id= - fruits.html + fruits.js: searchable Devil Fruit index with type filter - fruit.html + fruit.js: Devil Fruit detail template driven by ?id= - css/styles.css: new wanted-poster/ocean-navy design system, responsive - Fixed docker-compose volume mount (previously pointed at a nonexistent ./data directory) and rewrote README for the new structure Verified with a headless browser: all four page types render without script errors, search/filter interactions work, and every character- fruit cross-reference resolves correctly.
This commit is contained in:
45
js/main.js
Normal file
45
js/main.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/* Home page: character grid with search + affiliation + devil-fruit filters. */
|
||||
|
||||
(function () {
|
||||
const grid = document.getElementById('character-grid');
|
||||
const searchInput = document.getElementById('search-input');
|
||||
const affiliationSelect = document.getElementById('affiliation-select');
|
||||
const fruitOnlyCheckbox = document.getElementById('fruit-only-checkbox');
|
||||
const resultCount = document.getElementById('result-count');
|
||||
|
||||
document.getElementById('stat-characters').textContent = CHARACTERS.length;
|
||||
document.getElementById('stat-fruits').textContent = FRUITS.length;
|
||||
|
||||
const affiliations = [...new Set(CHARACTERS.map((c) => c.affiliation))].sort((a, b) => a.localeCompare(b));
|
||||
affiliations.forEach((aff) => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = aff;
|
||||
opt.textContent = aff;
|
||||
affiliationSelect.appendChild(opt);
|
||||
});
|
||||
|
||||
function applyFilters() {
|
||||
const term = searchInput.value.trim().toLowerCase();
|
||||
const affiliation = affiliationSelect.value;
|
||||
const fruitOnly = fruitOnlyCheckbox.checked;
|
||||
|
||||
const results = CHARACTERS.filter((c) => {
|
||||
if (fruitOnly && !c.devilFruit) return false;
|
||||
if (affiliation && c.affiliation !== affiliation) return false;
|
||||
if (term) {
|
||||
const haystack = `${c.name} ${c.epithet || ''} ${c.affiliation} ${c.role}`.toLowerCase();
|
||||
if (!haystack.includes(term)) return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
renderCardGrid(grid, results, characterCardHTML, 'No characters match your search. Try a different name or affiliation.');
|
||||
resultCount.textContent = `${results.length} of ${CHARACTERS.length} characters`;
|
||||
}
|
||||
|
||||
searchInput.addEventListener('input', applyFilters);
|
||||
affiliationSelect.addEventListener('change', applyFilters);
|
||||
fruitOnlyCheckbox.addEventListener('change', applyFilters);
|
||||
|
||||
applyFilters();
|
||||
})();
|
||||
Reference in New Issue
Block a user