Отзывы и предложения к софту от AleXStam
  • Страница 15 из 15
  • «
  • 1
  • 2
  • 13
  • 14
  • 15
Поговорим о...
// Инициализация режима поиска
function initSearchMode() {
const selectedMode = document.querySelector('input[name="search-mode"]:checked').value;
const searchBox = document.querySelector('.tree-search-box');
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');
} else {
// Поиск по кнопке
searchBtn.classList.remove('hidden');
searchBox.classList.remove('no-button');
}
}

// Инициализация
initSearchMode();
<div class="icons-gallery">
<h2>Галерея иконок</h2>

{{ if .Site.Data.icons }}
{{ $icons := .Site.Data.icons }}
{{ $descriptions := .Site.Data.icon_descriptions | default dict }}

<div class="icons-controls">
<div class="icons-stats">
Всего иконок: <strong>{{ len $icons }}</strong>
</div>

<div class="search-mode-container">
<label class="search-mode-label">
<input type="radio" name="search-mode" value="instant" checked>
<span>Мгновенный поиск</span>
</label>
<label class="search-mode-label">
<input type="radio" name="search-mode" value="button">
<span>Поиск по кнопке</span>
</label>
</div>

<div class="tree-search-box no-button">
<input
type="text"
id="iconsSearch"
placeholder="Поиск по названию или описанию..."
class="search-input"
>
<button id="tree-search-btn" class="hidden">Найти</button>
</div>
</div>

<div class="icons-table-container">
<table class="icons-table" id="iconsTable">
<thead>
<tr>
<th>Иконка</th>
<th>Название</th>
<th>Описание</th>
<th>Размер</th>
<th>Код для вставки</th>
</tr>
</thead>
<tbody>
{{ range $name, $svg := $icons }}
{{ $description := index $descriptions $name | default "" }}
<tr class="icon-row" data-name="{{ $name | lower }}" data-description="{{ $description | lower }}">
<td class="icon-cell">
<div class="icon-svg-small">{{ $svg | safeHTML }}</div>
</td>
<td class="name-cell">
<code>{{ $name }}</code>
</td>
<td class="description-cell">
{{ if $description }}
{{ $description }}
{{ else }}
<span class="no-description">—</span>
{{ end }}
</td>
<td class="size-cell">
16×16 px
</td>
<td class="code-cell">
<div class="code-snippet" onclick="copyCode(this)">
<code>{{ "{{<" }}icon "{{ $name }}"{{ ">"}}}}</code>
<span class="copy-tooltip">Кликните для копирования</span>
<div class="copy-success">
<div class="success-icon">✓</div>
<div>Скопировано!</div>
</div>
</div>
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>

<div class="no-results" id="noResults" style="display: none;">
<p>Иконки не найдены. Попробуйте другой запрос.</p>
</div>
{{ else }}
<div class="error-message">
<h3>Ошибка: данные иконок не найдены!</h3>
<p>Проверьте файл data/icons.yaml</p>
</div>
{{ end }}
</div>

<style>
/* Все предыдущие стили остаются */
.icons-gallery {
margin: 40px 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.search-mode-container {
display: flex;
gap: 20px;
margin-bottom: 15px;
}

.search-mode-label {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-size: 14px;
color: #555;
}

.search-mode-label input[type="radio"] {
margin: 0;
}

.tree-search-box {
display: flex;
gap: 10px;
position: relative;
}

.tree-search-box.no-button .search-input {
border-radius: 8px;
}

.tree-search-box:not(.no-button) .search-input {
border-radius: 8px 0 0 8px;
border-right: none;
}

#tree-search-btn {
padding: 12px 20px;
background: #007acc;
color: white;
border: none;
border-radius: 0 8px 8px 0;
cursor: pointer;
font-size: 14px;
transition: background 0.3s ease;
}

#tree-search-btn:hover {
background: #005a9e;
}

.hidden {
display: none !important;
}

/* Остальные стили остаются без изменений */
.icons-controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
gap: 15px;
}

.icons-stats {
background: #f8f9fa;
padding: 12px 20px;
border-radius: 8px;
font-size: 14px;
color: #555;
}

.search-input {
padding: 12px 16px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 14px;
min-width: 250px;
transition: border-color 0.3s ease;
}

.search-input:focus {
outline: none;
border-color: #007acc;
box-shadow: 0 0 0 3px rgba(0, 122, 204, 0.1);
}

.icons-table-container {
overflow-x: auto;
border: 1px solid #e1e5e9;
border-radius: 8px;
background: white;
}

.icons-table {
width: 100%;
border-collapse: collapse;
}

/* ... остальные стили без изменений ... */
</style>

<script>
// Функция для поиска иконок
function searchIcons() {
const searchTerm = document.getElementById('iconsSearch').value.toLowerCase();
const rows = document.querySelectorAll('.icon-row');
const noResults = document.getElementById('noResults');
let visibleCount = 0;

rows.forEach(row => {
const iconName = row.getAttribute('data-name');
const iconDescription = row.getAttribute('data-description');

if (searchTerm === '' || iconName.includes(searchTerm) || iconDescription.includes(searchTerm)) {
row.style.display = '';
visibleCount++;
} else {
row.style.display = 'none';
}
});

// Показываем/скрываем сообщение "нет результатов"
if (visibleCount === 0 && searchTerm !== '') {
noResults.style.display = 'block';
} else {
noResults.style.display = 'none';
}
}

// Обработчик мгновенного поиска
function handleInstantSearch(e) {
// Останавливаем всплытие чтобы не срабатывал глобальный поиск
e.stopPropagation();
e.stopImmediatePropagation();

clearTimeout(this.searchTimeout);
this.searchTimeout = setTimeout(() => {
searchIcons();
}, 300);
}

// Обработчик поиска по кнопке
function handleButtonSearch(e) {
e.stopPropagation();
e.stopImmediatePropagation();
e.preventDefault();

searchIcons();
}

// Инициализация режима поиска
function initSearchMode() {
const selectedMode = document.querySelector('input[name="search-mode"]:checked').value;
const searchBox = document.querySelector('.tree-search-box');
const searchBtn = document.getElementById('tree-search-btn');
const searchInput = document.getElementById('iconsSearch');

// Удаляем все обработчики
searchInput.removeEventListener('input', handleInstantSearch);
searchInput.removeEventListener('keydown', handleInputKeydown);
searchBtn.removeEventListener('click', handleButtonSearch);

if (selectedMode === 'instant') {
// Мгновенный поиск
searchInput.addEventListener('input', handleInstantSearch);
searchInput.addEventListener('keydown', handleInputKeydown);
searchBtn.classList.add('hidden');
searchBox.classList.add('no-button');
} else {
// Поиск по кнопке
searchBtn.addEventListener('click', handleButtonSearch);
searchInput.addEventListener('keydown', handleInputKeydown);
searchBtn.classList.remove('hidden');
searchBox.classList.remove('no-button');
}
}

// Обработчик клавиш для input
function handleInputKeydown(e) {
// Полностью останавливаем всплытие
e.stopPropagation();
e.stopImmediatePropagation();

// Enter в режиме кнопки
if (e.key === 'Enter' && document.querySelector('input[name="search-mode"]:checked').value === 'button') {
e.preventDefault();
searchIcons();
}

// Escape очищает поиск
if (e.key === 'Escape') {
this.value = '';
searchIcons();
e.preventDefault();
}
}

// Функция для копирования кода
function copyCode(element) {
const code = element.querySelector('code').textContent;

// Используем modern Clipboard API
navigator.clipboard.writeText(code).then(() => {
// Показываем успешное сообщение
const success = element.querySelector('.copy-success');
success.classList.add('show');

// Скрываем сообщение через 2 секунды
setTimeout(() => {
success.classList.remove('show');
}, 2000);
}).catch(err => {
console.error('Ошибка при копирования:', err);
// Fallback для старых браузеров
const textArea = document.createElement('textarea');
textArea.value = code;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);

const success = element.querySelector('.copy-success');
success.classList.add('show');
setTimeout(() => {
success.classList.remove('show');
}, 2000);
});
}

// Инициализация после загрузки DOM
document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('iconsSearch');
const modeRadios = document.querySelectorAll('input[name="search-mode"]');

if (!searchInput) return;

// Инициализируем поиск
initSearchMode();

// Обработчики переключения режима поиска
modeRadios.forEach(radio => {
radio.addEventListener('change', initSearchMode);
});

// Дополнительная изоляция - предотвращаем фокус на глобальный поиск
searchInput.addEventListener('focus', function(e) {
e.stopPropagation();
});

searchInput.addEventListener('click', function(e) {
e.stopPropagation();
});

// Предотвращаем всплытие для всех событий мыши
const searchContainer = document.querySelector('.tree-search-box');
if (searchContainer) {
searchContainer.addEventListener('mousedown', function(e) {
e.stopPropagation();
});
searchContainer.addEventListener('mouseup', function(e) {
e.stopPropagation();
});
}
});

// Дополнительная защита - перехватываем события до их всплытия
document.addEventListener('keydown', function(e) {
const searchInput = document.getElementById('iconsSearch');
if (searchInput && document.activeElement === searchInput) {
e.stopImmediatePropagation();
}
}, true); // Используем capture phase

document.addEventListener('keyup', function(e) {
const searchInput = document.getElementById('iconsSearch');
if (searchInput && document.activeElement === searchInput) {
e.stopImmediatePropagation();
}
}, true);

document.addEventListener('input', function(e) {
const searchInput = document.getElementById('iconsSearch');
if (searchInput && e.target === searchInput) {
e.stopImmediatePropagation();
}
}, true);
</script>
<div class="icons-gallery">
<h2>Галерея иконок</h2>

{{ if .Site.Data.icons }}
{{ $icons := .Site.Data.icons }}
{{ $descriptions := .Site.Data.icon_descriptions | default dict }}

<div class="icons-controls">
<div class="icons-stats">
Всего иконок: <strong>{{ len $icons }}</strong>
</div>

<div class="search-mode-container">
<label class="search-mode-label">
<input type="radio" name="search-mode" value="instant" checked>
<span>Мгновенный поиск</span>
</label>
<label class="search-mode-label">
<input type="radio" name="search-mode" value="button">
<span>Поиск по кнопке</span>
</label>
</div>

<div class="tree-search-box no-button">
<input
type="text"
id="iconsSearch"
placeholder="Поиск по названию или описанию..."
class="search-input"
>
<button id="clear-search" class="clear-search-btn hidden" title="Очистить поиск">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor">
<path d="M1 1L13 13M13 1L1 13"/>
</svg>
</button>
<button id="tree-search-btn" class="search-btn hidden">Найти</button>
</div>
</div>

<div class="icons-table-container">
<table class="icons-table" id="iconsTable">
<thead>
<tr>
<th>Иконка</th>
<th>Название</th>
<th>Описание</th>
<th>Размер</th>
<th>Код для вставки</th>
</tr>
</thead>
<tbody>
{{ range $name, $svg := $icons }}
{{ $description := index $descriptions $name | default "" }}
<tr class="icon-row" data-name="{{ $name | lower }}" data-description="{{ $description | lower }}">
<td class="icon-cell">
<div class="icon-svg-small">{{ $svg | safeHTML }}</div>
</td>
<td class="name-cell">
<code>{{ $name }}</code>
</td>
<td class="description-cell">
{{ if $description }}
{{ $description }}
{{ else }}
<span class="no-description">—</span>
{{ end }}
</td>
<td class="size-cell">
16×16 px
</td>
<td class="code-cell">
<div class="code-snippet" onclick="copyCode(this)">
<code>{{ "{{<" }}icon "{{ $name }}"{{ ">"}}}}</code>
<span class="copy-tooltip">Кликните для копирования</span>
<div class="copy-success">
<div class="success-icon">✓</div>
<div>Скопировано!</div>
</div>
</div>
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>

<div class="no-results" id="noResults" style="display: none;">
<p>Иконки не найдены. Попробуйте другой запрос.</p>
</div>
{{ else }}
<div class="error-message">
<h3>Ошибка: данные иконок не найдены!</h3>
<p>Проверьте файл data/icons.yaml</p>
</div>
{{ end }}
</div>

<style>
/* Все предыдущие стили остаются */
.icons-gallery {
margin: 40px 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.search-mode-container {
display: flex;
gap: 20px;
margin-bottom: 15px;
}

.search-mode-label {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-size: 14px;
color: #555;
}

.search-mode-label input[type="radio"] {
margin: 0;
}

.tree-search-box {
display: flex;
gap: 0;
position: relative;
align-items: center;
}

.tree-search-box.no-button .search-input {
border-radius: 8px;
padding-right: 35px;
}

.tree-search-box:not(.no-button) .search-input {
border-radius: 8px 0 0 8px;
border-right: none;
padding-right: 35px;
}

.search-input {
padding: 12px 16px;
border: 2px solid #e1e5e9;
font-size: 14px;
min-width: 250px;
transition: border-color 0.3s ease;
flex: 1;
}

.search-input:focus {
outline: none;
border-color: #007acc;
box-shadow: 0 0 0 3px rgba(0, 122, 204, 0.1);
}

.clear-search-btn {
position: absolute;
right: 45px;
background: none;
border: none;
padding: 6px;
cursor: pointer;
color: #999;
border-radius: 50%;
transition: all 0.3s ease;
}

.clear-search-btn:hover {
color: #666;
background: #f0f0f0;
}

.clear-search-btn:not(.hidden) {
display: flex;
align-items: center;
justify-content: center;
}

.search-btn {
padding: 12px 20px;
background: #007acc;
color: white;
border: none;
border-radius: 0 8px 8px 0;
cursor: pointer;
font-size: 14px;
transition: background 0.3s ease;
white-space: nowrap;
}

.search-btn:hover {
background: #005a9e;
}

.hidden {
display: none !important;
}

/* Остальные стили остаются без изменений */
.icons-controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
gap: 15px;
}

.icons-stats {
background: #f8f9fa;
padding: 12px 20px;
border-radius: 8px;
font-size: 14px;
color: #555;
}

.icons-table-container {
overflow-x: auto;
border: 1px solid #e1e5e9;
border-radius: 8px;
background: white;
}

.icons-table {
width: 100%;
border-collapse: collapse;
}

/* ... остальные стили без изменений ... */
</style>

<script>
// Функция для поиска иконок
function searchIcons() {
const searchTerm = document.getElementById('iconsSearch').value.toLowerCase();
const rows = document.querySelectorAll('.icon-row');
const noResults = document.getElementById('noResults');
const clearBtn = document.getElementById('clear-search');
let visibleCount = 0;

rows.forEach(row => {
const iconName = row.getAttribute('data-name');
const iconDescription = row.getAttribute('data-description');

if (searchTerm === '' || iconName.includes(searchTerm) || iconDescription.includes(searchTerm)) {
row.style.display = '';
visibleCount++;
} else {
row.style.display = 'none';
}
});

// Показываем/скрываем сообщение "нет результатов"
if (visibleCount === 0 && searchTerm !== '') {
noResults.style.display = 'block';
} else {
noResults.style.display = 'none';
}

// Показываем/скрываем кнопку очистки
if (searchTerm !== '') {
clearBtn.classList.remove('hidden');
} else {
clearBtn.classList.add('hidden');
}
}

// Функция очистки поиска
function clearSearch() {
const searchInput = document.getElementById('iconsSearch');
searchInput.value = '';
searchInput.focus();
searchIcons();
}

// Обработчик мгновенного поиска
function handleInstantSearch(e) {
// Останавливаем всплытие чтобы не срабатывал глобальный поиск
e.stopPropagation();
e.stopImmediatePropagation();

clearTimeout(this.searchTimeout);
this.searchTimeout = setTimeout(() => {
searchIcons();
}, 300);
}

// Обработчик поиска по кнопке
function handleButtonSearch(e) {
e.stopPropagation();
e.stopImmediatePropagation();
e.preventDefault();

searchIcons();
}

// Обработчик Enter для поиска
function handleEnterSearch(e) {
if (e.key === 'Enter') {
e.stopPropagation();
e.stopImmediatePropagation();
e.preventDefault();

searchIcons();
}

// Escape очищает поиск
if (e.key === 'Escape') {
clearSearch();
e.preventDefault();
}
}

// Инициализация режима поиска
function initSearchMode() {
const selectedMode = document.querySelector('input[name="search-mode"]:checked').value;
const searchBox = document.querySelector('.tree-search-box');
const searchBtn = document.getElementById('tree-search-btn');
const searchInput = document.getElementById('iconsSearch');
const clearBtn = document.getElementById('clear-search');

// Удаляем все обработчики
searchInput.removeEventListener('input', handleInstantSearch);
searchInput.removeEventListener('keydown', handleEnterSearch);
searchBtn.removeEventListener('click', handleButtonSearch);
clearBtn.removeEventListener('click', clearSearch);

// Добавляем общие обработчики
searchInput.addEventListener('keydown', handleEnterSearch);
clearBtn.addEventListener('click', clearSearch);

if (selectedMode === 'instant') {
// Мгновенный поиск
searchInput.addEventListener('input', handleInstantSearch);
searchBtn.classList.add('hidden');
searchBox.classList.add('no-button');
} else {
// Поиск по кнопке
searchBtn.addEventListener('click', handleButtonSearch);
searchBtn.classList.remove('hidden');
searchBox.classList.remove('no-button');
}

// Обновляем отображение кнопки очистки
searchIcons();
}

// Функция для копирования кода
function copyCode(element) {
const code = element.querySelector('code').textContent;

// Используем modern Clipboard API
navigator.clipboard.writeText(code).then(() => {
// Показываем успешное сообщение
const success = element.querySelector('.copy-success');
success.classList.add('show');

// Скрываем сообщение через 2 секунды
setTimeout(() => {
success.classList.remove('show');
}, 2000);
}).catch(err => {
console.error('Ошибка при копирования:', err);
// Fallback для старых браузеров
const textArea = document.createElement('textarea');
textArea.value = code;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);

const success = element.querySelector('.copy-success');
success.classList.add('show');
setTimeout(() => {
success.classList.remove('show');
}, 2000);
});
}

// Инициализация после загрузки DOM
document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('iconsSearch');
const modeRadios = document.querySelectorAll('input[name="search-mode"]');

if (!searchInput) return;

// Инициализируем поиск
initSearchMode();

// Обработчики переключения режима поиска
modeRadios.forEach(radio => {
radio.addEventListener('change', initSearchMode);
});

// Дополнительная изоляция - предотвращаем фокус на глобальный поиск
const stopPropagation = (e) => e.stopPropagation();

searchInput.addEventListener('focus', stopPropagation);
searchInput.addEventListener('click', stopPropagation);
searchInput.addEventListener('mousedown', stopPropagation);

const searchContainer = document.querySelector('.tree-search-box');
if (searchContainer) {
searchContainer.addEventListener('mousedown', stopPropagation);
searchContainer.addEventListener('mouseup', stopPropagation);
}
});

// Дополнительная защита - перехватываем события до их всплытия
document.addEventListener('keydown', function(e) {
const searchInput = document.getElementById('iconsSearch');
if (searchInput && (document.activeElement === searchInput || e.target === searchInput)) {
e.stopImmediatePropagation();
}
}, true);

document.addEventListener('keyup', function(e) {
const searchInput = document.getElementById('iconsSearch');
if (searchInput && (document.activeElement === searchInput || e.target === searchInput)) {
e.stopImmediatePropagation();
}
}, true);

document.addEventListener('input', function(e) {
const searchInput = document.getElementById('iconsSearch');
if (searchInput && e.target === searchInput) {
e.stopImmediatePropagation();
}
}, true);
</script>
<div class="icons-gallery">
<h2>Галерея иконок</h2>

{{ if .Site.Data.icons }}
{{ $icons := .Site.Data.icons }}
{{ $descriptions := .Site.Data.icon_descriptions | default dict }}

<div class="icons-controls">
<div class="icons-stats">
Всего иконок: <strong>{{ len $icons }}</strong>
</div>

<div class="search-container">
<div class="search-mode-container">
<label class="search-mode-label">
<input type="radio" name="search-mode" value="instant" checked>
<span>Мгновенный поиск</span>
</label>
<label class="search-mode-label">
<input type="radio" name="search-mode" value="button">
<span>Поиск по кнопке</span>
</label>
</div>

<div class="search-box">
<input
type="text"
id="iconsSearch"
placeholder="Поиск по названию или описанию..."
class="search-input"
>
<button id="clearSearch" class="clear-btn" title="Очистить поиск">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor">
<path d="M1 1L13 13M13 1L1 13"/>
</svg>
</button>
<button id="searchBtn" class="search-btn">Найти</button>
</div>
</div>
</div>

<div class="icons-table-container">
<table class="icons-table" id="iconsTable">
<thead>
<tr>
<th>Иконка</th>
<th>Название</th>
<th>Описание</th>
<th>Размер</th>
<th>Код для вставки</th>
</tr>
</thead>
<tbody>
{{ range $name, $svg := $icons }}
{{ $description := index $descriptions $name | default "" }}
<tr class="icon-row" data-name="{{ $name | lower }}" data-description="{{ $description | lower }}">
<td class="icon-cell">
<div class="icon-svg-small">{{ $svg | safeHTML }}</div>
</td>
<td class="name-cell">
<code>{{ $name }}</code>
</td>
<td class="description-cell">
{{ if $description }}
{{ $description }}
{{ else }}
<span class="no-description">—</span>
{{ end }}
</td>
<td class="size-cell">
16×16 px
</td>
<td class="code-cell">
<div class="code-snippet" onclick="copyCode(this)">
<code>{{ "{{<" }}icon "{{ $name }}"{{ ">"}}}}</code>
<span class="copy-tooltip">Кликните для копирования</span>
<div class="copy-success">
<div class="success-icon">✓</div>
<div>Скопировано!</div>
</div>
</div>
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>

<div class="no-results" id="noResults" style="display: none;">
<p>Иконки не найдены. Попробуйте другой запрос.</p>
</div>
{{ else }}
<div class="error-message">
<h3>Ошибка: данные иконок не найдены!</h3>
<p>Проверьте файл data/icons.yaml</p>
</div>
{{ end }}
</div>

<style>
.icons-gallery {
margin: 40px 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.icons-controls {
display: flex;
justify-content: space-between;
align-items: start;
margin-bottom: 20px;
flex-wrap: wrap;
gap: 20px;
}

.icons-stats {
background: #f8f9fa;
padding: 12px 20px;
border-radius: 8px;
font-size: 14px;
color: #555;
min-width: 150px;
}

.search-container {
display: flex;
flex-direction: column;
gap: 15px;
min-width: 300px;
}

.search-mode-container {
display: flex;
gap: 20px;
}

.search-mode-label {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-size: 14px;
color: #555;
}

.search-mode-label input[type="radio"] {
margin: 0;
}

.search-box {
display: flex;
position: relative;
width: 100%;
}

.search-input {
padding: 12px 40px 12px 16px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 14px;
width: 100%;
transition: border-color 0.3s ease;
background: white;
}

.search-input:focus {
outline: none;
border-color: #007acc;
box-shadow: 0 0 0 3px rgba(0, 122, 204, 0.1);
}

.search-input:focus + .clear-btn {
opacity: 1;
}

.clear-btn {
position: absolute;
right: 50px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
padding: 4px;
cursor: pointer;
color: #999;
border-radius: 50%;
transition: all 0.3s ease;
opacity: 0;
display: flex;
align-items: center;
justify-content: center;
}

.clear-btn:hover {
color: #666;
background: #f0f0f0;
}

.search-input:not(:placeholder-shown) + .clear-btn {
opacity: 1;
}

.search-btn {
padding: 12px 20px;
background: #007acc;
color: white;
border: none;
border-radius: 0 8px 8px 0;
cursor: pointer;
font-size: 14px;
transition: background 0.3s ease;
white-space: nowrap;
margin-left: -2px;
}

.search-btn:hover {
background: #005a9e;
}

.icons-table-container {
overflow-x: auto;
border: 1px solid #e1e5e9;
border-radius: 8px;
background: white;
margin-top: 10px;
}

.icons-table {
width: 100%;
border-collapse: collapse;
}

.icons-table th {
background: #f8f9fa;
padding: 16px;
text-align: left;
font-weight: 600;
color: #555;
border-bottom: 2px solid #e1e5e9;
}

.icons-table td {
padding: 12px 16px;
border-bottom: 1px solid #f0f0f0;
}

.icon-row:hover {
background: #fafafa;
}

.icon-cell {
text-align: center;
width: 60px;
}

.icon-svg-small {
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
}

.icon-svg-small svg {
width: 16px;
height: 16px;
min-width: 16px;
min-height: 16px;
}

.name-cell {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
color: #333;
width: 150px;
}

.name-cell code {
background: #f5f5f5;
padding: 4px 8px;
border-radius: 4px;
border: 1px solid #eee;
font-size: 12px;
}

.description-cell {
color: #666;
font-size: 14px;
line-height: 1.4;
max-width: 300px;
}

.no-description {
color: #999;
font-style: italic;
}

.size-cell {
color: #888;
font-size: 12px;
text-align: center;
width: 80px;
}

.code-cell {
width: 200px;
}

.code-snippet {
position: relative;
background: #f8f9fa;
padding: 10px 14px;
border-radius: 6px;
border: 1px solid #e9ecef;
cursor: pointer;
transition: all 0.3s ease;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
min-height: 40px;
display: flex;
align-items: center;
}

.code-snippet:hover {
background: #e3f2fd;
border-color: #2196f3;
}

.code-snippet code {
background: none;
border: none;
padding: 0;
color: #1976d2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
flex: 1;
}

.copy-tooltip {
position: absolute;
top: -35px;
left: 50%;
transform: translateX(-50%);
background: #333;
color: white;
padding: 6px 12px;
border-radius: 4px;
font-size: 12px;
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
white-space: nowrap;
z-index: 1000;
}

.code-snippet:hover .copy-tooltip {
opacity: 1;
}

.copy-success {
position: absolute;
top: -60px;
left: 50%;
transform: translateX(-50%);
background: #4caf50;
color: white;
padding: 10px 15px;
border-radius: 6px;
font-size: 12px;
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
z-index: 1000;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}

.copy-success.show {
opacity: 1;
}

.success-icon {
font-size: 16px;
font-weight: bold;
}

.no-results {
text-align: center;
padding: 40px;
color: #888;
font-style: italic;
display: none;
}

.error-message {
color: #d32f2f;
padding: 20px;
border: 2px solid #ffcdd2;
border-radius: 8px;
background: #ffebee;
}

.hidden {
display: none !important;
}

/* Адаптивность */
@media (max-width: 1024px) {
.icons-controls {
flex-direction: column;
align-items: stretch;
}

.search-container {
width: 100%;
}

.description-cell {
display: none;
}

.code-cell {
width: 180px;
}
}

@media (max-width: 768px) {
.search-mode-container {
flex-direction: column;
gap: 10px;
}

.search-box {
flex-direction: column;
gap: 10px;
}

.search-input {
border-radius: 8px;
padding-right: 16px;
}

.clear-btn {
right: 10px;
}

.search-btn {
border-radius: 8px;
margin-left: 0;
}

.icons-table th,
.icons-table td {
padding: 10px 12px;
}

.code-cell {
display: none;
}

.name-cell {
width: 120px;
}
}
</style>

<script>
// Глобальные переменные
let searchTimeout = null;

// Функция для поиска иконок
function searchIcons() {
const searchTerm = document.getElementById('iconsSearch').value.toLowerCase();
const rows = document.querySelectorAll('.icon-row');
const noResults = document.getElementById('noResults');
const clearBtn = document.getElementById('clearSearch');
let visibleCount = 0;

rows.forEach(row => {
const iconName = row.getAttribute('data-name');
const iconDescription = row.getAttribute('data-description');

if (searchTerm === '' || iconName.includes(searchTerm) || iconDescription.includes(searchTerm)) {
row.style.display = '';
visibleCount++;
} else {
row.style.display = 'none';
}
});

// Показываем/скрываем сообщение "нет результатов"
if (visibleCount === 0 && searchTerm !== '') {
noResults.style.display = 'block';
} else {
noResults.style.display = 'none';
}

// Показываем/скрываем кнопку очистки
if (searchTerm !== '') {
clearBtn.style.display = 'flex';
} else {
clearBtn.style.display = 'none';
}
}

// Функция очистки поиска
function clearSearch() {
const searchInput = document.getElementById('iconsSearch');
searchInput.value = '';
searchInput.focus();
searchIcons();
}

// Обработчик мгновенного поиска
function handleInstantSearch(e) {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
searchIcons();
}, 300);
}

// Обработчик поиска по кнопке
function handleButtonSearch() {
searchIcons();
}

// Обработчик клавиш
function handleKeyDown(e) {
// Enter запускает поиск
if (e.key === 'Enter') {
e.preventDefault();
searchIcons();
}

// Escape очищает поиск
if (e.key === 'Escape') {
e.preventDefault();
clearSearch();
}
}

// Инициализация режима поиска
function initSearchMode() {
const selectedMode = document.querySelector('input[name="search-mode"]:checked').value;
const searchInput = document.getElementById('iconsSearch');
const searchBtn = document.getElementById('searchBtn');
const clearBtn = document.getElementById('clearSearch');

// Удаляем все обработчики
searchInput.removeEventListener('input', handleInstantSearch);
searchInput.removeEventListener('keydown', handleKeyDown);
searchBtn.removeEventListener('click', handleButtonSearch);
clearBtn.removeEventListener('click', clearSearch);

// Добавляем общие обработчики
searchInput.addEventListener('keydown', handleKeyDown);
clearBtn.addEventListener('click', clearSearch);

if (selectedMode === 'instant') {
// Мгновенный поиск
searchInput.addEventListener('input', handleInstantSearch);
searchBtn.style.display = 'none';
searchInput.style.borderRadius = '8px';
searchInput.style.paddingRight = '40px';
} else {
// Поиск по кнопке
searchBtn.addEventListener('click', handleButtonSearch);
searchBtn.style.display = 'block';
searchInput.style.borderRadius = '8px 0 0 8px';
searchInput.style.paddingRight = '40px';
}

// Обновляем отображение
searchIcons();
}

// Функция для копирования кода
function copyCode(element) {
const code = element.querySelector('code').textContent;

navigator.clipboard.writeText(code).then(() => {
const success = element.querySelector('.copy-success');
success.classList.add('show');

setTimeout(() => {
success.classList.remove('show');
}, 2000);
}).catch(err => {
console.error('Ошибка при копировании:', err);
// Fallback для старых браузеров
const textArea = document.createElement('textarea');
textArea.value = code;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);

const success = element.querySelector('.copy-success');
success.classList.add('show');
setTimeout(() => {
success.classList.remove('show');
}, 2000);
});
}

// Инициализация после загрузки DOM
document.addEventListener('DOMContentLoaded', function() {
// Инициализируем поиск
initSearchMode();

// Обработчики переключения режима поиска
const modeRadios = document.querySelectorAll('input[name="search-mode"]');
modeRadios.forEach(radio => {
radio.addEventListener('change', initSearchMode);
});

// Изоляция событий
const searchInput = document.getElementById('iconsSearch');
if (searchInput) {
const stopEvents = (e) => {
e.stopPropagation();
e.stopImmediatePropagation();
};

searchInput.addEventListener('keydown', stopEvents, true);
searchInput.addEventListener('keyup', stopEvents, true);
searchInput.addEventListener('input', stopEvents, true);
searchInput.addEventListener('focus', stopEvents, true);
searchInput.addEventListener('click', stopEvents, true);
}
});

// Глобальная защита от всплытия
document.addEventListener('keydown', function(e) {
const searchInput = document.getElementById('iconsSearch');
if (searchInput && document.activeElement === searchInput) {
e.stopImmediatePropagation();
}
}, true);
</script>
<div class="icons-gallery">
<h2>Галерея иконок</h2>

{{ if .Site.Data.icons }}
{{ $icons := .Site.Data.icons }}
{{ $descriptions := .Site.Data.icon_descriptions | default dict }}

<div class="icons-controls">
<div class="icons-stats">
Всего иконок: <strong>{{ len $icons }}</strong>
</div>

<div class="search-filters">
<label class="filter-checkbox">
<input type="checkbox" id="showWithDescription">
<span>Только с описанием</span>
</label>
</div>

<div class="search-container">
<div class="search-mode-container">
<label class="search-mode-label">
<input type="radio" name="search-mode" value="instant" checked>
<span>Мгновенный поиск</span>
</label>
<label class="search-mode-label">
<input type="radio" name="search-mode" value="button">
<span>Поиск по кнопке</span>
</label>
</div>

<div class="search-box instant-mode">
<input
type="text"
id="iconsSearch"
placeholder="Поиск по названию или описанию..."
class="search-input"
>
<button id="clearSearch" class="clear-btn" title="Очистить поиск">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor">
<path d="M1 1L13 13M13 1L1 13"/>
</svg>
</button>
<button id="searchBtn" class="search-btn">Найти</button>
</div>
</div>
</div>

<div class="icons-table-container">
<table class="icons-table" id="iconsTable">
<thead>
<tr>
<th>Иконка</th>
<th>Название</th>
<th>Описание</th>
<th>Размер</th>
<th>Код для вставки</th>
</tr>
</thead>
<tbody>
{{ range $name, $svg := $icons }}
{{ $description := index $descriptions $name | default "" }}
<tr class="icon-row" data-name="{{ $name | lower }}" data-description="{{ $description | lower }}" data-has-description="{{ if $description }}true{{ else }}false{{ end }}">
<td class="icon-cell">
<div class="icon-svg-small">{{ $svg | safeHTML }}</div>
</td>
<td class="name-cell">
<code>{{ $name }}</code>
</td>
<td class="description-cell">
{{ if $description }}
{{ $description }}
{{ else }}
<span class="no-description">—</span>
{{ end }}
</td>
<td class="size-cell">
16×16 px
</td>
<td class="code-cell">
<div class="code-snippet" onclick="copyCode(this)">
<code>{{ "{{<" }}icon "{{ $name }}"{{ ">"}}}}</code>
<span class="copy-tooltip">Кликните для копирования</span>
<div class="copy-success">
<div class="success-icon">✓</div>
<div>Скопировано!</div>
</div>
</div>
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>

<div class="no-results" id="noResults">
<p>Иконки не найдены. Попробуйте другой запрос.</p>
</div>
{{ else }}
<div class="error-message">
<h3>Ошибка: данные иконок не найдены!</h3>
<p>Проверьте файл data/icons.yaml</p>
</div>
{{ end }}
</div>

<style>
.icons-gallery {
margin: 40px 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.icons-controls {
display: grid;
grid-template-columns: auto 1fr;
gap: 20px;
margin-bottom: 20px;
align-items: start;
}

.icons-stats {
background: #f8f9fa;
padding: 12px 20px;
border-radius: 8px;
font-size: 14px;
color: #555;
white-space: nowrap;
}

.search-filters {
grid-column: 1;
grid-row: 2;
}

.filter-checkbox {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-size: 14px;
color: #555;
padding: 8px 12px;
border-radius: 6px;
transition: background 0.3s ease;
}

.filter-checkbox:hover {
background: #f0f0f0;
}

.filter-checkbox input[type="checkbox"] {
margin: 0;
}

.search-container {
grid-column: 2;
grid-row: 1 / span 2;
display: flex;
flex-direction: column;
gap: 12px;
min-width: 300px;
}

.search-mode-container {
display: flex;
gap: 20px;
}

.search-mode-label {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-size: 14px;
color: #555;
}

.search-mode-label input[type="radio"] {
margin: 0;
}

.search-box {
display: flex;
position: relative;
width: 100%;
align-items: center;
}

.search-input {
padding: 12px 40px 12px 16px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 14px;
width: 100%;
transition: border-color 0.3s ease;
background: white;
flex: 1;
}

.search-input:focus {
outline: none;
border-color: #007acc;
box-shadow: 0 0 0 3px rgba(0, 122, 204, 0.1);
}

.clear-btn {
position: absolute;
right: 110px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
padding: 6px;
cursor: pointer;
color: #999;
border-radius: 50%;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
pointer-events: none;
}

.clear-btn.visible {
opacity: 1;
pointer-events: auto;
}

.clear-btn:hover {
color: #666;
background: #f0f0f0;
}

.search-btn {
padding: 12px 20px;
background: #007acc;
color: white;
border: 2px solid #007acc;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s ease;
white-space: nowrap;
margin-left: 10px;
flex-shrink: 0;
}

.search-btn:hover {
background: #005a9e;
border-color: #005a9e;
}

/* Режимы поиска */
.search-box.instant-mode .search-btn {
display: none;
}

.search-box.button-mode .search-btn {
display: block;
}

.search-box.button-mode .search-input {
border-radius: 8px 0 0 8px;
border-right: none;
padding-right: 40px;
}

.search-box.button-mode .clear-btn {
right: 110px;
}

.search-box.instant-mode .search-input {
border-radius: 8px;
padding-right: 40px;
}

.search-box.instant-mode .clear-btn {
right: 10px;
}

.icons-table-container {
overflow-x: auto;
border: 1px solid #e1e5e9;
border-radius: 8px;
background: white;
margin-top: 10px;
}

.icons-table {
width: 100%;
border-collapse: collapse;
}

.icons-table th {
background: #f8f9fa;
padding: 16px;
text-align: left;
font-weight: 600;
color: #555;
border-bottom: 2px solid #e1e5e9;
}

.icons-table td {
padding: 12px 16px;
border-bottom: 1px solid #f0f0f0;
}

.icon-row {
transition: opacity 0.3s ease;
}

.icon-row.hidden {
display: none;
}

.icon-row:hover {
background: #fafafa;
}

.icon-cell {
text-align: center;
width: 60px;
}

.icon-svg-small {
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
}

.icon-svg-small svg {
width: 16px;
height: 16px;
min-width: 16px;
min-height: 16px;
}

.name-cell {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
color: #333;
width: 150px;
}

.name-cell code {
background: #f5f5f5;
padding: 4px 8px;
border-radius: 4px;
border: 1px solid #eee;
font-size: 12px;
}

.description-cell {
color: #666;
font-size: 14px;
line-height: 1.4;
max-width: 300px;
}

.no-description {
color: #999;
font-style: italic;
}

.size-cell {
color: #888;
font-size: 12px;
text-align: center;
width: 80px;
}

.code-cell {
width: 200px;
}

.code-snippet {
position: relative;
background: #f8f9fa;
padding: 10px 14px;
border-radius: 6px;
border: 1px solid #e9ecef;
cursor: pointer;
transition: all 0.3s ease;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
min-height: 40px;
display: flex;
align-items: center;
}

.code-snippet:hover {
background: #e3f2fd;
border-color: #2196f3;
}

.code-snippet code {
background: none;
border: none;
padding: 0;
color: #1976d2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
flex: 1;
}

.copy-tooltip {
position: absolute;
top: -35px;
left: 50%;
transform: translateX(-50%);
background: #333;
color: white;
padding: 6px 12px;
border-radius: 4px;
font-size: 12px;
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
white-space: nowrap;
z-index: 1000;
}

.code-snippet:hover .copy-tooltip {
opacity: 1;
}

.copy-success {
position: absolute;
top: -60px;
left: 50%;
transform: translateX(-50%);
background: #4caf50;
color: white;
padding: 10px 15px;
border-radius: 6px;
font-size: 12px;
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
z-index: 1000;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}

.copy-success.show {
opacity: 1;
}

.success-icon {
font-size: 16px;
font-weight: bold;
}

.no-results {
text-align: center;
padding: 40px;
color: #888;
font-style: italic;
display: none;
}

.error-message {
color: #d32f2f;
padding: 20px;
border: 2px solid #ffcdd2;
border-radius: 8px;
background: #ffebee;
}

/* Адаптивность */
@media (max-width: 1024px) {
.icons-controls {
grid-template-columns: 1fr;
gap: 15px;
}

.search-container {
grid-column: 1;
grid-row: 3;
}

.description-cell {
display: none;
}

.code-cell {
width: 180px;
}
}

@media (max-width: 768px) {
.search-mode-container {
flex-direction: column;
gap: 10px;
}

.search-box {
flex-direction: column;
gap: 10px;
}

.search-input {
border-radius: 8px !important;
padding-right: 16px;
}

.clear-btn {
right: 10px !important;
top: 50%;
}

.search-btn {
margin-left: 0;
width: 100%;
}

.icons-table th,
.icons-table td {
padding: 10px 12px;
}

.code-cell {
display: none;
}

.name-cell {
width: 120px;
}

.search-box.button-mode .search-input {
border-right: 2px solid #e1e5e9;
}

.search-box.button-mode .clear-btn {
right: 10px !important;
}
}
</style>

<script>
// Глобальные переменные
let searchTimeout = null;
let currentSearchMode = 'instant';
let showOnlyWithDescription = false;

// Основная функция поиска и фильтрации
function performSearch() {
const searchTerm = document.getElementById('iconsSearch').value.toLowerCase();
const rows = document.querySelectorAll('.icon-row');
const noResults = document.getElementById('noResults');
const clearBtn = document.getElementById('clearSearch');
let visibleCount = 0;

rows.forEach(row => {
const iconName = row.getAttribute('data-name');
const iconDescription = row.getAttribute('data-description');
const hasDescription = row.getAttribute('data-has-description') === 'true';

// Проверяем фильтр по описанию
const descriptionFilter = !showOnlyWithDescription || hasDescription;

// Проверяем поисковый запрос
const searchFilter = searchTerm === '' ||
iconName.includes(searchTerm) ||
iconDescription.includes(searchTerm);

// Показываем/скрываем строку
if (descriptionFilter && searchFilter) {
row.classList.remove('hidden');
visibleCount++;
} else {
row.classList.add('hidden');
}
});

// Показываем/скрываем сообщение "нет результатов"
noResults.style.display = visibleCount === 0 ? 'block' : 'none';

// Показываем/скрываем кнопку очистки
clearBtn.classList.toggle('visible', searchTerm !== '');
}

// Функция очистки поиска
function clearSearch() {
const searchInput = document.getElementById('iconsSearch');
searchInput.value = '';
searchInput.focus();
performSearch();
}

// Обработчик мгновенного поиска
function handleInstantSearch() {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(performSearch, 300);
}

// Обработчик поиска по кнопке
function handleButtonSearch() {
performSearch();
}

// Обработчик клавиш
function handleKeyDown(e) {
if (e.key === 'Enter') {
e.preventDefault();
performSearch();
}

if (e.key === 'Escape') {
e.preventDefault();
clearSearch();
}
}

// Переключение режима поиска
function initSearchMode() {
const searchMode = document.querySelector('input[name="search-mode"]:checked').value;
const searchBox = document.querySelector('.search-box');
const searchInput = document.getElementById('iconsSearch');
const searchBtn = document.getElementById('searchBtn');

currentSearchMode = searchMode;

// Обновляем классы для стилей
searchBox.className = 'search-box ' + (searchMode === 'instant' ? 'instant-mode' : 'button-mode');

// Обновляем обработчики
searchInput.removeEventListener('input', handleInstantSearch);
searchBtn.removeEventListener('click', handleButtonSearch);

if (searchMode === 'instant') {
searchInput.addEventListener('input', handleInstantSearch);
} else {
searchBtn.addEventListener('click', handleButtonSearch);
}
}

// Фильтр по описанию
function toggleDescriptionFilter() {
showOnlyWithDescription = document.getElementById('showWithDescription').checked;
performSearch();
}

// Функция для копирования кода
function copyCode(element) {
const code = element.querySelector('code').textContent;

navigator.clipboard.writeText(code).then(() => {
const success = element.querySelector('.copy-success');
success.classList.add('show');

setTimeout(() => {
success.classList.remove('show');
}, 2000);
}).catch(err => {
// Fallback
const textArea = document.createElement('textarea');
textArea.value = code;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);

const success = element.querySelector('.copy-success');
success.classList.add('show');
setTimeout(() => {
success.classList.remove('show');
}, 2000);
});
}

// Инициализация
document.addEventListener('DOMContentLoaded', function() {
// Инициализируем элементы
const searchInput = document.getElementById('iconsSearch');
const clearBtn = document.getElementById('clearSearch');
const modeRadios = document.querySelectorAll('input[name="search-mode"]');
const descriptionFilter = document.getElementById('showWithDescription');

// Основные обработчики
searchInput.addEventListener('keydown', handleKeyDown);
clearBtn.addEventListener('click', clearSearch);
descriptionFilter.addEventListener('change', toggleDescriptionFilter);

// Обработчики переключения режима
modeRadios.forEach(radio => {
radio.addEventListener('change', initSearchMode);
});

// Инициализация
initSearchMode();
performSearch();

// Изоляция событий
const stopEvents = (e) => {
if (e.target === searchInput) {
e.stopPropagation();
}
};

searchInput.addEventListener('keydown', stopEvents, true);
searchInput.addEventListener('keyup', stopEvents, true);
searchInput.addEventListener('input', stopEvents, true);
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Элементы управления
const searchInput = document.getElementById('rockSearchField');
const searchBtn = document.getElementById('rockSearchButton');
const clearBtn = document.getElementById('rockResetButton');
const modeRadios = document.querySelectorAll('input[name="search-mode"]');

let currentSearchTerm = '';
let currentMode = 'button';
let searchTimeout;
let originalContents = new Map();

// Стили для подсветки
const style = document.createElement('style');
style.textContent = `
.rock-search-match {
background-color: #889cf8;
font-weight: bold;
border-radius: 3px;
padding: 0 2px;
}
.tab-with-results {
position: relative;
background-color: #f0f7ff !important;
}
.tab-with-results::after {
content: '';
position: absolute;
top: 5px;
right: 5px;
width: 8px;
height: 8px;
background-color: #ff5722;
border-radius: 50%;
}
.hidden-row {
display: none !important;
}
`;
document.head.appendChild(style);

// Сохраняем оригинальное содержимое
function saveOriginalContents() {
document.querySelectorAll('td, th').forEach(cell => {
originalContents.set(cell, cell.innerHTML);
});
}

// Восстанавливаем оригинальное содержимое
function restoreOriginalContents() {
originalContents.forEach((content, cell) => {
cell.innerHTML = content;
});
}

// Функция сброса поиска
function resetSearch() {
searchInput.value = '';
currentSearchTerm = '';
restoreOriginalContents();

document.querySelectorAll('.tab-with-results, .hidden-row').forEach(el => {
el.classList.remove('tab-with-results', 'hidden-row');
});

document.querySelectorAll('tr, details').forEach(el => {
el.style.display = '';
});

document.querySelectorAll('details').forEach(section => {
section.open = false;
});

const tabs = document.querySelectorAll('.tab-content');
if (tabs.length) {
tabs.forEach(tab => tab.style.display = 'none');
tabs[0].style.display = '';
}
}

// Улучшенная функция выделения совпадений
function highlightMatches(text, searchTerm) {
if (!searchTerm) return text;
try {
const regex = new RegExp(`(${searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
return text.replace(regex, '<span class="rock-search-match">$1</span>');
} catch (e) {
return text;
}
}

// Основная функция поиска (полностью переработанная)
function performSearch() {
const searchTerm = searchInput.value.trim().toLowerCase();
if (searchTerm === currentSearchTerm) return;
currentSearchTerm = searchTerm;

if (searchTerm === '') {
resetSearch();
return;
}

restoreOriginalContents();
let foundCount = 0;

// Ищем во ВСЕХ строках таблиц (включая заголовки)
document.querySelectorAll('table').forEach(table => {
const allRows = table.querySelectorAll('tr');
let tableHasMatches = false;

allRows.forEach(row => {
const cells = row.querySelectorAll('td, th');
let rowHasMatches = false;

cells.forEach(cell => {
const originalHtml = originalContents.get(cell) || cell.innerHTML;
const textContent = cell.textContent.toLowerCase();

if (textContent.includes(searchTerm)) {
cell.innerHTML = highlightMatches(originalHtml, searchTerm);
foundCount++;
rowHasMatches = true;
tableHasMatches = true;
}
});

// Не скрываем заголовки таблиц (первые строки)
if (row !== table.querySelector('tr:first-child')) {
row.style.display = rowHasMatches ? '' : 'none';
}
});

// Показываем/скрываем родительские элементы
const parentSection = table.closest('details');
if (parentSection) {
parentSection.style.display = tableHasMatches ? '' : 'none';
if (tableHasMatches) parentSection.open = true;
}
});

// Обработка вкладок
document.querySelectorAll('.tab-content').forEach(tab => {
const tabTables = tab.querySelectorAll('table');
let tabHasMatches = false;

tabTables.forEach(table => {
const hasMatches = Array.from(table.querySelectorAll('td, th')).some(cell =>
cell.textContent.toLowerCase().includes(searchTerm)
);

if (hasMatches) {
tabHasMatches = true;
table.querySelectorAll('tr').forEach(row => {
row.style.display = '';
});
}
});

if (tabHasMatches) {
tab.style.display = '';
const tabId = tab.id;
if (tabId) {
const tabHeader = document.querySelector(`[data-tab="${tabId}"]`);
if (tabHeader) tabHeader.classList.add('tab-with-results');
}
} else {
tab.style.display = 'none';
}
});
}

// Инициализация режима поиска
function initSearchMode() {
currentMode = document.querySelector('input[name="search-mode"]:checked').value;

searchInput.removeEventListener('input', handleInstantSearch);
searchInput.removeEventListener('input', handleDelayedSearch);

if (currentMode === 'instant') {
searchInput.addEventListener('input', handleInstantSearch);
searchBtn.classList.add('hidden');
document.querySelector('.tree-search-box').classList.add('no-button');
} else {
searchInput.addEventListener('input', handleDelayedSearch);
searchBtn.classList.remove('hidden');
document.querySelector('.tree-search-box').classList.remove('no-button');
}
}

// Обработчики событий
function handleInstantSearch() {
clearTimeout(searchTimeout);
performSearch();
}

function handleDelayedSearch() {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
if (searchInput.value.trim() === '') {
resetSearch();
}
}, 300);
}

// Инициализация
saveOriginalContents();
initSearchMode();
searchBtn.addEventListener('click', performSearch);
searchInput.addEventListener('keypress', (e) => e.key === 'Enter' && performSearch());
clearBtn.addEventListener('click', resetSearch);
modeRadios.forEach(radio => radio.addEventListener('change', initSearchMode));
});
</script>

<style>
.tree-search-panel {
margin: 20px 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

.tree-search-box {
position: relative;
display: flex;
margin-bottom: 8px;
height: 36px; /* Фиксированная высота */
align-items: center; /* Выравнивание по центру */
}

.tree-search-input {
flex: 1;
height: 100%;
padding: 0 30px 0 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box;
transition: border-color 0.2s;
}

.tree-search-input:focus {
border-color: #2188ff;
outline: none;
}

.tree-search-btn {
height: 36px; /* Такая же высота как у поля ввода */
margin-left: 8px;
padding: 0 12px;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
flex-shrink: 0; /* Не сжимается при скрытии */
transition: opacity 0.2s, width 0.2s, margin 0.2s;
}

.tree-search-btn:hover {
background: #68aeff;
}

.tree-search-btn.hidden {
opacity: 0;
width: 0;
margin-left: 0;
padding: 0;
overflow: hidden;
}

.tree-search-clear {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
font-size: 18px;
color: #999;
transition: all 0.2s;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}

.tree-search-clear:hover {
color: #666;
}

.tree-search-box:not(.no-button) .tree-search-clear {
right: 90px;
}

.search-modes {
display: flex;
gap: 15px;
font-size: 13px;
color: #666;
padding: 5px 0;
}

.search-modes label {
display: flex;
align-items: center;
gap: 5px;
cursor: pointer;
user-select: none;
}

.search-modes input[type="radio"] {
margin: 0;
}
</style>
<div class="icons-gallery">
<h2>Галерея иконок</h2>

{{ if .Site.Data.icons }}
{{ $icons := .Site.Data.icons }}
{{ $descriptions := .Site.Data.icon_descriptions | default dict }}

<div class="icons-controls">
<div class="icons-stats">
Всего иконок: <strong>{{ len $icons }}</strong>
</div>

<div class="search-filters">
<label class="filter-checkbox">
<input type="checkbox" id="showWithDescription">
<span>Только с описанием</span>
</label>
</div>

<div class="tree-search-panel">
<div class="search-modes">
<label>
<input type="radio" name="search-mode" value="instant" checked>
<span>Мгновенный поиск</span>
</label>
<label>
<input type="radio" name="search-mode" value="button">
<span>Поиск по кнопке</span>
</label>
</div>

<div class="tree-search-box no-button">
<input
type="text"
id="iconsSearch"
placeholder="Поиск по названию или описанию..."
class="tree-search-input"
>
<button id="clearSearch" class="tree-search-clear" title="Очистить поиск">×</button>
<button id="searchBtn" class="tree-search-btn hidden">Найти</button>
</div>
</div>
</div>

<div class="icons-table-container">
<table class="icons-table" id="iconsTable">
<thead>
<tr>
<th>Иконка</th>
<th>Название</th>
<th>Описание</th>
<th>Размер</th>
<th>Код для вставки</th>
</tr>
</thead>
<tbody>
{{ range $name, $svg := $icons }}
{{ $description := index $descriptions $name | default "" }}
<tr class="icon-row" data-name="{{ $name | lower }}" data-description="{{ $description | lower }}" data-has-description="{{ if $description }}true{{ else }}false{{ end }}">
<td class="icon-cell">
<div class="icon-svg-small">{{ $svg | safeHTML }}</div>
</td>
<td class="name-cell">
<code>{{ $name }}</code>
</td>
<td class="description-cell">
{{ if $description }}
{{ $description }}
{{ else }}
<span class="no-description">—</span>
{{ end }}
</td>
<td class="size-cell">
16×16 px
</td>
<td class="code-cell">
<div class="code-snippet" onclick="copyCode(this)">
<code>{{ "{{<" }}icon "{{ $name }}"{{ ">"}}}}</code>
<span class="copy-tooltip">Кликните для копирования</span>
<div class="copy-success">
<div class="success-icon">✓</div>
<div>Скопировано!</div>
</div>
</div>
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>

<div class="no-results" id="noResults" style="display: none;">
<p>Иконки не найдены. Попробуйте другой запрос.</p>
</div>
{{ else }}
<div class="error-message">
<h3>Ошибка: данные иконок не найдены!</h3>
<p>Проверьте файл data/icons.yaml</p>
</div>
{{ end }}
</div>

<style>
.icons-gallery {
margin: 40px 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.icons-controls {
display: grid;
grid-template-columns: auto 1fr;
gap: 20px;
margin-bottom: 20px;
align-items: start;
}

.icons-stats {
background: #f8f9fa;
padding: 12px 20px;
border-radius: 8px;
font-size: 14px;
color: #555;
white-space: nowrap;
}

.search-filters {
grid-column: 1;
grid-row: 2;
}

.filter-checkbox {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
font-size: 14px;
color: #555;
padding: 8px 12px;
border-radius: 6px;
transition: background 0.3s ease;
}

.filter-checkbox:hover {
background: #f0f0f0;
}

.filter-checkbox input[type="checkbox"] {
margin: 0;
}

.tree-search-panel {
grid-column: 2;
grid-row: 1 / span 2;
display: flex;
flex-direction: column;
gap: 12px;
}

.search-modes {
display: flex;
gap: 20px;
font-size: 14px;
color: #555;
}

.search-modes label {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
}

.search-modes input[type="radio"] {
margin: 0;
}

.tree-search-box {
position: relative;
display: flex;
margin-bottom: 8px;
height: 36px;
align-items: center;
}

.tree-search-input {
flex: 1;
height: 100%;
padding: 0 30px 0 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box;
transition: border-color 0.2s;
}

.tree-search-input:focus {
border-color: #2188ff;
outline: none;
}

.tree-search-btn {
height: 36px;
margin-left: 8px;
padding: 0 12px;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
flex-shrink: 0;
transition: opacity 0.2s, width 0.2s, margin 0.2s;
}

.tree-search-btn:hover {
background: #68aeff;
}

.tree-search-btn.hidden {
opacity: 0;
width: 0;
margin-left: 0;
padding: 0;
overflow: hidden;
}

.tree-search-clear {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
font-size: 18px;
color: #999;
transition: all 0.2s;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}

.tree-search-clear:hover {
color: #666;
}

.tree-search-box:not(.no-button) .tree-search-clear {
right: 90px;
}

.icons-table-container {
overflow-x: auto;
border: 1px solid #e1e5e9;
border-radius: 8px;
background: white;
margin-top: 10px;
}

.icons-table {
width: 100%;
border-collapse: collapse;
}

.icons-table th {
background: #f8f9fa;
padding: 16px;
text-align: left;
font-weight: 600;
color: #555;
border-bottom: 2px solid #e1e5e9;
}

.icons-table td {
padding: 12px 16px;
border-bottom: 1px solid #f0f0f0;
}

.icon-row.hidden {
display: none;
}

.icon-row:hover {
background: #fafafa;
}

.icon-cell {
text-align: center;
width: 60px;
}

.icon-svg-small {
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
}

.icon-svg-small svg {
width: 16px;
height: 16px;
min-width: 16px;
min-height: 16px;
}

.name-cell {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
color: #333;
width: 150px;
}

.name-cell code {
background: #f5f5f5;
padding: 4px 8px;
border-radius: 4px;
border: 1px solid #eee;
font-size: 12px;
}

.description-cell {
color: #666;
font-size: 14px;
line-height: 1.4;
max-width: 300px;
}

.no-description {
color: #999;
font-style: italic;
}

.size-cell {
color: #888;
font-size: 12px;
text-align: center;
width: 80px;
}

.code-cell {
width: 200px;
}

.code-snippet {
position: relative;
background: #f8f9fa;
padding: 10px 14px;
border-radius: 6px;
border: 1px solid #e9ecef;
cursor: pointer;
transition: all 0.3s ease;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 13px;
min-height: 40px;
display: flex;
align-items: center;
}

.code-snippet:hover {
background: #e3f2fd;
border-color: #2196f3;
}

.code-snippet code {
background: none;
border: none;
padding: 0;
color: #1976d2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
flex: 1;
}

.copy-tooltip {
position: absolute;
top: -35px;
left: 50%;
transform: translateX(-50%);
background: #333;
color: white;
padding: 6px 12px;
border-radius: 4px;
font-size: 12px;
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
white-space: nowrap;
z-index: 1000;
}

.code-snippet:hover .copy-tooltip {
opacity: 1;
}

.copy-success {
position: absolute;
top: -60px;
left: 50%;
transform: translateX(-50%);
background: #4caf50;
color: white;
padding: 10px 15px;
border-radius: 6px;
font-size: 12px;
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
z-index: 1000;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}

.copy-success.show {
opacity: 1;
}

.success-icon {
font-size: 16px;
font-weight: bold;
}

.no-results {
text-align: center;
padding: 40px;
color: #888;
font-style: italic;
display: none;
}

.error-message {
color: #d32f2f;
padding: 20px;
border: 2px solid #ffcdd2;
border-radius: 8px;
background: #ffebee;
}

.hidden {
display: none !important;
}

/* Адаптивность */
@media (max-width: 1024px) {
.icons-controls {
grid-template-columns: 1fr;
gap: 15px;
}

.tree-search-panel {
grid-column: 1;
grid-row: 3;
}

.description-cell {
display: none;
}

.code-cell {
width: 180px;
}
}

@media (max-width: 768px) {
.search-modes {
flex-direction: column;
gap: 10px;
}

.icons-table th,
.icons-table td {
padding: 10px 12px;
}

.code-cell {
display: none;
}

.name-cell {
width: 120px;
}
}
</style>

<script>
document.addEventListener('DOMContentLoaded', function() {
// Элементы управления
const searchInput = document.getElementById('iconsSearch');
const searchBtn = document.getElementById('searchBtn');
const clearBtn = document.getElementById('clearSearch');
const modeRadios = document.querySelectorAll('input[name="search-mode"]');
const descriptionFilter = document.getElementById('showWithDescription');

let currentSearchTerm = '';
let currentMode = 'instant';
let searchTimeout;
let showOnlyWithDescription = false;

// Инициализация режима поиска
function initSearchMode() {
currentMode = document.querySelector('input[name="search-mode"]:checked').value;
const searchBox = document.querySelector('.tree-search-box');

// Удаляем все обработчики
searchInput.removeEventListener('input', handleInstantSearch);

if (currentMode === 'instant') {
// Мгновенный поиск
searchInput.addEventListener('input', handleInstantSearch);
searchBtn.classList.add('hidden');
searchBox.classList.add('no-button');
} else {
// Поиск по кнопке
searchBtn.classList.remove('hidden');
searchBox.classList.remove('no-button');
}
}

// Основная функция поиска и фильтрации
function performSearch() {
const searchTerm = searchInput.value.toLowerCase();
const rows = document.querySelectorAll('.icon-row');
const noResults = document.getElementById('noResults');
let visibleCount = 0;

rows.forEach(row => {
const iconName = row.getAttribute('data-name');
const iconDescription = row.getAttribute('data-description');
const hasDescription = row.getAttribute('data-has-description') === 'true';

// Проверяем фильтр по описанию
const descriptionFilter = !showOnlyWithDescription || hasDescription;

// Проверяем поисковый запрос
const searchFilter = searchTerm === '' ||
iconName.includes(searchTerm) ||
iconDescription.includes(searchTerm);

// Показываем/скрываем строку
if (descriptionFilter && searchFilter) {
row.classList.remove('hidden');
visibleCount++;
} else {
row.classList.add('hidden');
}
});

// Показываем/скрываем сообщение "нет результатов"
noResults.style.display = visibleCount === 0 && searchTerm !== '' ? 'block' : 'none';
}

// Функция очистки поиска
function clearSearch() {
searchInput.value = '';
searchInput.focus();
performSearch();
}

// Обработчики событий
function handleInstantSearch() {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(performSearch, 300);
}

function handleButtonSearch() {
performSearch();
}

function toggleDescriptionFilter() {
showOnlyWithDescription = descriptionFilter.checked;
performSearch();
}

// Функция для копирования кода
function copyCode(element) {
const code = element.querySelector('code').textContent;

navigator.clipboard.writeText(code).then(() => {
const success = element.querySelector('.copy-success');
success.classList.add('show');

setTimeout(() => {
success.classList.remove('show');
}, 2000);
}).catch(err => {
// Fallback
const textArea = document.createElement('textarea');
textArea.value = code;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);

const success = element.querySelector('.copy-success');
success.classList.add('show');
setTimeout(() => {
success.classList.remove('show');
}, 2000);
});
}

// Инициализация
initSearchMode();
performSearch();

// Обработчики событий
searchBtn.addEventListener('click', handleButtonSearch);
clearBtn.addEventListener('click', clearSearch);
descriptionFilter.addEventListener('change', toggleDescriptionFilter);

searchInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
performSearch();
}
});

modeRadios.forEach(radio => {
radio.addEventListener('change', initSearchMode);
});

// Изоляция событий для предотвращения конфликта с глобальным поиском
const stopEvents = (e) => {
e.stopPropagation();
};

searchInput.addEventListener('keydown', stopEvents, true);
searchInput.addEventListener('keyup', stopEvents, true);
searchInput.addEventListener('input', stopEvents, true);
searchInput.addEventListener('focus', stopEvents, true);
searchInput.addEventListener('click', stopEvents, true);
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Элементы управления
const searchInput = document.getElementById('iconsSearch');
const searchBtn = document.getElementById('searchBtn');
const clearBtn = document.getElementById('clearSearch');
const modeRadios = document.querySelectorAll('input[name="search-mode"]');
const descriptionFilter = document.getElementById('showWithDescription');

let currentSearchTerm = '';
let currentMode = 'instant';
let searchTimeout;
let showOnlyWithDescription = false;

// Инициализация режима поиска
function initSearchMode() {
currentMode = document.querySelector('input[name="search-mode"]:checked').value;
const searchBox = document.querySelector('.tree-search-box');

// Удаляем все обработчики
searchInput.removeEventListener('input', handleInstantSearch);
searchInput.removeEventListener('keypress', handleEnterPress);

if (currentMode === 'instant') {
// Мгновенный поиск
searchInput.addEventListener('input', handleInstantSearch);
searchInput.addEventListener('keypress', handleEnterPress);
searchBtn.classList.add('hidden');
searchBox.classList.add('no-button');
} else {
// Поиск по кнопке
searchInput.addEventListener('keypress', handleEnterPress);
searchBtn.classList.remove('hidden');
searchBox.classList.remove('no-button');
}

// Принудительно обновляем поиск при смене режима
performSearch();
}

// Основная функция поиска и фильтрации
function performSearch() {
const searchTerm = searchInput.value.toLowerCase();
const rows = document.querySelectorAll('.icon-row');
const noResults = document.getElementById('noResults');
let visibleCount = 0;

rows.forEach(row => {
const iconName = row.getAttribute('data-name');
const iconDescription = row.getAttribute('data-description');
const hasDescription = row.getAttribute('data-has-description') === 'true';

// Проверяем фильтр по описанию
const descriptionFilter = !showOnlyWithDescription || hasDescription;

// Проверяем поисковый запрос
const searchFilter = searchTerm === '' ||
iconName.includes(searchTerm) ||
iconDescription.includes(searchTerm);

// Показываем/скрываем строку
if (descriptionFilter && searchFilter) {
row.classList.remove('hidden');
visibleCount++;
} else {
row.classList.add('hidden');
}
});

// Показываем/скрываем сообщение "нет результатов"
noResults.style.display = visibleCount === 0 && searchTerm !== '' ? 'block' : 'none';
}

// Функция очистки поиска
function clearSearch() {
searchInput.value = '';
searchInput.focus();
performSearch();
}

// Обработчики событий
function handleInstantSearch() {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(performSearch, 100); // Уменьшил задержку для мгновенности
}

function handleButtonSearch() {
performSearch();
}

function handleEnterPress(e) {
if (e.key === 'Enter') {
e.preventDefault();
performSearch();
}
}

function toggleDescriptionFilter() {
showOnlyWithDescription = descriptionFilter.checked;
performSearch();
}

// Функция для копирования кода
function copyCode(element) {
const code = element.querySelector('code').textContent;

navigator.clipboard.writeText(code).then(() => {
const success = element.querySelector('.copy-success');
success.classList.add('show');

setTimeout(() => {
success.classList.remove('show');
}, 2000);
}).catch(err => {
// Fallback
const textArea = document.createElement('textarea');
textArea.value = code;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);

const success = element.querySelector('.copy-success');
success.classList.add('show');
setTimeout(() => {
success.classList.remove('show');
}, 2000);
});
}

// Инициализация
initSearchMode();

// Обработчики событий
searchBtn.addEventListener('click', handleButtonSearch);
clearBtn.addEventListener('click', clearSearch);
descriptionFilter.addEventListener('change', toggleDescriptionFilter);

modeRadios.forEach(radio => {
radio.addEventListener('change', initSearchMode);
});

// Изоляция событий для предотвращения конфликта с глобальным поиском
const stopEvents = (e) => {
e.stopPropagation();
e.stopImmediatePropagation();
};

// Более агрессивная изоляция событий
searchInput.addEventListener('keydown', stopEvents, true);
searchInput.addEventListener('keyup', stopEvents, true);
searchInput.addEventListener('keypress', stopEvents, true);
searchInput.addEventListener('input', stopEvents, true);
searchInput.addEventListener('focus', stopEvents, true);
searchInput.addEventListener('click', stopEvents, true);
searchInput.addEventListener('mousedown', stopEvents, true);

// Дополнительная глобальная защита
document.addEventListener('keydown', function(e) {
if (e.target === searchInput || document.activeElement === searchInput) {
e.stopImmediatePropagation();
}
}, true);

document.addEventListener('keyup', function(e) {
if (e.target === searchInput || document.activeElement === searchInput) {
e.stopImmediatePropagation();
}
}, true);

document.addEventListener('input', function(e) {
if (e.target === searchInput) {
e.stopImmediatePropagation();
}
}, true);
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Элементы управления
const searchInput = document.getElementById('iconsSearch');
const searchBtn = document.getElementById('searchBtn');
const clearBtn = document.getElementById('clearSearch');
const modeRadios = document.querySelectorAll('input[name="search-mode"]');
const descriptionFilter = document.getElementById('showWithDescription');

let searchTimeout;
let showOnlyWithDescription = false;

// Основная функция поиска и фильтрации
function performSearch() {
const searchTerm = searchInput.value.toLowerCase();
const rows = document.querySelectorAll('.icon-row');
const noResults = document.getElementById('noResults');
let visibleCount = 0;

rows.forEach(row => {
const iconName = row.getAttribute('data-name');
const iconDescription = row.getAttribute('data-description');
const hasDescription = row.getAttribute('data-has-description') === 'true';

// Проверяем фильтр по описанию
const descriptionFilter = !showOnlyWithDescription || hasDescription;

// Проверяем поисковый запрос
const searchFilter = searchTerm === '' ||
iconName.includes(searchTerm) ||
iconDescription.includes(searchTerm);

// Показываем/скрываем строку
if (descriptionFilter && searchFilter) {
row.classList.remove('hidden');
visibleCount++;
} else {
row.classList.add('hidden');
}
});

// Показываем/скрываем сообщение "нет результатов"
noResults.style.display = visibleCount === 0 && searchTerm !== '' ? 'block' : 'none';
}

// Функция очистки поиска
function clearSearch() {
searchInput.value = '';
searchInput.focus();
performSearch();
}

// Обработчики событий
function handleInstantSearch() {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(performSearch, 100);
}

function handleButtonSearch() {
performSearch();
}

function handleEnterPress(e) {
if (e.key === 'Enter') {
e.preventDefault();
performSearch();
}
}

function toggleDescriptionFilter() {
showOnlyWithDescription = descriptionFilter.checked;
performSearch();
}

// Инициализация режима поиска
function initSearchMode() {
const currentMode = document.querySelector('input[name="search-mode"]:checked').value;
const searchBox = document.querySelector('.tree-search-box');

// Удаляем все обработчики
searchInput.removeEventListener('input', handleInstantSearch);
searchInput.removeEventListener('keypress', handleEnterPress);
searchBtn.removeEventListener('click', handleButtonSearch);

if (currentMode === 'instant') {
// Мгновенный поиск
searchInput.addEventListener('input', handleInstantSearch);
searchInput.addEventListener('keypress', handleEnterPress);
searchBtn.classList.add('hidden');
searchBox.classList.add('no-button');
} else {
// Поиск по кнопке
searchBtn.addEventListener('click', handleButtonSearch);
searchInput.addEventListener('keypress', handleEnterPress);
searchBtn.classList.remove('hidden');
searchBox.classList.remove('no-button');
}
}

// Функция для копирования кода
function copyCode(element) {
const code = element.querySelector('code').textContent;

navigator.clipboard.writeText(code).then(() => {
const success = element.querySelector('.copy-success');
success.classList.add('show');

setTimeout(() => {
success.classList.remove('show');
}, 2000);
}).catch(err => {
// Fallback
const textArea = document.createElement('textarea');
textArea.value = code;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);

const success = element.querySelector('.copy-success');
success.classList.add('show');
setTimeout(() => {
success.classList.remove('show');
}, 2000);
});
}

// Инициализация
initSearchMode();
performSearch(); // Initial search to show all icons

// Обработчики событий
clearBtn.addEventListener('click', clearSearch);
descriptionFilter.addEventListener('change', toggleDescriptionFilter);

modeRadios.forEach(radio => {
radio.addEventListener('change', initSearchMode);
});

// Минимальная изоляция событий - только для предотвращения всплытия
function stopPropagation(e) {
if (e.target === searchInput) {
e.stopPropagation();
}
}

searchInput.addEventListener('keydown', stopPropagation);
searchInput.addEventListener('keyup', stopPropagation);
searchInput.addEventListener('input', stopPropagation);
searchInput.addEventListener('focus', stopPropagation);
});
</script>
  • Страница 15 из 15
  • «
  • 1
  • 2
  • 13
  • 14
  • 15
Поиск:
Новый ответ
Имя:
Текст сообщения: