feat: add list template with category tabs and dynamic content filtering

This commit is contained in:
Greg 2025-05-25 21:18:55 +02:00
parent 5ee5bf85e4
commit 7ec04f2b5c

View File

@ -27,38 +27,58 @@
</div> </div>
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
const tabsContainer = document.getElementById('tabs'); console.log('SCRIPT: DOMContentLoaded event fired.');
const originalTabs = Array.from(tabsContainer.querySelectorAll('.tab')); // Tabs defined in HTML
const cardsContainer = document.getElementById('cards');
const allCards = Array.from(cardsContainer.children); // These are the <a> elements
// Get the current section and section-to-category mappings const tabsContainer = document.getElementById('tabs');
const currentSection = tabsContainer.getAttribute('data-current-section'); console.log('SCRIPT: tabsContainer:', tabsContainer);
let sectionMappings = {}; if (!tabsContainer) {
try { console.error('SCRIPT ERROR: Could not find tabsContainer (#tabs). Stopping script.');
sectionMappings = JSON.parse(tabsContainer.getAttribute('data-section-mappings')); return;
} catch (e) { }
console.error('Error parsing section mappings:', e);
const originalTabs = Array.from(tabsContainer.querySelectorAll('.tab'));
console.log('SCRIPT: originalTabs (from HTML):', originalTabs, 'Count:', originalTabs.length);
const cardsContainer = document.getElementById('cards');
console.log('SCRIPT: cardsContainer:', cardsContainer);
if (!cardsContainer) {
console.error('SCRIPT ERROR: Could not find cardsContainer (#cards). Stopping script.');
return;
}
const allCards = Array.from(cardsContainer.children);
console.log('SCRIPT: allCards (direct children of #cards):', allCards, 'Count:', allCards.length);
const currentSection = tabsContainer.getAttribute('data-current-section');
console.log('SCRIPT: currentSection (from data-current-section):', currentSection);
let sectionMappings = {};
try {
const mappingsAttr = tabsContainer.getAttribute('data-section-mappings');
console.log('SCRIPT: data-section-mappings attribute:', mappingsAttr);
if (mappingsAttr) {
sectionMappings = JSON.parse(mappingsAttr);
}
console.log('SCRIPT: parsed sectionMappings:', sectionMappings);
} catch (e) {
console.error('SCRIPT ERROR: Error parsing section mappings:', e);
} }
// Map the current section to its corresponding category
const currentCategory = sectionMappings[currentSection] || null; const currentCategory = sectionMappings[currentSection] || null;
console.log('SCRIPT: currentCategory (mapped from currentSection):', currentCategory);
// Get all category values from the tabs
const knownCategories = originalTabs.map(tab => tab.getAttribute('data-tab')); const knownCategories = originalTabs.map(tab => tab.getAttribute('data-tab'));
console.log('SCRIPT: knownCategories (from originalTabs):', knownCategories);
// Create and prepend the "All" tab console.log('SCRIPT: Creating and prepending "All" tab...');
const allTab = document.createElement('div'); const allTab = document.createElement('div');
allTab.className = 'tab'; allTab.className = 'tab';
allTab.textContent = 'All'; allTab.textContent = 'All';
allTab.setAttribute('data-tab', 'all'); allTab.setAttribute('data-tab', 'all');
tabsContainer.prepend(allTab); tabsContainer.prepend(allTab);
console.log('SCRIPT: "All" tab prepended:', allTab);
// Function to activate a tab and filter cards
function activateTabAndFilter(selectedCategory) { function activateTabAndFilter(selectedCategory) {
console.log('Filtering by category:', selectedCategory); console.log('FUNC activateTabAndFilter: Filtering by category:', selectedCategory);
// Update active state for all tabs
document.querySelectorAll('#tabs .tab').forEach(t => { document.querySelectorAll('#tabs .tab').forEach(t => {
if (t.getAttribute('data-tab') === selectedCategory) { if (t.getAttribute('data-tab') === selectedCategory) {
t.classList.add('active'); t.classList.add('active');
@ -66,61 +86,65 @@ document.addEventListener('DOMContentLoaded', function() {
t.classList.remove('active'); t.classList.remove('active');
} }
}); });
console.log('FUNC activateTabAndFilter: Active states updated for tabs.');
// Filter cards
let visibleCount = 0; let visibleCount = 0;
allCards.forEach(cardLinkElement => { // Renamed 'card' to 'cardLinkElement' for clarity allCards.forEach(cardLinkElement => {
const cardDiv = cardLinkElement.querySelector('.card'); // Get the nested <div class="card"> const cardDiv = cardLinkElement.querySelector('.card');
if (!cardDiv) { if (!cardDiv) {
console.warn('Card structure issue: .card div not found inside', cardLinkElement); console.warn('FUNC activateTabAndFilter: Card structure issue: .card div not found inside', cardLinkElement);
cardLinkElement.style.display = 'none'; // Hide if structure is wrong cardLinkElement.style.display = 'none';
return; // Skip this card return;
} }
if (selectedCategory === 'all') { if (selectedCategory === 'all') {
cardLinkElement.style.display = ''; cardLinkElement.style.display = '';
visibleCount++; visibleCount++;
} else { } else {
const cardCategory = cardDiv.getAttribute('data-category'); // Get category from the .card div const cardCategoryAttr = cardDiv.getAttribute('data-category');
// Detailed log for comparison
const sCat = selectedCategory ? selectedCategory : 'null_or_empty'; const sCat = selectedCategory ? selectedCategory : 'null_or_empty';
const cCat = cardCategory ? cardCategory : 'null_or_empty'; const cCat = cardCategoryAttr ? cardCategoryAttr : 'null_or_empty';
console.log( console.log(
`Comparing: cardCategory='${cCat}' (length ${cCat.length})` + `FUNC activateTabAndFilter: Comparing: cardCategory='${cCat}' (length ${cCat.length})` +
` vs selectedCategory='${sCat}' (length ${sCat.length})` + ` vs selectedCategory='${sCat}' (length ${sCat.length})` +
` for card titled: '${cardDiv.querySelector('.card-title') ? cardDiv.querySelector('.card-title').textContent.trim() : 'N/A'}'` ` for card titled: '${cardDiv.querySelector('.card-title') ? cardDiv.querySelector('.card-title').textContent.trim() : 'N/A'}'`
); );
const isVisible = (cardCategoryAttr === selectedCategory);
const isVisible = (cardCategory === selectedCategory);
cardLinkElement.style.display = isVisible ? '' : 'none'; cardLinkElement.style.display = isVisible ? '' : 'none';
if (isVisible) visibleCount++; if (isVisible) visibleCount++;
} }
}); });
console.log('Visible cards after filtering:', visibleCount); console.log('FUNC activateTabAndFilter: Visible cards after filtering:', visibleCount);
} }
// Determine initial category to display
let initialCategoryToDisplay = 'all'; let initialCategoryToDisplay = 'all';
// If we're on a section page and we have a mapping for this section,
// use the corresponding category
if (currentSection && currentCategory && knownCategories.includes(currentCategory)) { if (currentSection && currentCategory && knownCategories.includes(currentCategory)) {
initialCategoryToDisplay = currentCategory; initialCategoryToDisplay = currentCategory;
console.log('Initial category set to', initialCategoryToDisplay, 'based on section', currentSection);
} }
console.log('SCRIPT: initialCategoryToDisplay determined as:', initialCategoryToDisplay);
// Attach click listeners to all tabs (including the new "All" tab) console.log('SCRIPT: Attaching click listeners to tabs...');
document.querySelectorAll('#tabs .tab').forEach(tab => { const allTabsForListeners = document.querySelectorAll('#tabs .tab');
console.log('SCRIPT: Found', allTabsForListeners.length, 'tabs to attach listeners to.');
allTabsForListeners.forEach((tab, index) => {
console.log(`SCRIPT: Attaching listener to tab ${index + 1}:`, tab);
tab.addEventListener('click', function() { tab.addEventListener('click', function() {
console.log('EVENT HANDLER: Tab clicked:', this);
const categoryToFilter = this.getAttribute('data-tab'); const categoryToFilter = this.getAttribute('data-tab');
console.log('EVENT HANDLER: Category to filter (from data-tab):', categoryToFilter);
if (!categoryToFilter) {
console.error('EVENT HANDLER ERROR: data-tab attribute is missing or empty for the clicked tab:', this);
return;
}
activateTabAndFilter(categoryToFilter); activateTabAndFilter(categoryToFilter);
}); });
}); });
console.log('SCRIPT: Finished attaching click listeners.');
// Initial filter and active tab setup console.log('SCRIPT: Calling activateTabAndFilter for initial page load with category:', initialCategoryToDisplay);
activateTabAndFilter(initialCategoryToDisplay); activateTabAndFilter(initialCategoryToDisplay);
console.log('SCRIPT: Initial page load filtering complete.');
}); });
</script> </script>
{{ end }} {{ end }}