Поговорим о...
|
|
AleXStam | Дата: Понедельник, 2025-06-23, 11:21 | Сообщение # 76 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| // В функции обработки поиска: function handleSearch(query) { // ... ваш существующий код ...
// Добавьте этот вызов: if (window.manageTreeSearch) { window.manageTreeSearch(query); } }
// Для мгновенного поиска при вводе const searchInput = document.querySelector('.search-input'); if (searchInput) { searchInput.addEventListener('input', function(e) { if (window.manageTreeSearch) { window.manageTreeSearch(e.target.value); } }); }
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 11:29 | Сообщение # 77 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| <div class="tree-container"> {{ $level := .level | default 1 }} <ul class="tree-ul level-{{ $level }}"> {{ range .nodes }} <li class="tree-item {{ if .children }}has-children{{ end }} {{ .state | default "closed" }}" data-search-text="{{ lower .name }}"> <div class="tree-line"> {{ if .children }} <span class="tree-arrow">›</span> {{ else }} <span class="tree-dot">•</span> {{ end }} <span class="tree-name">{{ .name }}</span> </div> {{ if .children }} {{ partial "tree" (dict "nodes" .children "level" (add $level 1)) }} {{ end }} </li> {{ end }} </ul> </div>
<script> (function() { // Инициализация дерева function initTree() { // Закрываем все узлы по умолчанию document.querySelectorAll('.tree-item.has-children').forEach(item => { if (!item.classList.contains('open')) { item.querySelector('.tree-ul').style.display = 'none'; } });
// Обработчики кликов document.querySelectorAll('.tree-line').forEach(line => { line.addEventListener('click', function() { const item = this.parentElement; if (item.classList.contains('has-children')) { const isOpen = item.classList.contains('open'); item.classList.toggle('open', !isOpen); item.querySelector('.tree-ul').style.display = isOpen ? 'none' : 'block'; } }); }); }
// Поиск по дереву function searchTree(query) { const term = query.toLowerCase().trim(); // Сбрасываем предыдущие результаты document.querySelectorAll('.tree-item').forEach(item => { item.classList.remove('highlighted'); });
if (!term) return;
// Ищем совпадения document.querySelectorAll('.tree-item').forEach(item => { const text = item.getAttribute('data-search-text'); if (text.includes(term)) { item.classList.add('highlighted'); // Раскрываем родителей let parent = item.parentElement.closest('.tree-item'); while (parent) { parent.classList.add('open'); parent.querySelector('.tree-ul').style.display = 'block'; parent = parent.parentElement.closest('.tree-item'); } // Прокрутка к первому найденному элементу const firstMatch = document.querySelector('.tree-item.highlighted'); if (firstMatch) { firstMatch.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } } }); }
// Инициализация при загрузке document.addEventListener('DOMContentLoaded', function() { initTree();
// Обработчики для поиска const searchInput = document.getElementById('tree-search-input'); const clearButton = document.getElementById('tree-search-clear');
searchInput.addEventListener('input', function() { searchTree(this.value); });
clearButton.addEventListener('click', function() { searchInput.value = ''; searchTree(''); }); }); })(); </script>
<style> /* Ваши существующие стили дерева */ .tree-container { font-family: sans-serif; font-size: 14px; } .tree-ul { list-style: none; padding-left: 20px; margin: 0; } .tree-item { margin: 2px 0; } .tree-line { display: flex; align-items: center; cursor: pointer; padding: 2px 0; } .tree-arrow, .tree-dot { width: 16px; margin-right: 4px; } .tree-arrow { transition: transform 0.2s; } .tree-item.open > .tree-line > .tree-arrow { transform: rotate(90deg); } .tree-item > .tree-ul { display: none; } .tree-item.open > .tree-ul { display: block; }
/* Подсветка найденных элементов */ .tree-item.highlighted > .tree-line > .tree-name { background-color: #fff8c5; border-radius: 3px; padding: 0 2px; } </style>
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 11:30 | Сообщение # 78 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| <div class="tree-search-box"> <input type="text" id="tree-search-input" placeholder="Поиск в дереве..." class="tree-search-input"> <button id="tree-search-clear" class="tree-search-clear">×</button> </div>
<style> .tree-search-box { position: relative; margin-bottom: 15px; max-width: 300px; }
.tree-search-input { width: 100%; padding: 8px 30px 8px 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; }
.tree-search-clear { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; font-size: 16px; color: #999; } </style>
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 11:37 | Сообщение # 79 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| <div class="tree-search-panel"> <div class="tree-search-box"> <input type="text" id="tree-search-input" placeholder="Поиск в дереве..." class="tree-search-input"> <button id="tree-search-btn" class="tree-search-btn">Найти</button> <button id="tree-search-clear" class="tree-search-clear">×</button> </div> <div class="search-modes"> <label><input type="radio" name="search-mode" value="instant" checked> Мгновенный поиск</label> <label><input type="radio" name="search-mode" value="button"> Поиск по кнопке</label> </div> </div>
<style> .tree-search-panel { margin-bottom: 15px; max-width: 400px; }
.tree-search-box { position: relative; display: flex; margin-bottom: 8px; }
.tree-search-input { flex: 1; padding: 8px 35px 8px 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; }
.tree-search-btn { margin-left: 8px; padding: 0 12px; background: #f0f0f0; border: 1px solid #ddd; border-radius: 4px; cursor: pointer; }
.tree-search-clear { position: absolute; right: 90px; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; font-size: 16px; color: #999; }
.search-modes { font-size: 13px; color: #666; }
.search-modes label { margin-right: 10px; cursor: pointer; } </style>
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 11:38 | Сообщение # 80 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| (function() { // Инициализация дерева function initTree() { // Закрываем все узлы по умолчанию document.querySelectorAll('.tree-item.has-children').forEach(item => { if (!item.classList.contains('open')) { item.querySelector('.tree-ul').style.display = 'none'; } });
// Обработчики кликов document.querySelectorAll('.tree-line').forEach(line => { line.addEventListener('click', function() { const item = this.parentElement; if (item.classList.contains('has-children')) { const isOpen = item.classList.contains('open'); item.classList.toggle('open', !isOpen); item.querySelector('.tree-ul').style.display = isOpen ? 'none' : 'block'; } }); }); }
// Поиск по дереву function searchTree(query) { const term = query.toLowerCase().trim(); // Сбрасываем предыдущие результаты document.querySelectorAll('.tree-item').forEach(item => { item.classList.remove('highlighted'); });
if (!term) return;
// Ищем совпадения let foundItems = []; document.querySelectorAll('.tree-item').forEach(item => { const text = item.getAttribute('data-search-text'); if (text.includes(term)) { item.classList.add('highlighted'); foundItems.push(item); // Раскрываем родителей let parent = item.parentElement.closest('.tree-item'); while (parent) { parent.classList.add('open'); parent.querySelector('.tree-ul').style.display = 'block'; parent = parent.parentElement.closest('.tree-item'); } } });
// Прокрутка к первому найденному элементу if (foundItems.length > 0) { foundItems[0].scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } }
// Инициализация при загрузке document.addEventListener('DOMContentLoaded', function() { initTree();
// Элементы управления const searchInput = document.getElementById('tree-search-input'); const searchBtn = document.getElementById('tree-search-btn'); const clearBtn = document.getElementById('tree-search-clear'); const instantMode = document.querySelector('input[value="instant"]'); // Обработка URL параметра const urlParams = new URLSearchParams(window.location.search); const urlSearch = urlParams.get('q'); if (urlSearch) { searchInput.value = urlSearch; searchTree(urlSearch); }
// Обработчики событий let searchTimeout; searchInput.addEventListener('input', function() { if (instantMode.checked) { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchTree(this.value); }, 300); } }); searchInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { searchTree(this.value); } }); searchBtn.addEventListener('click', function() { searchTree(searchInput.value); }); clearBtn.addEventListener('click', function() { searchInput.value = ''; searchTree(''); }); }); })();
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 11:45 | Сообщение # 81 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| (function() { // Сохраняем изначальное состояние дерева let initialTreeState = [];
// Инициализация дерева function initTree() { // Запоминаем изначальное состояние document.querySelectorAll('.tree-item.has-children').forEach((item, index) => { initialTreeState[index] = item.classList.contains('open'); });
// Обработчики кликов document.querySelectorAll('.tree-line').forEach(line => { line.addEventListener('click', function() { const item = this.parentElement; if (item.classList.contains('has-children')) { const isOpen = item.classList.contains('open'); item.classList.toggle('open', !isOpen); item.querySelector('.tree-ul').style.display = isOpen ? 'none' : 'block'; } }); }); }
// Сброс дерева в исходное состояние function resetTreeState() { document.querySelectorAll('.tree-item.has-children').forEach((item, index) => { const shouldBeOpen = initialTreeState[index]; item.classList.toggle('open', shouldBeOpen); item.querySelector('.tree-ul').style.display = shouldBeOpen ? 'block' : 'none'; item.classList.remove('highlighted'); }); }
// Поиск по дереву function searchTree(query) { const term = query.toLowerCase().trim(); // Сбрасываем к исходному состоянию resetTreeState();
// Если поиск пустой - оставляем как есть if (!term) return;
// Ищем совпадения let foundItems = []; document.querySelectorAll('.tree-item').forEach(item => { const text = item.getAttribute('data-search-text'); if (text.includes(term)) { item.classList.add('highlighted'); foundItems.push(item); // Раскрываем родителей let parent = item.parentElement.closest('.tree-item'); while (parent) { parent.classList.add('open'); parent.querySelector('.tree-ul').style.display = 'block'; parent = parent.parentElement.closest('.tree-item'); } } });
// Если ничего не найдено - сворачиваем всё if (foundItems.length === 0) { document.querySelectorAll('.tree-item.has-children').forEach(item => { item.classList.remove('open'); item.querySelector('.tree-ul').style.display = 'none'; }); } else { // Прокрутка к первому найденному элементу foundItems[0].scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } }
// Инициализация при загрузке document.addEventListener('DOMContentLoaded', function() { initTree();
// Элементы управления const searchInput = document.getElementById('tree-search-input'); const searchBtn = document.getElementById('tree-search-btn'); const clearBtn = document.getElementById('tree-search-clear'); const instantMode = document.querySelector('input[value="instant"]'); // Обработка URL параметра const urlParams = new URLSearchParams(window.location.search); const urlSearch = urlParams.get('q'); if (urlSearch) { searchInput.value = urlSearch; searchTree(urlSearch); }
// Обработчики событий searchBtn.addEventListener('click', function() { searchTree(searchInput.value); }); searchInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { searchTree(this.value); } }); clearBtn.addEventListener('click', function() { searchInput.value = ''; searchTree(''); }); // Для мгновенного поиска (если переключили режим) instantMode.addEventListener('change', function() { if (this.checked) { searchInput.addEventListener('input', handleInstantSearch); } else { searchInput.removeEventListener('input', handleInstantSearch); } }); let searchTimeout; function handleInstantSearch() { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchTree(this.value); }, 300); } }); })();
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 11:48 | Сообщение # 82 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| <div class="tree-container"> {{ $level := .level | default 1 }} <ul class="tree-ul level-{{ $level }}"> {{ range .nodes }} <li class="tree-item {{ if .children }}has-children{{ end }} {{ if eq (.state | default "closed") "open" }}open{{ else }}closed{{ end }}" data-search-text="{{ lower .name }}"> <div class="tree-line"> {{ if .children }}<span class="tree-arrow">›</span>{{ else }}<span class="tree-dot">•</span>{{ end }} <span class="tree-name">{{ .name }}</span> </div> {{ if .children }} {{ partial "tree" (dict "nodes" .children "level" (add $level 1)) }} {{ end }} </li> {{ end }} </ul> </div>
<script> (function() { // Сохраняем изначальное состояние const initialTreeState = new Map();
// Инициализация дерева function initTree() { document.querySelectorAll('.tree-item.has-children').forEach(item => { // Явно закрываем все узлы, кроме тех, что помечены как open if (!item.classList.contains('open')) { item.querySelector('.tree-ul').style.display = 'none'; } // Запоминаем исходное состояние initialTreeState.set(item, item.classList.contains('open')); });
// Обработчики кликов document.querySelectorAll('.tree-line').forEach(line => { line.addEventListener('click', function() { const item = this.parentElement; if (item.classList.contains('has-children')) { const isOpen = item.classList.contains('open'); item.classList.toggle('open', !isOpen); item.querySelector('.tree-ul').style.display = isOpen ? 'none' : 'block'; } }); }); }
// Сброс к исходному состоянию function resetTreeState() { document.querySelectorAll('.tree-item.has-children').forEach(item => { const shouldBeOpen = initialTreeState.get(item); item.classList.toggle('open', shouldBeOpen); item.querySelector('.tree-ul').style.display = shouldBeOpen ? 'block' : 'none'; item.classList.remove('highlighted'); }); }
// Поиск по дереву function searchTree(query) { const term = query.toLowerCase().trim(); // Сбрасываем к исходному состоянию resetTreeState();
// Если поиск пустой - оставляем как есть if (!term) return;
// Ищем совпадения let foundItems = []; document.querySelectorAll('.tree-item').forEach(item => { const text = item.getAttribute('data-search-text'); if (text.includes(term)) { item.classList.add('highlighted'); foundItems.push(item); // Раскрываем родителей let parent = item.parentElement.closest('.tree-item'); while (parent) { parent.classList.add('open'); parent.querySelector('.tree-ul').style.display = 'block'; parent = parent.parentElement.closest('.tree-item'); } } });
// Если ничего не найдено - сворачиваем всё if (foundItems.length === 0) { document.querySelectorAll('.tree-item.has-children').forEach(item => { item.classList.remove('open'); item.querySelector('.tree-ul').style.display = 'none'; }); } else { // Прокрутка к первому найденному элементу foundItems[0].scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } }
// Инициализация при загрузке document.addEventListener('DOMContentLoaded', function() { initTree();
// Обработка URL параметра const urlParams = new URLSearchParams(window.location.search); const urlSearch = urlParams.get('q'); if (urlSearch) { document.getElementById('tree-search-input').value = urlSearch; searchTree(urlSearch); } });
// Экспортируем функцию поиска window.searchTree = searchTree; })(); </script>
<style> /* Ваши существующие стили дерева */ .tree-container { font-family: sans-serif; font-size: 14px; } .tree-ul { list-style: none; padding-left: 20px; margin: 0; } .tree-item { margin: 2px 0; } .tree-line { display: flex; align-items: center; cursor: pointer; padding: 2px 0; } .tree-arrow, .tree-dot { width: 16px; margin-right: 4px; } .tree-arrow { transition: transform 0.2s; } .tree-item.open > .tree-line > .tree-arrow { transform: rotate(90deg); } .tree-item > .tree-ul { display: none; } .tree-item.open > .tree-ul { display: block; } .tree-item.highlighted > .tree-line > .tree-name { background-color: #fff8c5; border-radius: 3px; padding: 0 2px; } </style>
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 11:49 | Сообщение # 83 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| <div class="tree-search-panel"> <div class="tree-search-box"> <input type="text" id="tree-search-input" placeholder="Поиск в дереве..." class="tree-search-input"> <button id="tree-search-btn" class="tree-search-btn">Найти</button> <button id="tree-search-clear" class="tree-search-clear">×</button> </div> <div class="search-modes"> <label><input type="radio" name="search-mode" value="instant"> Мгновенный поиск</label> <label><input type="radio" name="search-mode" value="button" checked> Поиск по кнопке</label> </div> </div>
<script> document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('tree-search-input'); const searchBtn = document.getElementById('tree-search-btn'); const clearBtn = document.getElementById('tree-search-clear'); const instantMode = document.querySelector('input[value="instant"]');
// Обработчики событий searchBtn.addEventListener('click', function() { if (window.searchTree) window.searchTree(searchInput.value); }); searchInput.addEventListener('keypress', function(e) { if (e.key === 'Enter' && window.searchTree) { window.searchTree(this.value); } }); clearBtn.addEventListener('click', function() { searchInput.value = ''; if (window.searchTree) window.searchTree(''); }); // Для мгновенного поиска instantMode.addEventListener('change', function() { if (this.checked) { searchInput.addEventListener('input', handleInstantSearch); } else { searchInput.removeEventListener('input', handleInstantSearch); } }); let searchTimeout; function handleInstantSearch() { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { if (window.searchTree) window.searchTree(this.value); }, 300); } }); </script>
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 11:58 | Сообщение # 84 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| <div class="tree-container"> <!-- Добавляем панель поиска --> <div class="tree-search-panel"> <div class="tree-search-box"> <input type="text" id="tree-search-input" placeholder="Поиск в дереве..." class="tree-search-input" value="{{ with .Page.Params.searchQuery }}{{ . }}{{ end }}"> <button id="tree-search-btn" class="tree-search-btn">Найти</button> <button id="tree-search-clear" class="tree-search-clear">×</button> </div> </div>
{{ $level := .level | default 1 }} <ul class="tree-ul level-{{ $level }}"> {{ range .nodes }} <li class="tree-item {{ if .children }}has-children{{ end }} {{ .state | default "closed" }}" data-search-text="{{ lower .name }}"> <div class="tree-line"> {{ if .children }}<span class="tree-arrow">›</span>{{ else }}<span class="tree-dot">•</span>{{ end }} <span class="tree-name">{{ .name }}</span> </div> {{ if .children }} {{ partial "tree" (dict "nodes" .children "level" (add $level 1)) }} {{ end }} </li> {{ end }} </ul> </div>
<script> (function() { // Сохраняем изначальное состояние const initialTreeState = new Map();
// Инициализация дерева function initTree() { document.querySelectorAll('.tree-item.has-children').forEach(item => { // Явно закрываем все узлы, кроме помеченных как open const isOpen = item.classList.contains('open'); if (!isOpen) { item.querySelector('.tree-ul').style.display = 'none'; } initialTreeState.set(item, isOpen); });
// Обработчики кликов document.querySelectorAll('.tree-line').forEach(line => { line.addEventListener('click', function() { const item = this.parentElement; if (item.classList.contains('has-children')) { const isOpen = item.classList.contains('open'); item.classList.toggle('open', !isOpen); item.querySelector('.tree-ul').style.display = isOpen ? 'none' : 'block'; } }); }); }
// Функция поиска по дереву window.searchTree = function(query) { const term = query.toLowerCase().trim(); const searchInput = document.getElementById('tree-search-input'); if (searchInput) searchInput.value = term;
// Сброс к исходному состоянию document.querySelectorAll('.tree-item').forEach(item => { item.classList.remove('highlighted'); if (initialTreeState.get(item)) { item.classList.add('open'); item.querySelector('.tree-ul').style.display = 'block'; } else { item.classList.remove('open'); item.querySelector('.tree-ul').style.display = 'none'; } });
if (!term) return;
// Поиск и раскрытие let foundItems = []; document.querySelectorAll('.tree-item').forEach(item => { const text = item.getAttribute('data-search-text'); if (text.includes(term)) { item.classList.add('highlighted'); foundItems.push(item); // Раскрываем родителей let parent = item.parentElement.closest('.tree-item'); while (parent) { parent.classList.add('open'); parent.querySelector('.tree-ul').style.display = 'block'; parent = parent.parentElement.closest('.tree-item'); } } });
if (foundItems.length > 0) { foundItems[0].scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } };
// Инициализация document.addEventListener('DOMContentLoaded', function() { initTree();
// Обработчики для панели поиска const searchInput = document.getElementById('tree-search-input'); const searchBtn = document.getElementById('tree-search-btn'); const clearBtn = document.getElementById('tree-search-clear');
if (searchBtn) { searchBtn.addEventListener('click', function() { if (window.searchTree) window.searchTree(searchInput.value); }); }
if (searchInput) { searchInput.addEventListener('keypress', function(e) { if (e.key === 'Enter' && window.searchTree) { window.searchTree(this.value); } }); }
if (clearBtn) { clearBtn.addEventListener('click', function() { searchInput.value = ''; if (window.searchTree) window.searchTree(''); }); }
// Проверяем URL параметр const urlParams = new URLSearchParams(window.location.search); const urlSearch = urlParams.get('q'); if (urlSearch && window.searchTree) { window.searchTree(urlSearch); } }); })(); </script>
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 11:58 | Сообщение # 85 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| // В функции displayResults: function displayResults(results, query) { // ... существующий код ...
// Добавляем интеграцию с деревом if (window.searchTree) { window.searchTree(query); // Заполняем поле поиска в дереве const treeSearchInput = document.getElementById('tree-search-input'); if (treeSearchInput) { treeSearchInput.value = query; } } }
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 11:58 | Сообщение # 86 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| {{ define "main" }} {{ .Scratch.Set "searchQuery" (.Params.searchQuery | default "") }} {{ partial "tree" (dict "nodes" .Params.tree "searchQuery" (.Scratch.Get "searchQuery")) }} {{ end }}
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 12:09 | Сообщение # 87 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| (function() { // Сохраняем изначальное состояние const initialTreeState = new Map(); let currentSearchMode = 'button'; // По умолчанию поиск по кнопке
// Инициализация дерева function initTree() { document.querySelectorAll('.tree-item.has-children').forEach(item => { // Явно закрываем все узлы, кроме тех, что помечены как open if (!item.classList.contains('open')) { item.querySelector('.tree-ul').style.display = 'none'; } // Запоминаем исходное состояние initialTreeState.set(item, item.classList.contains('open')); });
// Обработчики кликов document.querySelectorAll('.tree-line').forEach(line => { line.addEventListener('click', function() { const item = this.parentElement; if (item.classList.contains('has-children')) { const isOpen = item.classList.contains('open'); item.classList.toggle('open', !isOpen); item.querySelector('.tree-ul').style.display = isOpen ? 'none' : 'block'; } }); }); }
// Сброс к исходному состоянию function resetTreeState() { document.querySelectorAll('.tree-item.has-children').forEach(item => { const shouldBeOpen = initialTreeState.get(item); item.classList.toggle('open', shouldBeOpen); item.querySelector('.tree-ul').style.display = shouldBeOpen ? 'block' : 'none'; item.classList.remove('highlighted'); }); }
// Поиск по дереву function searchTree(query) { const term = query.toLowerCase().trim(); // Сбрасываем к исходному состоянию resetTreeState();
// Если поиск пустой - оставляем как есть if (!term) return;
// Ищем совпадения let foundItems = []; document.querySelectorAll('.tree-item').forEach(item => { const text = item.getAttribute('data-search-text'); if (text.includes(term)) { item.classList.add('highlighted'); foundItems.push(item); // Раскрываем родителей let parent = item.parentElement.closest('.tree-item'); while (parent) { parent.classList.add('open'); parent.querySelector('.tree-ul').style.display = 'block'; parent = parent.parentElement.closest('.tree-item'); } } });
// Если ничего не найдено - сворачиваем всё if (foundItems.length === 0) { document.querySelectorAll('.tree-item.has-children').forEach(item => { item.classList.remove('open'); item.querySelector('.tree-ul').style.display = 'none'; }); } else { // Прокрутка к первому найденному элементу foundItems[0].scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } }
// Инициализация при загрузке document.addEventListener('DOMContentLoaded', function() { initTree();
// Обработка URL параметра const urlParams = new URLSearchParams(window.location.search); const urlSearch = urlParams.get('q'); if (urlSearch) { document.getElementById('tree-search-input').value = urlSearch; searchTree(urlSearch); } });
// Экспортируем функции window.searchTree = searchTree; window.setSearchMode = function(mode) { currentSearchMode = mode; }; })();
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 12:09 | Сообщение # 88 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| <div class="tree-search-panel"> <div class="tree-search-box"> <input type="text" id="tree-search-input" placeholder="Поиск в дереве..." class="tree-search-input"> <button id="tree-search-btn" class="tree-search-btn">Найти</button> <button id="tree-search-clear" class="tree-search-clear">×</button> </div> <div class="search-modes"> <label><input type="radio" name="search-mode" value="instant"> Мгновенный поиск</label> <label><input type="radio" name="search-mode" value="button" checked> Поиск по кнопке</label> </div> </div>
<script> document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('tree-search-input'); const searchBtn = document.getElementById('tree-search-btn'); const clearBtn = document.getElementById('tree-search-clear'); const modeRadios = document.querySelectorAll('input[name="search-mode"]'); let searchTimeout; // Обработчик мгновенного поиска function handleInstantSearch() { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { if (window.searchTree) window.searchTree(this.value); }, 300); } // Инициализация режима поиска function initSearchMode() { const selectedMode = document.querySelector('input[name="search-mode"]:checked').value; // Удаляем все обработчики searchInput.removeEventListener('input', handleInstantSearch); searchBtn.style.display = 'block'; if (selectedMode === 'instant') { searchInput.addEventListener('input', handleInstantSearch); searchBtn.style.display = 'none'; } if (window.setSearchMode) { window.setSearchMode(selectedMode); } } // Инициализация initSearchMode(); // Обработчики событий searchBtn.addEventListener('click', function() { if (window.searchTree) window.searchTree(searchInput.value); }); searchInput.addEventListener('keypress', function(e) { if (e.key === 'Enter' && window.searchTree) { window.searchTree(this.value); } }); clearBtn.addEventListener('click', function() { searchInput.value = ''; if (window.searchTree) window.searchTree(''); }); // Переключение режимов modeRadios.forEach(radio => { radio.addEventListener('change', initSearchMode); }); }); </script>
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 12:35 | Сообщение # 89 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| .tree-search-panel { margin-bottom: 15px; max-width: 400px; }
.tree-search-box { position: relative; display: flex; margin-bottom: 8px; }
.tree-search-input { flex: 1; padding: 8px 30px 8px 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; transition: padding 0.2s; }
/* Когда кнопка скрыта - увеличиваем отступ для крестика */ .tree-search-input.no-button { padding-right: 30px; }
.tree-search-btn { margin-left: 8px; padding: 0 12px; background: #f0f0f0; border: 1px solid #ddd; border-radius: 4px; cursor: pointer; transition: opacity 0.2s, margin 0.2s; }
.tree-search-btn.hidden { opacity: 0; margin-left: 0; width: 0; padding: 0; border: none; overflow: hidden; }
.tree-search-clear { position: absolute; right: 10px; /* Базовое положение */ top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; font-size: 16px; color: #999; transition: right 0.2s; }
/* Когда кнопка видна - смещаем крестик */ .tree-search-box:not(.no-button) .tree-search-clear { right: 90px; }
.search-modes { font-size: 13px; color: #666; }
.search-modes label { margin-right: 10px; cursor: pointer; }
|
|
| |
AleXStam | Дата: Понедельник, 2025-06-23, 12:35 | Сообщение # 90 |
Генералиссимус
Группа: Администраторы
Сообщений: 200
Награды: 1
Репутация: 10003
Статус: Оффлайн
| // В функции initSearchMode: function initSearchMode() { const selectedMode = document.querySelector('input[name="search-mode"]:checked').value; const searchBox = document.querySelector('.tree-search-box'); const searchInput = document.getElementById('tree-search-input'); const searchBtn = document.getElementById('tree-search-btn'); // Удаляем все обработчики searchInput.removeEventListener('input', handleInstantSearch); if (selectedMode === 'instant') { // Мгновенный поиск searchInput.addEventListener('input', handleInstantSearch); searchBtn.classList.add('hidden'); searchBox.classList.add('no-button'); searchInput.classList.add('no-button'); } else { // Поиск по кнопке searchBtn.classList.remove('hidden'); searchBox.classList.remove('no-button'); searchInput.classList.remove('no-button'); } if (window.setSearchMode) { window.setSearchMode(selectedMode); } }
|
|
| |