class IconPicker { constructor() { this.modal = null; this.container = null; this.searchInput = null; this.iconList = null; this.closeButton = null; this.isInitialized = false; this.isModalOpen = false; this.icons = []; this.currentSearch = ''; this.eventListeners = []; } static getInstance() { if (!window._iconPickerInstance) { window._iconPickerInstance = new IconPicker(); } return window._iconPickerInstance; } init() { if (this.isInitialized) return; // Check if DOM is ready if (!document.body) { console.error('DOM not ready - cannot initialize icon picker'); return; } // Create modal structure this.modal = document.createElement('div'); this.modal.className = 'icon-picker-modal fixed inset-0 bg-black bg-opacity-50 z-50 hidden'; this.modal.innerHTML = `
Žádné ikony nenalezeny
`; this.iconList.appendChild(noResults); } } setupEventListeners() { // Close button const closeHandler = () => this.close(); this.closeButton.addEventListener('click', closeHandler); this.eventListeners.push({ element: this.closeButton, event: 'click', handler: closeHandler }); // Search input const searchHandler = (e) => { const searchTerm = e.target.value.toLowerCase(); this.renderIcons(searchTerm); }; this.searchInput.addEventListener('input', searchHandler); this.eventListeners.push({ element: this.searchInput, event: 'input', handler: searchHandler }); // Document click - close when clicking outside const clickHandler = (e) => { if (this.isModalOpen && !this.container.contains(e.target)) { this.close(); } }; document.addEventListener('click', clickHandler); this.eventListeners.push({ element: document, event: 'click', handler: clickHandler }); // Escape key const keydownHandler = (e) => { if (e.key === 'Escape' && this.isModalOpen) { this.close(); } }; document.addEventListener('keydown', keydownHandler); this.eventListeners.push({ element: document, event: 'keydown', handler: keydownHandler }); // Icon selection const iconClickHandler = (e) => { const iconOption = e.target.closest('.icon-option'); if (iconOption && iconOption.dataset.icon) { this.selectIcon(iconOption.dataset.icon); } }; this.iconList.addEventListener('click', iconClickHandler); this.eventListeners.push({ element: this.iconList, event: 'click', handler: iconClickHandler }); } cleanupEventListeners() { this.eventListeners.forEach(listener => { const { element, event, handler } = listener; element.removeEventListener(event, handler); }); this.eventListeners = []; } close() { if (!this.isModalOpen) return; this.isModalOpen = false; this.modal.style.display = 'none'; document.body.style.overflow = ''; // Clear search this.searchInput.value = ''; this.renderIcons(''); // Cleanup event listeners this.cleanupEventListeners(); } open() { if (!this.isInitialized) this.init(); if (this.isModalOpen) return; this.isModalOpen = true; this.modal.style.display = 'flex'; document.body.style.overflow = 'hidden'; // Focus search input requestAnimationFrame(() => { this.searchInput.focus(); this.searchInput.value = ''; this.renderIcons(''); }); } close() { if (!this.isModalOpen) return; this.isModalOpen = false; this.modal.style.display = 'none'; document.body.style.overflow = ''; // Clear search this.searchInput.value = ''; this.renderIcons(''); } selectIcon(iconClass) { // Get target elements const selectedIcon = document.getElementById('selectedIcon'); const customIconPreview = document.getElementById('customIconPreview'); const iconPreview = document.getElementById('iconPreview'); const appIcon = document.getElementById('appIcon'); const customIconInput = document.getElementById('customIconInput'); // Update selected icon if (selectedIcon) { selectedIcon.className = `fas ${iconClass} text-2xl text-gray-400`; selectedIcon.classList.remove('hidden'); } // Hide custom icon preview if (customIconPreview) { customIconPreview.src = ''; customIconPreview.classList.add('hidden'); } // Update app icon if (appIcon) { appIcon.value = iconClass; appIcon.dispatchEvent(new Event('change')); } // Reset custom icon input if (customIconInput) { customIconInput.value = ''; customIconInput.dispatchEvent(new Event('change')); } // Update preview if (iconPreview) { const colors = ['blue', 'green', 'red', 'yellow', 'indigo', 'purple', 'pink', 'gray']; const randomColor = colors[Math.floor(Math.random() * colors.length)]; iconPreview.className = `mt-2 flex items-center justify-center w-16 h-16 bg-${randomColor}-100 rounded-md overflow-hidden`; iconPreview.innerHTML = ``; } // Close modal this.close(); } static getInstance() { if (!window.iconPickerInstance) { window.iconPickerInstance = new IconPicker(); } return window.iconPickerInstance; } }