Форум

Отзывы и предолжения к софту от AleXStam
  • Страница 8 из 9
  • «
  • 1
  • 2
  • 6
  • 7
  • 8
  • 9
  • »
Поговорим о...
AleXStamДата: Вторник, 2025-06-24, 10:17 | Сообщение # 106
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<!-- Вставьте этот код ПЕРЕД всеми секциями с породами -->
<div id="rockSearchSystem" style="margin: 20px 0; padding: 20px; background: #f8f9fa; border-radius: 8px; border: 1px solid #e1e4e8;">
<div style="display: flex; gap: 10px;">
<input type="text" id="rockSearchField" placeholder="Введите название породы..."
style="flex: 1; padding: 12px 15px; border: 1px solid #d1d5da; border-radius: 6px; font-size: 16px;">
<button id="rockSearchButton" style="padding: 12px 20px; background: #2188ff; color: white; border: none; border-radius: 6px; cursor: pointer;">
Поиск
</button>
<button id="rockResetButton" style="padding: 12px 20px; background: #f0f0f0; color: #333; border: none; border-radius: 6px; cursor: pointer;">
Сброс
</button>
</div>
<div id="searchStatus" style="margin-top: 10px; color: #586069; font-size: 14px;">Готов к поиску</div>
</div>

<script>
// Функция для сброса поиска
function resetSearch() {
const searchField = document.getElementById('rockSearchField');
const searchStatus = document.getElementById('searchStatus');

searchField.value = '';
searchStatus.textContent = 'Готов к поиску';

// Убираем подсветку
document.querySelectorAll('.rock-search-match').forEach(el => {
el.classList.remove('rock-search-match');
});

// Закрываем все секции и показываем их
document.querySelectorAll('details').forEach(section => {
section.style.display = '';
section.open = false;
});

// Закрываем все табы (если есть система вкладок)
const tabs = document.querySelectorAll('.tab-content');
if (tabs) {
tabs.forEach(tab => {
tab.style.display = 'none';
});
// Показываем первый таб по умолчанию
if (tabs[0]) tabs[0].style.display = '';
}
}

// Функция для поиска пород
function searchRocks() {
const searchField = document.getElementById('rockSearchField');
const searchStatus = document.getElementById('searchStatus');

if (!searchField || !searchStatus) {
console.error('Элементы поиска не найдены');
return;
}

const searchTerm = searchField.value.trim().toLowerCase();
let foundCount = 0;

// Сбрасываем предыдущие результаты
document.querySelectorAll('.rock-search-match').forEach(el => {
el.classList.remove('rock-search-match');
});

// 1. Поиск в обычных секциях details
const allSections = document.querySelectorAll('details');
allSections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr');

rows.forEach((row, index) => {
if (index === 0) return; // Пропускаем заголовок

const cells = row.querySelectorAll('td');
cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (searchTerm !== '' && text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
sectionHasMatches = true;
}
});
});
});

// Управление секцией
if (searchTerm === '') {
section.style.display = '';
section.open = false;
} else if (sectionHasMatches) {
section.style.display = '';
section.open = true;
} else {
section.style.display = 'none';
}
});

// 2. Поиск во вкладках (tabs)
const allTabs = document.querySelectorAll('.tab-content');
allTabs.forEach(tab => {
const tabSections = tab.querySelectorAll('details');
let tabHasMatches = false;

tabSections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr');

rows.forEach((row, index) => {
if (index === 0) return;

const cells = row.querySelectorAll('td');
cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (searchTerm !== '' && text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
sectionHasMatches = true;
tabHasMatches = true;
}
});
});
});

// Управление секцией во вкладке
if (searchTerm === '') {
section.style.display = '';
section.open = false;
} else if (sectionHasMatches) {
section.style.display = '';
section.open = true;
} else {
section.style.display = 'none';
}
});

// Показываем вкладку, если есть совпадения
if (searchTerm !== '' && tabHasMatches) {
tab.style.display = '';
}
});

// Обновляем статус
if (searchTerm === '') {
searchStatus.textContent = 'Введите название породы для поиска';
} else if (foundCount > 0) {
searchStatus.textContent = `Найдено совпадений: ${foundCount}`;
} else {
searchStatus.textContent = 'Ничего не найдено';
}
}

// Инициализация поиска
function initializeRockSearch() {
// Добавляем стили для подсветки
const style = document.createElement('style');
style.textContent = `
.rock-search-match {
background-color: #fff3bf;
font-weight: bold;
border-radius: 3px;
padding: 0 2px;
}
.hidden-section {
display: none !important;
}
`;
document.head.appendChild(style);

// Обработчики событий
const searchField = document.getElementById('rockSearchField');
const searchButton = document.getElementById('rockSearchButton');
const resetButton = document.getElementById('rockResetButton');

if (searchButton) {
searchButton.addEventListener('click', searchRocks);
}

if (resetButton) {
resetButton.addEventListener('click', resetSearch);
}

// Только поиск по кнопке (убираем поиск при вводе)
if (searchField) {
searchField.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
searchRocks();
}
});
}
}

// Запускаем после загрузки страницы
window.addEventListener('DOMContentLoaded', initializeRockSearch);
</script>
ГостьДата: Вторник, 2025-06-24, 10:21 | Сообщение # 107
Гость
Группа: Гости





<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" aria-label="Очистить поиск">×</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;
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();

// Обработчики событий
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.resetTreeState) window.resetTreeState();
});

// Переключение режимов
modeRadios.forEach(radio => {
radio.addEventListener('change', initSearchMode);
});
});
</script>

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

.tree-search-input {
flex: 1;
height: 36px; /* Фиксированная высота */
padding: 0 30px 0 10px; /* Убрали вертикальные отступы */
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box; /* Учитываем padding в высоте */
}

.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.hidden {
opacity: 0;
width: 0;
margin-left: 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; /* Позиция с кнопкой */
}
</style>
AleXStamДата: Вторник, 2025-06-24, 10:24 | Сообщение # 108
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<!-- Вставьте этот код ПЕРЕД всеми секциями с породами -->
<div class="tree-search-panel" style="margin: 20px 0;">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</button>
</div>
<div id="searchStatus" style="margin-top: 8px; font-size: 14px; color: #666;">Готов к поиску</div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
// Элементы управления
const searchField = document.getElementById('rockSearchField');
const searchBtn = document.getElementById('rockSearchButton');
const resetBtn = document.getElementById('rockResetButton');
const searchStatus = document.getElementById('searchStatus');

// Стили для подсветки
const style = document.createElement('style');
style.textContent = `
.rock-search-match {
background-color: #fff3bf;
font-weight: bold;
border-radius: 3px;
padding: 0 2px;
}
.tab-highlight {
background-color: #e6f7ff;
border-left: 3px solid #1890ff;
}
`;
document.head.appendChild(style);

// Функция сброса поиска
function resetSearch() {
searchField.value = '';
searchStatus.textContent = 'Готов к поиску';

// Убираем подсветку
document.querySelectorAll('.rock-search-match, .tab-highlight').forEach(el => {
el.classList.remove('rock-search-match', 'tab-highlight');
});

// Сворачиваем все секции
document.querySelectorAll('details').forEach(section => {
section.style.display = '';
section.open = false;
});

// Сбрасываем вкладки
const tabs = document.querySelectorAll('.tab-content');
if (tabs) {
tabs.forEach(tab => tab.style.display = 'none');
if (tabs[0]) tabs[0].style.display = '';
}
}

// Функция поиска
function performSearch() {
const searchTerm = searchField.value.trim().toLowerCase();
let foundCount = 0;

// Сбрасываем предыдущие результаты
document.querySelectorAll('.rock-search-match, .tab-highlight').forEach(el => {
el.classList.remove('rock-search-match', 'tab-highlight');
});

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

// 1. Поиск в обычных секциях
document.querySelectorAll('details').forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr');

rows.forEach((row, index) => {
if (index === 0) return; // Пропускаем заголовки

const cells = row.querySelectorAll('td');
cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
sectionHasMatches = true;
}
});
});
});

// Управление секцией
if (sectionHasMatches) {
section.style.display = '';
section.open = true;
} else {
section.style.display = 'none';
}
});

// 2. Поиск во вкладках
const tabContents = document.querySelectorAll('.tab-content');
const tabHeaders = document.querySelectorAll('.tab-header'); // Предполагаемая структура вкладок

tabContents.forEach((tab, index) => {
const sections = tab.querySelectorAll('details');
let tabHasMatches = false;

sections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr');

rows.forEach((row, idx) => {
if (idx === 0) return;

const cells = row.querySelectorAll('td');
cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
sectionHasMatches = true;
tabHasMatches = true;
}
});
});
});

// Управление секцией во вкладке
if (sectionHasMatches) {
section.style.display = '';
section.open = true;
} else {
section.style.display = 'none';
}
});

// Подсветка заголовка вкладки
if (tabHasMatches && tabHeaders[index]) {
tabHeaders[index].classList.add('tab-highlight');
tab.style.display = ''; // Показываем вкладку с результатами
}
});

// Обновление статуса
searchStatus.textContent = foundCount > 0
? `Найдено совпадений: ${foundCount}`
: 'Ничего не найдено';
}

// Обработчики событий
searchBtn.addEventListener('click', performSearch);
searchField.addEventListener('keypress', function(e) {
if (e.key === 'Enter') performSearch();
});
resetBtn.addEventListener('click', resetSearch);
});
</script>

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

.tree-search-input {
flex: 1;
height: 36px;
padding: 0 30px 0 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box;
}

.tree-search-btn {
height: 36px;
margin-left: 8px;
padding: 0 12px;
background: #2188ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
flex-shrink: 0;
}

.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;
}
</style>
AleXStamДата: Вторник, 2025-06-24, 10:35 | Сообщение # 109
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<div class="tree-search-panel">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</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('rockSearchField');
const searchBtn = document.getElementById('rockSearchButton');
const clearBtn = document.getElementById('rockResetButton');
const modeRadios = document.querySelectorAll('input[name="search-mode"]');

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

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

// Убираем подсветку
document.querySelectorAll('.rock-search-match').forEach(el => {
el.classList.remove('rock-search-match');
});

// Сбрасываем подсветку вкладок
document.querySelectorAll('.tab-with-results').forEach(tab => {
tab.classList.remove('tab-with-results');
});

// Закрываем все секции
document.querySelectorAll('details').forEach(section => {
section.style.display = '';
section.open = false;
});

// Возвращаем вкладки в исходное состояние
const tabs = document.querySelectorAll('.tab-content');
if (tabs) {
tabs.forEach(tab => {
tab.style.display = 'none';
});
if (tabs[0]) tabs[0].style.display = '';
}
}

// Функция поиска
function performSearch() {
const searchTerm = searchInput.value.trim().toLowerCase();

// Сбрасываем предыдущие результаты
document.querySelectorAll('.rock-search-match, .tab-with-results').forEach(el => {
el.classList.remove('rock-search-match', 'tab-with-results');
});

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

let foundCount = 0;

// 1. Поиск в обычных секциях
document.querySelectorAll('details').forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr');

rows.forEach((row, index) => {
if (index === 0) return;

const cells = row.querySelectorAll('td');
cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
sectionHasMatches = true;
}
});
});
});

// Управление секцией
if (sectionHasMatches) {
section.style.display = '';
section.open = true;
} else {
section.style.display = 'none';
}
});

// 2. Поиск во вкладках и подсветка
document.querySelectorAll('.tab-content').forEach(tab => {
const tabSections = tab.querySelectorAll('details');
let tabHasMatches = false;

tabSections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr');

rows.forEach((row, index) => {
if (index === 0) return;

const cells = row.querySelectorAll('td');
cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
sectionHasMatches = true;
tabHasMatches = true;
}
});
});
});

// Управление секцией во вкладке
if (sectionHasMatches) {
section.style.display = '';
section.open = true;
} else {
section.style.display = 'none';
}
});

// Подсветка вкладки
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');
}
}
});
}

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

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

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

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

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

// Обработчики событий
searchBtn.addEventListener('click', performSearch);
searchInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') performSearch();
});
clearBtn.addEventListener('click', resetSearch);
modeRadios.forEach(radio => {
radio.addEventListener('change', initSearchMode);
});
});
</script>

<style>
.tree-search-panel {
margin: 20px 0;
}

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

.tree-search-input {
flex: 1;
height: 36px;
padding: 0 30px 0 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box;
}

.tree-search-btn {
height: 36px;
margin-left: 8px;
padding: 0 12px;
background: #2188ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
flex-shrink: 0;
transition: opacity 0.2s, width 0.2s, margin 0.2s;
}

.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: 16px;
color: #999;
transition: right 0.2s;
}

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

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

.search-modes label {
display: flex;
align-items: center;
gap: 5px;
cursor: pointer;
}
</style>
AleXStamДата: Вторник, 2025-06-24, 10:45 | Сообщение # 110
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<div class="tree-search-panel">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</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('rockSearchField');
const searchBtn = document.getElementById('rockSearchButton');
const clearBtn = document.getElementById('rockResetButton');
const modeRadios = document.querySelectorAll('input[name="search-mode"]');

let searchTimeout;
let currentSearchTerm = '';

// Стили для подсветки
const style = document.createElement('style');
style.textContent = `
.rock-search-match {
background-color: #fff3bf;
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 resetSearch() {
searchInput.value = '';
currentSearchTerm = '';

// Убираем подсветку
document.querySelectorAll('.rock-search-match, .tab-with-results, .hidden-row').forEach(el => {
el.classList.remove('rock-search-match', 'tab-with-results', 'hidden-row');
});

// Показываем все строки
document.querySelectorAll('tr').forEach(row => {
row.style.display = '';
});

// Закрываем все секции
document.querySelectorAll('details').forEach(section => {
section.style.display = '';
section.open = false;
});

// Возвращаем вкладки в исходное состояние
const tabs = document.querySelectorAll('.tab-content');
if (tabs) {
tabs.forEach(tab => {
tab.style.display = 'none';
});
if (tabs[0]) tabs[0].style.display = '';
}
}

// Основная функция поиска
function performSearch() {
const searchTerm = searchInput.value.trim().toLowerCase();
currentSearchTerm = searchTerm;

// Сбрасываем предыдущие результаты
document.querySelectorAll('.rock-search-match, .tab-with-results').forEach(el => {
el.classList.remove('rock-search-match', 'tab-with-results');
});

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

let foundCount = 0;

// 1. Поиск в обычных секциях
document.querySelectorAll('details').forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr');

rows.forEach((row, index) => {
if (index === 0) return; // Пропускаем заголовки таблиц

const cells = row.querySelectorAll('td');
let rowHasMatches = false;

cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
rowHasMatches = true;
sectionHasMatches = true;
}
});

// Скрываем строки без совпадений
if (!rowHasMatches) {
row.classList.add('hidden-row');
}
});
});

// Управление секцией
if (sectionHasMatches) {
section.style.display = '';
section.open = true;
} else {
section.style.display = 'none';
}
});

// 2. Поиск во вкладках
document.querySelectorAll('.tab-content').forEach(tab => {
const tabSections = tab.querySelectorAll('details');
let tabHasMatches = false;

tabSections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr');

rows.forEach((row, index) => {
if (index === 0) return;

const cells = row.querySelectorAll('td');
let rowHasMatches = false;

cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
rowHasMatches = true;
sectionHasMatches = true;
tabHasMatches = true;
}
});

// Скрываем строки без совпадений
if (!rowHasMatches) {
row.classList.add('hidden-row');
}
});
});

// Управление секцией во вкладке
if (sectionHasMatches) {
section.style.display = '';
section.open = true;
} else {
section.style.display = 'none';
}
});

// Подсветка вкладки
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 handleInstantSearch() {
clearTimeout(searchTimeout);
performSearch();
}

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

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

if (selectedMode === '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 handleDelayedSearch() {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
if (searchInput.value.trim().toLowerCase() !== currentSearchTerm) {
resetSearch();
}
}, 300);
}

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

// Обработчики событий
searchBtn.addEventListener('click', performSearch);
searchInput.addEventListener('keypress', function(e) {
if (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;
background: #fff;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.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: 100%;
margin-left: 8px;
padding: 0 16px;
background: #2188ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
flex-shrink: 0;
transition: all 0.2s;
font-size: 14px;
}

.tree-search-btn:hover {
background: #0c7ae3;
}

.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>
AleXStamДата: Вторник, 2025-06-24, 10:50 | Сообщение # 111
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<div class="tree-search-panel">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</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('rockSearchField');
const searchBtn = document.getElementById('rockSearchButton');
const clearBtn = document.getElementById('rockResetButton');
const modeRadios = document.querySelectorAll('input[name="search-mode"]');

let currentSearchTerm = '';
let currentMode = 'button'; // По умолчанию "поиск по кнопке"

// Стили для подсветки
const style = document.createElement('style');
style.textContent = `
.rock-search-match {
background-color: #fff3bf;
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 resetSearch() {
searchInput.value = '';
currentSearchTerm = '';

// Убираем подсветку
document.querySelectorAll('.rock-search-match, .tab-with-results, .hidden-row').forEach(el => {
el.classList.remove('rock-search-match', 'tab-with-results', 'hidden-row');
});

// Показываем все строки
document.querySelectorAll('tr').forEach(row => {
row.style.display = '';
});

// Закрываем все секции
document.querySelectorAll('details').forEach(section => {
section.style.display = '';
section.open = false;
});

// Возвращаем вкладки в исходное состояние
const tabs = document.querySelectorAll('.tab-content');
if (tabs) {
tabs.forEach(tab => {
tab.style.display = 'none';
});
if (tabs[0]) tabs[0].style.display = '';
}
}

// Основная функция поиска
function performSearch() {
const searchTerm = searchInput.value.trim().toLowerCase();
currentSearchTerm = searchTerm;

// Сбрасываем предыдущие результаты
document.querySelectorAll('.rock-search-match, .tab-with-results').forEach(el => {
el.classList.remove('rock-search-match', 'tab-with-results');
});

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

let foundCount = 0;

// 1. Поиск в обычных секциях
document.querySelectorAll('details').forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr');

rows.forEach((row, index) => {
if (index === 0) return; // Пропускаем заголовки таблиц

const cells = row.querySelectorAll('td');
let rowHasMatches = false;

cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
rowHasMatches = true;
sectionHasMatches = true;
}
});

// Скрываем строки без совпадений
if (!rowHasMatches) {
row.classList.add('hidden-row');
}
});
});

// Управление секцией
if (sectionHasMatches) {
section.style.display = '';
section.open = true;
} else {
section.style.display = 'none';
}
});

// 2. Поиск во вкладках
document.querySelectorAll('.tab-content').forEach(tab => {
const tabSections = tab.querySelectorAll('details');
let tabHasMatches = false;

tabSections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr');

rows.forEach((row, index) => {
if (index === 0) return;

const cells = row.querySelectorAll('td');
let rowHasMatches = false;

cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
rowHasMatches = true;
sectionHasMatches = true;
tabHasMatches = true;
}
});

// Скрываем строки без совпадений
if (!rowHasMatches) {
row.classList.add('hidden-row');
}
});
});

// Управление секцией во вкладке
if (sectionHasMatches) {
section.style.display = '';
section.open = true;
} else {
section.style.display = 'none';
}
});

// Подсветка вкладки
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);

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

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

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

// Обработчики событий
searchBtn.addEventListener('click', performSearch);
searchInput.addEventListener('keypress', function(e) {
if (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;
background: #fff;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.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: 100%;
margin-left: 8px;
padding: 0 16px;
background: #2188ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
flex-shrink: 0;
transition: all 0.2s;
font-size: 14px;
}

.tree-search-btn:hover {
background: #0c7ae3;
}

.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>
AleXStamДата: Вторник, 2025-06-24, 11:09 | Сообщение # 112
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<div class="tree-search-panel">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</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('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;

// Стили для подсветки
const style = document.createElement('style');
style.textContent = `
.rock-search-match {
background-color: #fff3bf;
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;
}
.visible-row {
display: table-row !important;
}
`;
document.head.appendChild(style);

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

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

document.querySelectorAll('.hidden-row').forEach(row => {
row.classList.remove('hidden-row');
row.classList.add('visible-row');
});

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

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

// Основная функция поиска
function performSearch() {
const searchTerm = searchInput.value.trim().toLowerCase();
currentSearchTerm = searchTerm;

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

let foundCount = 0;

// Поиск в обычных секциях
document.querySelectorAll('details').forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr:not(:first-child)');

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

cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
rowHasMatches = true;
sectionHasMatches = true;
}
});

row.style.display = rowHasMatches ? '' : 'none';
});
});

section.style.display = sectionHasMatches ? '' : 'none';
if (sectionHasMatches) section.open = true;
});

// Поиск во вкладках
document.querySelectorAll('.tab-content').forEach(tab => {
const tabSections = tab.querySelectorAll('details');
let tabHasMatches = false;

tabSections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr:not(:first-child)');

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

cells.forEach(cell => {
const text = cell.textContent.toLowerCase();
if (text.includes(searchTerm)) {
cell.classList.add('rock-search-match');
foundCount++;
rowHasMatches = true;
sectionHasMatches = true;
tabHasMatches = true;
}
});

row.style.display = rowHasMatches ? '' : 'none';
});
});

section.style.display = sectionHasMatches ? '' : 'none';
if (sectionHasMatches) section.open = true;
});

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() {
performSearch();
}

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

// Инициализация
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;
background: #fff;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.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: 100%;
margin-left: 8px;
padding: 0 16px;
background: #2188ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
flex-shrink: 0;
transition: all 0.2s;
font-size: 14px;
}

.tree-search-btn:hover {
background: #0c7ae3;
}

.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>
AleXStamДата: Вторник, 2025-06-24, 11:17 | Сообщение # 113
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<div class="tree-search-panel">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</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('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;

// Стили для подсветки
const style = document.createElement('style');
style.textContent = `
.rock-search-match {
background-color: #fff3bf;
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 resetSearch() {
searchInput.value = '';
currentSearchTerm = '';

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

document.querySelectorAll('.hidden-row').forEach(row => {
row.classList.remove('hidden-row');
});

document.querySelectorAll('details').forEach(section => {
section.style.display = '';
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;

const regex = new RegExp(`(${searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
return text.replace(regex, '<span class="rock-search-match">$1</span>');
}

// Основная функция поиска
function performSearch() {
const searchTerm = searchInput.value.trim().toLowerCase();
currentSearchTerm = searchTerm;

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

let foundCount = 0;

// Поиск в обычных секциях
document.querySelectorAll('details').forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr:not(:first-child)');

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

cells.forEach(cell => {
const originalText = cell.textContent;
const lowerText = originalText.toLowerCase();

if (lowerText.includes(searchTerm)) {
// Сохраняем HTML только если есть совпадения
cell.innerHTML = highlightMatches(originalText, searchTerm);
foundCount++;
rowHasMatches = true;
sectionHasMatches = true;
}
});

row.style.display = rowHasMatches ? '' : 'none';
});
});

section.style.display = sectionHasMatches ? '' : 'none';
if (sectionHasMatches) section.open = true;
});

// Поиск во вкладках
document.querySelectorAll('.tab-content').forEach(tab => {
const tabSections = tab.querySelectorAll('details');
let tabHasMatches = false;

tabSections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr:not(:first-child)');

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

cells.forEach(cell => {
const originalText = cell.textContent;
const lowerText = originalText.toLowerCase();

if (lowerText.includes(searchTerm)) {
cell.innerHTML = highlightMatches(originalText, searchTerm);
foundCount++;
rowHasMatches = true;
sectionHasMatches = true;
tabHasMatches = true;
}
});

row.style.display = rowHasMatches ? '' : 'none';
});
});

section.style.display = sectionHasMatches ? '' : 'none';
if (sectionHasMatches) section.open = true;
});

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);
}

// Инициализация
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>
AleXStamДата: Вторник, 2025-06-24, 11:23 | Сообщение # 114
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<div class="tree-search-panel">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</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('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: #fff3bf;
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').forEach(td => {
originalContents.set(td, td.innerHTML);
});
}

// Восстанавливаем оригинальное содержимое
function restoreOriginalContents() {
originalContents.forEach((content, td) => {
td.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').forEach(row => {
row.style.display = '';
});

document.querySelectorAll('details').forEach(section => {
section.style.display = '';
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;
const escapedTerm = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const regex = new RegExp(`(${escapedTerm})`, 'gi');
return text.replace(regex, '<span class="rock-search-match">$1</span>');
}

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

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

restoreOriginalContents();
let foundCount = 0;

// Поиск в обычных секциях
document.querySelectorAll('details').forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr:not(:first-child)');

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

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

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

row.style.display = rowHasMatches ? '' : 'none';
});
});

section.style.display = sectionHasMatches ? '' : 'none';
if (sectionHasMatches) section.open = true;
});

// Поиск во вкладках
document.querySelectorAll('.tab-content').forEach(tab => {
const tabSections = tab.querySelectorAll('details');
let tabHasMatches = false;

tabSections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr:not(:first-child)');

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

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

if (lowerText.includes(searchTerm)) {
cell.innerHTML = highlightMatches(originalHtml, searchTerm);
foundCount++;
rowHasMatches = true;
sectionHasMatches = true;
tabHasMatches = true;
}
});

row.style.display = rowHasMatches ? '' : 'none';
});
});

section.style.display = sectionHasMatches ? '' : 'none';
if (sectionHasMatches) section.open = true;
});

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>
AleXStamДата: Вторник, 2025-06-24, 11:29 | Сообщение # 115
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<div class="tree-search-panel">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</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('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: #fff3bf;
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').forEach(td => {
originalContents.set(td, td.innerHTML);
});
}

// Восстанавливаем оригинальное содержимое
function restoreOriginalContents() {
originalContents.forEach((content, td) => {
td.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('details').forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr:not(:first-child)');

rows.forEach(row => {
const cells = row.querySelectorAll('td');
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;
sectionHasMatches = true;
}
});

row.style.display = rowHasMatches ? '' : 'none';
});
});

section.style.display = sectionHasMatches ? '' : 'none';
if (sectionHasMatches) section.open = true;
});

// Поиск во вкладках
document.querySelectorAll('.tab-content').forEach(tab => {
const tabSections = tab.querySelectorAll('details');
let tabHasMatches = false;

tabSections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr:not(:first-child)');

rows.forEach(row => {
const cells = row.querySelectorAll('td');
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;
sectionHasMatches = true;
tabHasMatches = true;
}
});

row.style.display = rowHasMatches ? '' : 'none';
});
});

section.style.display = sectionHasMatches ? '' : 'none';
if (sectionHasMatches) section.open = true;
});

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>
AleXStamДата: Вторник, 2025-06-24, 11:36 | Сообщение # 116
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<div class="tree-search-panel">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</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('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: #fff3bf;
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>
AleXStamДата: Вторник, 2025-06-24, 11:43 | Сообщение # 117
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<div class="tree-search-panel">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</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('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();
let originalTabStates = new Map();

// Стили для подсветки
const style = document.createElement('style');
style.textContent = `
.rock-search-match {
background-color: #fff3bf;
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;
}
.hidden-tab {
display: none !important;
}
.hidden-tab-header {
display: none !important;
}
`;
document.head.appendChild(style);

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

// Сохраняем состояние вкладок
document.querySelectorAll('.tab-content').forEach(tab => {
originalTabStates.set(tab, {
display: tab.style.display,
headers: Array.from(document.querySelectorAll(`[data-tab="${tab.id}"]`))
});
});
}

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

// Восстанавливаем вкладки
originalTabStates.forEach((state, tab) => {
tab.style.display = state.display;
state.headers.forEach(header => {
header.classList.remove('hidden-tab-header', 'tab-with-results');
});
});

// Показываем все строки и секции
document.querySelectorAll('.hidden-row, details').forEach(el => {
el.style.display = '';
});
}

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

// Улучшенная функция выделения совпадений
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;
}

restoreOriginalStates();
let foundCount = 0;

// 1. Сначала обрабатываем все таблицы на странице
const allTables = document.querySelectorAll('table');
const tablesWithMatches = new Set();

allTables.forEach(table => {
const rows = table.querySelectorAll('tr');
let tableHasMatches = false;

rows.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';
}
});

if (tableHasMatches) {
tablesWithMatches.add(table);
// Показываем родительскую секцию
const parentSection = table.closest('details');
if (parentSection) {
parentSection.style.display = '';
parentSection.open = true;
}
}
});

// 2. Обрабатываем вкладки
const tabsContainer = document.querySelector('.tabs');
if (tabsContainer) {
const allTabs = document.querySelectorAll('.tab-content');
const allTabHeaders = document.querySelectorAll('[data-tab]');

// Сначала скрываем все вкладки и их заголовки
allTabs.forEach(tab => {
tab.style.display = 'none';
});
allTabHeaders.forEach(header => {
header.classList.add('hidden-tab-header');
});

// Показываем только вкладки с результатами
tablesWithMatches.forEach(table => {
const tabContent = table.closest('.tab-content');
if (tabContent) {
tabContent.style.display = '';
const tabId = tabContent.id;
const tabHeaders = document.querySelectorAll(`[data-tab="${tabId}"]`);

tabHeaders.forEach(header => {
header.classList.remove('hidden-tab-header');
header.classList.add('tab-with-results');
});
}
});

// Если нет результатов ни в одной вкладке - показываем первую
if (tablesWithMatches.size === 0 && allTabs.length > 0) {
allTabs[0].style.display = '';
const firstTabHeaders = document.querySelectorAll(`[data-tab="${allTabs[0].id}"]`);
firstTabHeaders.forEach(header => {
header.classList.remove('hidden-tab-header');
});
}
}
}

// Инициализация режима поиска
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);
}

// Инициализация
saveOriginalStates();
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>
AleXStamДата: Вторник, 2025-06-24, 11:47 | Сообщение # 118
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
<div class="tree-search-panel">
<div class="tree-search-box">
<input type="text" id="rockSearchField" placeholder="Поиск по литологии..." class="tree-search-input">
<button id="rockSearchButton" class="tree-search-btn">Найти</button>
<button id="rockResetButton" class="tree-search-clear" aria-label="Очистить поиск">×</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('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: #fff3bf;
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;
}
.hidden-tab {
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, .hidden-tab').forEach(el => {
el.classList.remove('tab-with-results', 'hidden-row', 'hidden-tab');
});

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

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

// Восстанавливаем все вкладки
document.querySelectorAll('.tab-content').forEach(tab => {
tab.style.display = '';
});

// Восстанавливаем все заголовки вкладок
document.querySelectorAll('[data-tab]').forEach(header => {
header.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('.tab-content').forEach(tab => {
tab.classList.add('hidden-tab');
});

// Сбрасываем подсветку заголовков вкладок
document.querySelectorAll('[data-tab]').forEach(header => {
header.classList.remove('tab-with-results');
});

// Поиск в обычных секциях (не в вкладках)
document.querySelectorAll('details:not(.tab-content details)').forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr:not(:first-child)');

rows.forEach(row => {
const cells = row.querySelectorAll('td');
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;
sectionHasMatches = true;
}
});

row.style.display = rowHasMatches ? '' : 'none';
});
});

section.style.display = sectionHasMatches ? '' : 'none';
if (sectionHasMatches) section.open = true;
});

// Поиск во вкладках
document.querySelectorAll('.tab-content').forEach(tab => {
const tabSections = tab.querySelectorAll('details');
let tabHasMatches = false;

tabSections.forEach(section => {
const tables = section.querySelectorAll('table');
let sectionHasMatches = false;

tables.forEach(table => {
const rows = table.querySelectorAll('tr:not(:first-child)');

rows.forEach(row => {
const cells = row.querySelectorAll('td');
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;
sectionHasMatches = true;
tabHasMatches = true;
}
});

row.style.display = rowHasMatches ? '' : 'none';
});
});

section.style.display = sectionHasMatches ? '' : 'none';
if (sectionHasMatches) section.open = true;
});

// Управление отображением вкладки
if (tabHasMatches) {
tab.classList.remove('hidden-tab');
const tabId = tab.id;
if (tabId) {
const tabHeader = document.querySelector(`[data-tab="${tabId}"]`);
if (tabHeader) {
tabHeader.classList.add('tab-with-results');
tabHeader.style.display = ''; // Показываем заголовок
}
}
}
});

// Если ничего не найдено - показываем первую вкладку
if (foundCount === 0) {
const firstTab = document.querySelector('.tab-content');
if (firstTab) {
firstTab.classList.remove('hidden-tab');
const firstTabHeader = document.querySelector(`[data-tab="${firstTab.id}"]`);
if (firstTabHeader) {
firstTabHeader.style.display = '';
}
}
}
}

// Инициализация режима поиска
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>
ГостьДата: Вторник, 2025-06-24, 12:53 | Сообщение # 119
Гость
Группа: Гости





document.addEventListener('DOMContentLoaded', function() {
const colorBlocks = document.querySelectorAll('.custom-rectangle');

colorBlocks.forEach(block => {
// Инициализация блока
const hexColor = block.textContent.trim();
block.dataset.hex = hexColor;
block.dataset.rgb = hexToRgbString(hexColor);

// Установка базовых стилей
block.style.fontSize = '15px';
block.style.width = '80px';
block.style.height = '40px';
block.style.display = 'flex';
block.style.alignItems = 'center';
block.style.justifyContent = 'center';
block.style.flexDirection = 'column';
block.style.border = '0.5px solid';
block.style.borderRadius = '8px';
block.style.textAlign = 'center';
block.style.boxSizing = 'border-box';

// Установка контрастного цвета текста и границы
updateTextColor(block, hexColor);

block.addEventListener('click', function(e) {
e.stopPropagation();
document.querySelectorAll('.copy-tooltip').forEach(t => t.remove());

if (block.classList.contains('show-rgb')) {
// Переключаем на HEX и копируем RGB
block.innerHTML = block.dataset.hex;
block.classList.remove('show-rgb');
copyToClipboard(block, block.dataset.rgb, 'RGB');
} else {
// Переключаем на RGB и копируем HEX
block.innerHTML = `
<span class="rgb-title">RGB</span>
<span class="rgb-values">${block.dataset.rgb.replace('rgb(', '').replace(')', '')}</span>
`;
block.classList.add('show-rgb');
copyToClipboard(block, block.dataset.hex, 'HEX');
adjustFontSize(block);
}

// Обновляем цвет текста после изменения содержимого
updateTextColor(block, block.dataset.hex);
});
});

// Функция обновления цвета текста и границы
function updateTextColor(element, hexColor) {
const rgb = hexToRgb(hexColor);
if (!rgb) return;

// Вычисляем яркость фона по формуле W3C
const brightness = (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;

// Устанавливаем цвет текста и границы
element.style.color = brightness > 128 ? '#000000' : '#FFFFFF';
element.style.borderColor = brightness > 128 ? 'rgba(0,0,0,0.3)' : 'rgba(255,255,255,0.3)';
}

// Преобразование HEX в RGB объект
function hexToRgb(hex) {
hex = hex.replace('#', '');

// Расширяем сокращенную запись HEX (#abc → #aabbcc)
if (hex.length === 3) {
hex = hex.split('').map(c => c + c).join('');
}

if (hex.length !== 6) return null;

return {
r: parseInt(hex.substring(0, 2), 16),
g: parseInt(hex.substring(2, 4), 16),
b: parseInt(hex.substring(4, 6), 16)
};
}

// Преобразование HEX в RGB строку
function hexToRgbString(hex) {
const rgb = hexToRgb(hex);
return rgb ? `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})` : 'rgb(0, 0, 0)';
}

// Подгонка размера шрифта для RGB значений
function adjustFontSize(element) {
const rgbValues = element.querySelector('.rgb-values');
if (!rgbValues) return;

let fontSize = 11; // Начальный размер
rgbValues.style.fontSize = fontSize + 'px';

// Уменьшаем шрифт, пока текст не поместится
while (rgbValues.scrollWidth > element.offsetWidth - 10 && fontSize > 8) {
fontSize -= 0.5;
rgbValues.style.fontSize = fontSize + 'px';
}
}

// Копирование в буфер обмена
function copyToClipboard(element, text, format) {
navigator.clipboard.writeText(text).then(() => {
showTooltip(element, format);
}).catch(err => {
console.error('Ошибка копирования:', err);
// Fallback для старых браузеров
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
showTooltip(element, format);
});
}

// Показ подсказки о копировании
function showTooltip(element, format) {
const tooltip = document.createElement('div');
tooltip.className = 'copy-tooltip';
tooltip.textContent = `${format} скопирован!`;
document.body.appendChild(tooltip);

const rect = element.getBoundingClientRect();
tooltip.style.left = `${rect.left + rect.width/2 - tooltip.offsetWidth/2}px`;
tooltip.style.top = `${rect.top - 35}px`;

setTimeout(() => {
tooltip.remove();
}, 2000);
}
});
AleXStamДата: Вторник, 2025-06-24, 13:49 | Сообщение # 120
AleXStam
Генералиссимус
Группа: Администраторы
Сообщений: 189
Награды: 1
Репутация: 10003
Статус: Оффлайн
Function RGBToHex(R As Integer, G As Integer, B As Integer) As String
' Преобразует отдельные значения R, G, B в HEX (например, #FFA500)
RGBToHex = "#" & Right("0" & Hex®, 2) & _
Right("0" & Hex(G), 2) & _
Right("0" & Hex(B), 2)
End Function
  • Страница 8 из 9
  • «
  • 1
  • 2
  • 6
  • 7
  • 8
  • 9
  • »
Поиск:
Новый ответ
Имя:
Текст сообщения:


Яндекс.Метрика