// Search and filtering functionality (function() { 'use strict'; // State management let currentFilters = { search: '', domain: '', phase: '', mode: 'selector' }; let allTools = []; let domains = []; let phases = []; // DOM elements let searchInput; let domainSelect; let phaseSelect; let resetButton; let resetEmptyButton; let toolResults; let toolsGrid; let defaultState; let noResults; let resultsTitle; let resultsCount; let resultsDescription; let viewModes; let modeButtons; // Initialize when DOM is loaded function init() { // Get data from global variables (set by template) if (typeof window.toolsData !== 'undefined') { allTools = window.toolsData; domains = window.domains || []; phases = window.phases || []; } // Get DOM elements searchInput = document.getElementById('search-input'); domainSelect = document.getElementById('domain-select'); phaseSelect = document.getElementById('phase-select'); resetButton = document.getElementById('reset-filters'); resetEmptyButton = document.getElementById('reset-filters-empty'); toolResults = document.getElementById('tool-results'); toolsGrid = document.getElementById('tools-grid'); defaultState = document.getElementById('default-state'); noResults = document.getElementById('no-results'); resultsTitle = document.getElementById('results-title'); resultsCount = document.getElementById('results-count'); resultsDescription = document.getElementById('results-description'); // View mode elements viewModes = { selector: document.getElementById('view-selector'), matrix: document.getElementById('view-matrix'), saas: document.getElementById('view-saas') }; modeButtons = { selector: document.getElementById('mode-selector'), matrix: document.getElementById('mode-matrix'), saas: document.getElementById('mode-saas') }; // Add event listeners if (searchInput) { searchInput.addEventListener('input', handleSearchChange); } if (domainSelect) { domainSelect.addEventListener('change', handleDomainChange); } if (phaseSelect) { phaseSelect.addEventListener('change', handlePhaseChange); } if (resetButton) { resetButton.addEventListener('click', resetFilters); } if (resetEmptyButton) { resetEmptyButton.addEventListener('click', resetFilters); } // Mode switching Object.keys(modeButtons).forEach(mode => { if (modeButtons[mode]) { modeButtons[mode].addEventListener('click', () => switchMode(mode)); } }); // Initialize views updateDisplay(); populateMatrix(); populateSaasGrid(); } // Event handlers function handleSearchChange(event) { currentFilters.search = event.target.value; updateDisplay(); } function handleDomainChange(event) { currentFilters.domain = event.target.value; updateDisplay(); } function handlePhaseChange(event) { currentFilters.phase = event.target.value; updateDisplay(); } function resetFilters() { currentFilters.search = ''; currentFilters.domain = ''; currentFilters.phase = ''; if (searchInput) searchInput.value = ''; if (domainSelect) domainSelect.value = ''; if (phaseSelect) phaseSelect.value = ''; updateDisplay(); } function switchMode(mode) { currentFilters.mode = mode; // Update button states Object.keys(modeButtons).forEach(m => { if (modeButtons[m]) { modeButtons[m].classList.toggle('view-mode-active', m === mode); modeButtons[m].classList.toggle('view-mode-btn', m !== mode); } }); // Update view visibility Object.keys(viewModes).forEach(m => { if (viewModes[m]) { viewModes[m].classList.toggle('hidden', m !== mode); viewModes[m].classList.toggle('view-mode-active', m === mode); } }); // Update displays based on mode if (mode === 'matrix') { populateMatrix(); } else if (mode === 'saas') { populateSaasGrid(); } else { updateDisplay(); } } // Filter tools based on current filters function filterTools() { let filtered = allTools; // Filter by type based on mode if (currentFilters.mode === 'saas') { filtered = filtered.filter(tool => tool.type === 'SaaS'); } else if (currentFilters.mode === 'selector' || currentFilters.mode === 'matrix') { filtered = filtered.filter(tool => tool.type === 'FOSS'); } // Apply search filter if (currentFilters.search) { const searchTerm = currentFilters.search.toLowerCase(); filtered = filtered.filter(tool => tool.name.toLowerCase().includes(searchTerm) || tool.description.toLowerCase().includes(searchTerm) || (tool.tags && tool.tags.some(tag => tag.toLowerCase().includes(searchTerm))) ); } // Apply domain filter (only for selector mode) if (currentFilters.mode === 'selector' && currentFilters.domain) { filtered = filtered.filter(tool => tool.domains && tool.domains.includes(currentFilters.domain) ); } // Apply phase filter (only for selector mode) if (currentFilters.mode === 'selector' && currentFilters.phase) { filtered = filtered.filter(tool => tool.phases && tool.phases.includes(currentFilters.phase) ); } return filtered; } // Update the display based on current filters function updateDisplay() { if (currentFilters.mode !== 'selector') return; const hasFilters = currentFilters.search || currentFilters.domain || currentFilters.phase; if (!hasFilters) { // Show default state if (toolResults) toolResults.classList.add('hidden'); if (defaultState) defaultState.classList.remove('hidden'); return; } const filtered = filterTools(); // Hide default state, show results if (defaultState) defaultState.classList.add('hidden'); if (toolResults) toolResults.classList.remove('hidden'); // Update results metadata if (resultsCount) resultsCount.textContent = filtered.length; updateResultsDescription(); // Show/hide no results message if (filtered.length === 0) { if (toolsGrid) toolsGrid.classList.add('hidden'); if (noResults) noResults.classList.remove('hidden'); } else { if (noResults) noResults.classList.add('hidden'); if (toolsGrid) toolsGrid.classList.remove('hidden'); renderTools(filtered); } } // Update results description text function updateResultsDescription() { if (!resultsDescription) return; const parts = []; if (currentFilters.domain) parts.push(`Bereich: ${currentFilters.domain}`); if (currentFilters.phase) parts.push(`Phase: ${currentFilters.phase}`); if (currentFilters.search) parts.push(`Suche: "${currentFilters.search}"`); resultsDescription.textContent = parts.join(' • '); } // Render tools in the grid function renderTools(tools) { if (!toolsGrid) return; toolsGrid.innerHTML = tools.map(tool => createToolCard(tool)).join(''); // Add click handlers for tool cards const toolCards = toolsGrid.querySelectorAll('.tool-card'); toolCards.forEach((card, index) => { card.addEventListener('click', () => showToolModal(tools[index])); }); } // Create HTML for a tool card function createToolCard(tool) { const typeLabel = tool.type === 'SaaS' ? 'SaaS' : ''; const tags = (tool.tags || []).slice(0, 3).map(tag => `${tag}` ).join(''); const platforms = (tool.platforms || []).join(', '); return `

${tool.name}

${typeLabel}

${tool.description}

${tags}
${tool.skillLevel} • ${tool.accessType} • ${platforms}
`; } // Populate matrix view function populateMatrix() { if (currentFilters.mode !== 'matrix') return; domains.forEach(domain => { phases.forEach(phase => { const cell = document.querySelector(`[data-domain="${domain}"][data-phase="${phase}"]`); if (!cell) return; const cellTools = allTools.filter(tool => tool.type === 'FOSS' && tool.domains && tool.domains.includes(domain) && tool.phases && tool.phases.includes(phase) && (!currentFilters.search || tool.name.toLowerCase().includes(currentFilters.search.toLowerCase()) || tool.description.toLowerCase().includes(currentFilters.search.toLowerCase()) || (tool.tags && tool.tags.some(tag => tag.toLowerCase().includes(currentFilters.search.toLowerCase())))) ); if (cellTools.length === 0) { cell.innerHTML = '
-
'; } else { cell.innerHTML = cellTools.map(tool => `
${tool.name}
` ).join(''); // Add click handlers const toolElements = cell.querySelectorAll('.matrix-cell-tool'); toolElements.forEach((element, index) => { element.addEventListener('click', () => showToolModal(cellTools[index])); }); } }); }); } // Populate SaaS grid function populateSaasGrid() { if (currentFilters.mode !== 'saas') return; const saasGrid = document.getElementById('saas-grid'); const saasCount = document.getElementById('saas-count'); const noSaasResults = document.getElementById('no-saas-results'); if (!saasGrid) return; const saasTools = filterTools(); if (saasCount) saasCount.textContent = saasTools.length; if (saasTools.length === 0) { saasGrid.classList.add('hidden'); if (noSaasResults) noSaasResults.classList.remove('hidden'); } else { if (noSaasResults) noSaasResults.classList.add('hidden'); saasGrid.classList.remove('hidden'); saasGrid.innerHTML = saasTools.map(tool => createToolCard(tool)).join(''); // Add click handlers const toolCards = saasGrid.querySelectorAll('.tool-card'); toolCards.forEach((card, index) => { card.addEventListener('click', () => showToolModal(saasTools[index])); }); } } // Show tool modal (defined in modal.js) function showToolModal(tool) { if (typeof window.showToolModal === 'function') { window.showToolModal(tool); } } // Export for use by other scripts window.searchModule = { init, filterTools, updateDisplay, populateMatrix, populateSaasGrid, resetFilters }; // Auto-initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();