// File: ./src/js/search.js // 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.description}