mirror of
https://github.com/Dvorinka/PPve.git
synced 2026-06-04 12:32:59 +00:00
te
This commit is contained in:
+60
-129
@@ -1214,21 +1214,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Icon Picker Dropdown -->
|
<!-- Icon Picker Container -->
|
||||||
<div id="iconPickerDropdown" class="hidden absolute z-50 bg-white rounded-lg shadow-lg border border-gray-200 w-full max-w-[400px]">
|
<div id="iconPickerContainer" class="relative">
|
||||||
<div class="p-4">
|
<div id="iconPickerDropdown" class="hidden absolute z-50 bg-white rounded-lg shadow-lg border border-gray-200 w-full max-w-[400px]">
|
||||||
<div class="flex justify-between items-center mb-4">
|
<div class="p-4">
|
||||||
<h3 class="text-sm font-medium text-gray-700">Vyberte ikonu</h3>
|
<div class="flex justify-between items-center mb-4">
|
||||||
<button id="closeIconPicker" class="text-gray-400 hover:text-gray-500 p-1">
|
<h3 class="text-sm font-medium text-gray-700">Vyberte ikonu</h3>
|
||||||
<i class="fas fa-times"></i>
|
<button id="closeIconPicker" class="text-gray-400 hover:text-gray-500 p-1">
|
||||||
</button>
|
<i class="fas fa-times"></i>
|
||||||
</div>
|
</button>
|
||||||
<div class="mb-4">
|
</div>
|
||||||
<input type="text" id="iconSearch" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Hledat ikony..." autocomplete="off">
|
<div class="mb-4">
|
||||||
</div>
|
<input type="text" id="iconSearch" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Hledat ikony..." autocomplete="off">
|
||||||
<div class="max-h-[400px] overflow-y-auto">
|
</div>
|
||||||
<div id="iconList" class="grid grid-cols-4 gap-3">
|
<div class="max-h-[400px] overflow-y-auto">
|
||||||
<!-- Icons will be populated by JavaScript -->
|
<div id="iconList" class="grid grid-cols-4 gap-3">
|
||||||
|
<!-- Icons will be populated by JavaScript -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -2443,96 +2445,67 @@ function initIconPicker() {
|
|||||||
|
|
||||||
if (!iconInput || !iconDropdown) return;
|
if (!iconInput || !iconDropdown) return;
|
||||||
|
|
||||||
let isDropdownOpen = false;
|
// Simple toggle function
|
||||||
let isMouseOverDropdown = false;
|
function toggleDropdown() {
|
||||||
let isMouseOverInput = false;
|
iconDropdown.classList.toggle('hidden');
|
||||||
|
if (!iconDropdown.classList.contains('hidden')) {
|
||||||
// Position dropdown relative to input
|
// Position and focus
|
||||||
function positionDropdown() {
|
const rect = iconInput.getBoundingClientRect();
|
||||||
const rect = iconInput.getBoundingClientRect();
|
iconDropdown.style.top = `${rect.bottom + window.scrollY}px`;
|
||||||
iconDropdown.style.top = `${rect.bottom + window.scrollY}px`;
|
iconDropdown.style.left = `${rect.left + window.scrollX}px`;
|
||||||
iconDropdown.style.left = `${rect.left + window.scrollX}px`;
|
iconDropdown.style.width = `${rect.width}px`;
|
||||||
iconDropdown.style.width = `${rect.width}px`;
|
|
||||||
}
|
if (iconSearch) {
|
||||||
|
iconSearch.value = '';
|
||||||
// Toggle dropdown
|
renderIcons('');
|
||||||
function toggleDropdown(open) {
|
iconSearch.focus();
|
||||||
if (open !== undefined) {
|
}
|
||||||
isDropdownOpen = open;
|
|
||||||
} else {
|
|
||||||
isDropdownOpen = !isDropdownOpen;
|
|
||||||
}
|
|
||||||
iconDropdown.classList.toggle('hidden', !isDropdownOpen);
|
|
||||||
|
|
||||||
if (isDropdownOpen) {
|
|
||||||
positionDropdown();
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
if (iconSearch) {
|
|
||||||
iconSearch.value = '';
|
|
||||||
renderIcons('');
|
|
||||||
iconSearch.focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle mouse enter/leave events
|
// Close dropdown
|
||||||
iconInput.addEventListener('mouseenter', () => {
|
function closeDropdown() {
|
||||||
isMouseOverInput = true;
|
iconDropdown.classList.add('hidden');
|
||||||
});
|
|
||||||
|
|
||||||
iconInput.addEventListener('mouseleave', () => {
|
|
||||||
isMouseOverInput = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
iconDropdown.addEventListener('mouseenter', () => {
|
|
||||||
isMouseOverDropdown = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
iconDropdown.addEventListener('mouseleave', () => {
|
|
||||||
isMouseOverDropdown = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle click outside
|
|
||||||
function handleClickOutside(e) {
|
|
||||||
if (isDropdownOpen && !isMouseOverDropdown && !isMouseOverInput) {
|
|
||||||
toggleDropdown(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle icon input click
|
// Handle icon input click
|
||||||
iconInput.addEventListener('click', (e) => {
|
iconInput.addEventListener('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
toggleDropdown(true);
|
toggleDropdown();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Close dropdown handlers
|
|
||||||
if (closeButton) {
|
|
||||||
closeButton.addEventListener('click', (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
toggleDropdown(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close when clicking outside
|
// Close when clicking outside
|
||||||
document.addEventListener('click', handleClickOutside);
|
document.addEventListener('click', (e) => {
|
||||||
|
if (!iconDropdown.classList.contains('hidden') &&
|
||||||
|
!iconDropdown.contains(e.target) &&
|
||||||
|
e.target !== iconInput) {
|
||||||
|
closeDropdown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close on Escape
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'Escape' && !iconDropdown.classList.contains('hidden')) {
|
||||||
|
closeDropdown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Handle icon selection
|
// Handle icon selection
|
||||||
if (iconList) {
|
if (iconList) {
|
||||||
iconList.addEventListener('click', (e) => {
|
iconList.addEventListener('click', (e) => {
|
||||||
const iconOption = e.target.closest('.icon-option');
|
const iconOption = e.target.closest('.icon-option');
|
||||||
if (iconOption && isDropdownOpen) {
|
if (iconOption && !iconDropdown.classList.contains('hidden')) {
|
||||||
const iconClass = iconOption.getAttribute('data-icon');
|
const iconClass = iconOption.getAttribute('data-icon');
|
||||||
if (iconClass) {
|
if (iconClass) {
|
||||||
selectIcon(iconClass);
|
selectIcon(iconClass);
|
||||||
toggleDropdown(false);
|
closeDropdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle search with improved debounce
|
// Handle search
|
||||||
if (iconSearch) {
|
if (iconSearch) {
|
||||||
let searchTimeout;
|
let searchTimeout;
|
||||||
iconSearch.addEventListener('input', (e) => {
|
iconSearch.addEventListener('input', (e) => {
|
||||||
@@ -2547,56 +2520,14 @@ function initIconPicker() {
|
|||||||
// Initial render
|
// Initial render
|
||||||
renderIcons('');
|
renderIcons('');
|
||||||
|
|
||||||
// Close on Escape
|
// Cleanup on window unload
|
||||||
document.addEventListener('keydown', (e) => {
|
window.addEventListener('unload', () => {
|
||||||
if (e.key === 'Escape' && isDropdownOpen) {
|
iconInput.removeEventListener('click', toggleDropdown);
|
||||||
toggleDropdown(false);
|
document.removeEventListener('click', closeDropdown);
|
||||||
}
|
document.removeEventListener('keydown', closeDropdown);
|
||||||
|
if (iconList) iconList.removeEventListener('click', selectIcon);
|
||||||
|
if (iconSearch) iconSearch.removeEventListener('input', renderIcons);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update position on scroll
|
|
||||||
window.addEventListener('scroll', () => {
|
|
||||||
if (isDropdownOpen) {
|
|
||||||
positionDropdown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update position on window resize
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
if (isDropdownOpen) {
|
|
||||||
positionDropdown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clean up event listeners when component is removed
|
|
||||||
const cleanup = () => {
|
|
||||||
iconInput.removeEventListener('mouseenter', () => {
|
|
||||||
isMouseOverInput = true;
|
|
||||||
});
|
|
||||||
iconInput.removeEventListener('mouseleave', () => {
|
|
||||||
isMouseOverInput = false;
|
|
||||||
});
|
|
||||||
iconDropdown.removeEventListener('mouseenter', () => {
|
|
||||||
isMouseOverDropdown = true;
|
|
||||||
});
|
|
||||||
iconDropdown.removeEventListener('mouseleave', () => {
|
|
||||||
isMouseOverDropdown = false;
|
|
||||||
});
|
|
||||||
document.removeEventListener('click', handleClickOutside);
|
|
||||||
window.removeEventListener('scroll', () => {
|
|
||||||
if (isDropdownOpen) {
|
|
||||||
positionDropdown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
window.removeEventListener('resize', () => {
|
|
||||||
if (isDropdownOpen) {
|
|
||||||
positionDropdown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add cleanup to window beforeunload
|
|
||||||
window.addEventListener('beforeunload', cleanup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render icons based on search term
|
// Render icons based on search term
|
||||||
|
|||||||
Reference in New Issue
Block a user