107 lines
3.8 KiB
JavaScript
107 lines
3.8 KiB
JavaScript
document.addEventListener("DOMContentLoaded", () => {
|
|
const authorSearchInput = document.getElementById(
|
|
"author-search-input"
|
|
);
|
|
const authorDropdown = document.getElementById("author-dropdown");
|
|
const selectedAuthorsContainer = document.getElementById(
|
|
"selected-authors-container"
|
|
);
|
|
const dropdownItems = authorDropdown.querySelectorAll('[data-value]');
|
|
let selectedAuthors = new Set();
|
|
|
|
// Function to update highlights in dropdown
|
|
const updateDropdownHighlights = () => {
|
|
dropdownItems.forEach(item => {
|
|
const value = item.dataset.value;
|
|
if (selectedAuthors.has(value)) {
|
|
item.classList.add('bg-blue-200');
|
|
} else {
|
|
item.classList.remove('bg-blue-200');
|
|
}
|
|
});
|
|
};
|
|
|
|
// Function to render selected authors
|
|
const renderSelectedAuthors = () => {
|
|
// Clear existing chips, but keep the input field
|
|
Array.from(selectedAuthorsContainer.children).forEach((child) => {
|
|
if (child.id !== "author-search-input") {
|
|
child.remove();
|
|
}
|
|
});
|
|
|
|
selectedAuthors.forEach((author) => {
|
|
const authorChip = document.createElement("span");
|
|
authorChip.className =
|
|
"flex items-center bg-blue-100 text-blue-800 text-sm font-medium px-2.5 py-0.5 rounded-full";
|
|
authorChip.innerHTML = `
|
|
${author}
|
|
<button type="button" class="ml-1 inline-flex items-center p-0.5 text-sm text-blue-400 bg-transparent rounded-sm hover:bg-blue-200 hover:text-blue-900" data-author="${author}">
|
|
<svg class="w-2 h-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
|
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
|
|
</svg>
|
|
<span class="sr-only">Remove author</span>
|
|
</button>
|
|
`;
|
|
selectedAuthorsContainer.insertBefore(
|
|
authorChip,
|
|
authorSearchInput
|
|
);
|
|
});
|
|
updateDropdownHighlights(); // Update highlights after rendering
|
|
authorSearchInput.focus(); // Keep focus on the input
|
|
};
|
|
|
|
// Handle input focus to show dropdown
|
|
authorSearchInput.addEventListener("focus", () => {
|
|
authorDropdown.classList.remove("hidden");
|
|
});
|
|
|
|
// Handle input for filtering
|
|
authorSearchInput.addEventListener('input', () => {
|
|
const query = authorSearchInput.value.toLowerCase();
|
|
dropdownItems.forEach(item => {
|
|
const text = item.textContent.toLowerCase();
|
|
item.style.display = text.includes(query) ? 'block' : 'none';
|
|
});
|
|
authorDropdown.classList.remove('hidden');
|
|
});
|
|
|
|
// Handle clicks outside to hide dropdown
|
|
document.addEventListener("click", (event) => {
|
|
if (
|
|
!selectedAuthorsContainer.contains(event.target) &&
|
|
!authorDropdown.contains(event.target)
|
|
) {
|
|
authorDropdown.classList.add("hidden");
|
|
}
|
|
});
|
|
|
|
// Handle author selection from dropdown
|
|
authorDropdown.addEventListener("click", (event) => {
|
|
const selectedValue = event.target.dataset.value;
|
|
if (selectedValue) {
|
|
if (selectedAuthors.has(selectedValue)) {
|
|
selectedAuthors.delete(selectedValue);
|
|
} else {
|
|
selectedAuthors.add(selectedValue);
|
|
}
|
|
authorSearchInput.value = ""; // Clear input after selection
|
|
renderSelectedAuthors();
|
|
// Keep dropdown open for further selections
|
|
}
|
|
});
|
|
|
|
// Handle removing selected author chip
|
|
selectedAuthorsContainer.addEventListener("click", (event) => {
|
|
if (event.target.closest("button")) {
|
|
const authorToRemove =
|
|
event.target.closest("button").dataset.author;
|
|
selectedAuthors.delete(authorToRemove);
|
|
renderSelectedAuthors();
|
|
}
|
|
});
|
|
|
|
// Initial render and highlights
|
|
renderSelectedAuthors();
|
|
}); |