|
|
@@ -0,0 +1,229 @@
|
|
|
+document.addEventListener('DOMContentLoaded', function() {
|
|
|
+ // 模拟数据 - 实际应用中可能来自API
|
|
|
+ const allOptions = Array.from({length: 100}, (_, i) => ({
|
|
|
+ id: i + 1,
|
|
|
+ name: `选项 ${i + 1}`,
|
|
|
+ category: i % 5 === 0 ? '热门' : '常规'
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 添加一些特殊选项
|
|
|
+ allOptions.push(
|
|
|
+ {id: 101, name: 'JavaScript', category: '技术'},
|
|
|
+ {id: 102, name: 'Python', category: '技术'},
|
|
|
+ {id: 103, name: 'Java', category: '技术'},
|
|
|
+ {id: 104, name: 'React', category: '前端'},
|
|
|
+ {id: 105, name: 'Vue', category: '前端'},
|
|
|
+ {id: 106, name: 'Angular', category: '前端'},
|
|
|
+ {id: 107, name: 'Node.js', category: '后端'},
|
|
|
+ {id: 108, name: 'Express', category: '后端'}
|
|
|
+ );
|
|
|
+
|
|
|
+ // DOM元素
|
|
|
+ const dropdownHeader = document.querySelector('.dropdown-header');
|
|
|
+ const dropdownList = document.querySelector('.dropdown-list');
|
|
|
+ const searchInput = document.querySelector('.search-input');
|
|
|
+ const optionsContainer = document.querySelector('.options-container');
|
|
|
+ const prevBtn = document.querySelector('.prev-btn');
|
|
|
+ const nextBtn = document.querySelector('.next-btn');
|
|
|
+ const currentPageEl = document.querySelector('.current-page');
|
|
|
+ const totalPagesEl = document.querySelector('.total-pages');
|
|
|
+ const selectedTagsContainer = document.querySelector('.selected-tags');
|
|
|
+ const selectedValueEl = document.querySelector('.selected-value');
|
|
|
+ const dropdownIcon = document.querySelector('.dropdown-icon');
|
|
|
+
|
|
|
+ // 状态变量
|
|
|
+ let currentPage = 1;
|
|
|
+ const itemsPerPage = 10;
|
|
|
+ let filteredOptions = [...allOptions];
|
|
|
+ let selectedOptions = [];
|
|
|
+
|
|
|
+ // 初始化
|
|
|
+ renderOptions();
|
|
|
+ updatePagination();
|
|
|
+
|
|
|
+ // 事件监听器
|
|
|
+ dropdownHeader.addEventListener('click', toggleDropdown);
|
|
|
+ searchInput.addEventListener('input', handleSearch);
|
|
|
+ prevBtn.addEventListener('click', goToPrevPage);
|
|
|
+ nextBtn.addEventListener('click', goToNextPage);
|
|
|
+
|
|
|
+ // 点击外部关闭下拉框
|
|
|
+ document.addEventListener('click', function(e) {
|
|
|
+ if (!dropdownHeader.contains(e.target) && !dropdownList.contains(e.target)) {
|
|
|
+ closeDropdown();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 切换下拉框显示/隐藏
|
|
|
+ function toggleDropdown() {
|
|
|
+ if (dropdownList.classList.contains('active')) {
|
|
|
+ closeDropdown();
|
|
|
+ } else {
|
|
|
+ openDropdown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function openDropdown() {
|
|
|
+ dropdownList.classList.add('active');
|
|
|
+ dropdownHeader.classList.add('active');
|
|
|
+ dropdownIcon.classList.add('rotated');
|
|
|
+ searchInput.focus();
|
|
|
+ }
|
|
|
+
|
|
|
+ function closeDropdown() {
|
|
|
+ dropdownList.classList.remove('active');
|
|
|
+ dropdownHeader.classList.remove('active');
|
|
|
+ dropdownIcon.classList.remove('rotated');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理搜索
|
|
|
+ function handleSearch(e) {
|
|
|
+ const searchTerm = e.target.value.toLowerCase();
|
|
|
+
|
|
|
+ if (searchTerm.trim() === '') {
|
|
|
+ filteredOptions = [...allOptions];
|
|
|
+ } else {
|
|
|
+ filteredOptions = allOptions.filter(option =>
|
|
|
+ option.name.toLowerCase().includes(searchTerm) ||
|
|
|
+ option.category.toLowerCase().includes(searchTerm)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ currentPage = 1;
|
|
|
+ renderOptions();
|
|
|
+ updatePagination();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 渲染选项
|
|
|
+ function renderOptions() {
|
|
|
+ optionsContainer.innerHTML = '';
|
|
|
+
|
|
|
+ if (filteredOptions.length === 0) {
|
|
|
+ optionsContainer.innerHTML = '<div class="no-results">未找到匹配的选项</div>';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const startIndex = (currentPage - 1) * itemsPerPage;
|
|
|
+ const endIndex = Math.min(startIndex + itemsPerPage, filteredOptions.length);
|
|
|
+ const currentOptions = filteredOptions.slice(startIndex, endIndex);
|
|
|
+
|
|
|
+ currentOptions.forEach(option => {
|
|
|
+ const isSelected = selectedOptions.some(selected => selected.id === option.id);
|
|
|
+
|
|
|
+ const optionElement = document.createElement('div');
|
|
|
+ optionElement.className = `option-item ${isSelected ? 'selected' : ''}`;
|
|
|
+ optionElement.innerHTML = `
|
|
|
+ <div>${option.name}</div>
|
|
|
+ <small style="color: #7f8c8d;">${option.category}</small>
|
|
|
+ `;
|
|
|
+
|
|
|
+ optionElement.addEventListener('click', () => toggleOption(option));
|
|
|
+ optionsContainer.appendChild(optionElement);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 切换选项选择状态
|
|
|
+ function toggleOption(option) {
|
|
|
+ const optionIndex = selectedOptions.findIndex(selected => selected.id === option.id);
|
|
|
+
|
|
|
+ if (optionIndex === -1) {
|
|
|
+ selectedOptions.push(option);
|
|
|
+ } else {
|
|
|
+ selectedOptions.splice(optionIndex, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ updateSelectedDisplay();
|
|
|
+ renderOptions();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新选中项显示
|
|
|
+ function updateSelectedDisplay() {
|
|
|
+ if (selectedOptions.length === 0) {
|
|
|
+ selectedValueEl.textContent = '请选择选项';
|
|
|
+ selectedValueEl.className = 'placeholder';
|
|
|
+ } else if (selectedOptions.length === 1) {
|
|
|
+ selectedValueEl.textContent = selectedOptions[0].name;
|
|
|
+ selectedValueEl.className = 'selected-value';
|
|
|
+ } else {
|
|
|
+ selectedValueEl.textContent = `已选择 ${selectedOptions.length} 项`;
|
|
|
+ selectedValueEl.className = 'selected-value';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新标签显示
|
|
|
+ selectedTagsContainer.innerHTML = '';
|
|
|
+
|
|
|
+ selectedOptions.forEach(option => {
|
|
|
+ const tagElement = document.createElement('div');
|
|
|
+ tagElement.className = 'selected-tag';
|
|
|
+ tagElement.innerHTML = `
|
|
|
+ ${option.name}
|
|
|
+ <button class="remove-tag" data-id="${option.id}">×</button>
|
|
|
+ `;
|
|
|
+
|
|
|
+ selectedTagsContainer.appendChild(tagElement);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 添加清除按钮
|
|
|
+ if (selectedOptions.length > 0) {
|
|
|
+ const clearBtn = document.createElement('button');
|
|
|
+ clearBtn.className = 'clear-btn';
|
|
|
+ clearBtn.textContent = '清除全部';
|
|
|
+ clearBtn.addEventListener('click', clearAllSelections);
|
|
|
+ selectedTagsContainer.appendChild(clearBtn);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加移除标签事件监听
|
|
|
+ document.querySelectorAll('.remove-tag').forEach(btn => {
|
|
|
+ btn.addEventListener('click', function(e) {
|
|
|
+ e.stopPropagation();
|
|
|
+ const id = parseInt(this.getAttribute('data-id'));
|
|
|
+ removeOption(id);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移除单个选项
|
|
|
+ function removeOption(id) {
|
|
|
+ selectedOptions = selectedOptions.filter(option => option.id !== id);
|
|
|
+ updateSelectedDisplay();
|
|
|
+ renderOptions();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清除所有选项
|
|
|
+ function clearAllSelections() {
|
|
|
+ selectedOptions = [];
|
|
|
+ updateSelectedDisplay();
|
|
|
+ renderOptions();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新分页
|
|
|
+ function updatePagination() {
|
|
|
+ const totalPages = Math.ceil(filteredOptions.length / itemsPerPage);
|
|
|
+
|
|
|
+ currentPageEl.textContent = currentPage;
|
|
|
+ totalPagesEl.textContent = totalPages;
|
|
|
+
|
|
|
+ prevBtn.disabled = currentPage === 1;
|
|
|
+ nextBtn.disabled = currentPage === totalPages || totalPages === 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 上一页
|
|
|
+ function goToPrevPage() {
|
|
|
+ if (currentPage > 1) {
|
|
|
+ currentPage--;
|
|
|
+ renderOptions();
|
|
|
+ updatePagination();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 下一页
|
|
|
+ function goToNextPage() {
|
|
|
+ const totalPages = Math.ceil(filteredOptions.length / itemsPerPage);
|
|
|
+
|
|
|
+ if (currentPage < totalPages) {
|
|
|
+ currentPage++;
|
|
|
+ renderOptions();
|
|
|
+ updatePagination();
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|