// File: ./src/js/modal.js // Tool detail modal functionality (function() { 'use strict'; let modal; let modalContent; let currentTool = null; // Initialize modal system function init() { modal = document.getElementById('tool-modal'); modalContent = document.getElementById('tool-modal-content'); if (!modal || !modalContent) { console.warn('Modal elements not found'); return; } // Add event listeners setupEventListeners(); } // Set up event listeners for modal function setupEventListeners() { // Click outside modal to close modal.addEventListener('click', (event) => { if (event.target === modal) { closeModal(); } }); // Escape key to close modal document.addEventListener('keydown', (event) => { if (event.key === 'Escape' && !modal.classList.contains('hidden')) { closeModal(); } }); // Prevent body scroll when modal is open modal.addEventListener('scroll', (event) => { event.stopPropagation(); }); } // Show tool detail modal function showToolModal(tool) { if (!tool || !modal || !modalContent) return; currentTool = tool; // Generate modal content modalContent.innerHTML = generateModalContent(tool); // Add close button handler const closeButton = modalContent.querySelector('.modal-close'); if (closeButton) { closeButton.addEventListener('click', closeModal); } // Add external link handler const externalLink = modalContent.querySelector('.external-link'); if (externalLink) { externalLink.addEventListener('click', (event) => { // Let the link work normally, but track the click trackToolClick(tool); }); } // Show modal modal.classList.remove('hidden'); document.body.style.overflow = 'hidden'; // Focus trap trapFocus(); } // Close modal function closeModal() { if (!modal) return; modal.classList.add('hidden'); document.body.style.overflow = ''; currentTool = null; // Return focus to the tool card that was clicked const activeToolCard = document.querySelector('.tool-card:focus'); if (activeToolCard) { activeToolCard.focus(); } } // Generate modal HTML content function generateModalContent(tool) { const typeLabel = tool.type === 'SaaS' ? 'SaaS' : 'FOSS'; const domains = (tool.domains || []).map(domain => `${domain}` ).join(''); const phases = (tool.phases || []).map(phase => `${phase}` ).join(''); const tags = (tool.tags || []).map(tag => `${tag}` ).join(''); const platforms = (tool.platforms || []).join(', '); // Handle service URL for self-hosted services const serviceInfo = tool.selfHosted && tool.serviceUrl ? `

Lab Instance: ${tool.serviceUrl}

` : ''; return `

${tool.name}

${typeLabel} ${tool.skillLevel}

${tool.description}

${serviceInfo}

Bereiche

${domains || 'Keine angegeben'}

Phasen

${phases || 'Keine angegeben'}

Tags

${tags || 'Keine Tags'}
Zugriff: ${tool.accessType}
Plattformen: ${platforms}
Projekt öffnen
`; } // Simple focus trap for modal function trapFocus() { const focusableElements = modal.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); if (focusableElements.length === 0) return; const firstElement = focusableElements[0]; const lastElement = focusableElements[focusableElements.length - 1]; // Focus first element firstElement.focus(); // Handle tab key modal.addEventListener('keydown', (event) => { if (event.key !== 'Tab') return; if (event.shiftKey) { // Shift + Tab if (document.activeElement === firstElement) { event.preventDefault(); lastElement.focus(); } } else { // Tab if (document.activeElement === lastElement) { event.preventDefault(); firstElement.focus(); } } }); } // Track tool clicks for analytics (placeholder) function trackToolClick(tool) { // This is where you'd send analytics data console.log('Tool clicked:', tool.name, tool.url); // Could send to analytics service: // analytics.track('tool_clicked', { // tool_name: tool.name, // tool_type: tool.type, // tool_url: tool.url // }); } // Export functions for use by other scripts window.showToolModal = showToolModal; window.closeToolModal = closeModal; // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();