|
Поговорим о...
|
|
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Полевой дневник №001 | Архив геологических материалов</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <style> :root { --primary: #4361ee; --secondary: #3f37c9; --accent: #4895ef; --light: #f8f9fa; --dark: #212529; --gray: #6c757d; --success: #4cc9f0; --warning: #f72585; --danger: #ef233c; --card-shadow: 0 4px 6px rgba(0,0,0,0.05), 0 1px 3px rgba(0,0,0,0.1); --transition: all 0.3s ease; } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; line-height: 1.6; color: var(--dark); background-color: #f5f7ff; padding: 20px; } .container { max-width: 1200px; margin: 0 auto; } /* Header */ .material-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; padding-bottom: 15px; border-bottom: 1px solid rgba(0,0,0,0.1); } .material-title { font-size: 28px; font-weight: 700; color: var(--secondary); } .material-id { display: inline-block; background-color: var(--primary); color: white; padding: 5px 15px; border-radius: 20px; font-size: 16px; margin-left: 10px; vertical-align: middle; } /* Breadcrumbs */ .breadcrumbs { display: flex; align-items: center; margin-bottom: 20px; font-size: 14px; color: var(--gray); } .breadcrumbs a { color: var(--primary); text-decoration: none; transition: var(--transition); } .breadcrumbs a:hover { text-decoration: underline; } .breadcrumbs i { margin: 0 8px; font-size: 12px; color: var(--gray); } /* Main Content */ .content-section { background: white; border-radius: 10px; padding: 25px; margin-bottom: 30px; box-shadow: var(--card-shadow); } .section-title { font-size: 20px; font-weight: 600; margin-bottom: 20px; color: var(--secondary); display: flex; align-items: center; } .section-title i { margin-right: 10px; color: var(--accent); } /* Material Info */ .info-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; margin-bottom: 25px; } .info-card { background: white; border-radius: 8px; padding: 20px; box-shadow: var(--card-shadow); border: 1px solid rgba(0,0,0,0.05); } .info-label { font-size: 13px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--gray); margin-bottom: 8px; } .info-value { font-size: 16px; font-weight: 500; line-height: 1.5; } .info-value a { color: var(--primary); text-decoration: none; transition: var(--transition); } .info-value a:hover { text-decoration: underline; } .no-data { color: #adb5bd; font-style: italic; } /* Status */ .status-badge { display: inline-block; padding: 5px 12px; border-radius: 15px; font-size: 14px; font-weight: 600; margin-left: 10px; } .status-available { background-color: rgba(76, 201, 240, 0.1); color: var(--success); } .status-issued { background-color: rgba(247, 37, 133, 0.1); color: var(--warning); } /* Material Details */ .details-section { margin-top: 30px; } .details-content { padding: 20px; background-color: #f8f9ff; border-radius: 8px; line-height: 1.6; } .details-content p { margin-bottom: 15px; } /* Photos */ .photos-section { margin-top: 30px; } .photos-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px; margin-top: 15px; } .photo-item { border-radius: 8px; overflow: hidden; box-shadow: var(--card-shadow); position: relative; cursor: pointer; aspect-ratio: 1/1; } .photo-item img { width: 100%; height: 100%; object-fit: cover; transition: var(--transition); } .photo-item:hover img { transform: scale(1.05); } /* Actions */ .actions-section { display: flex; justify-content: flex-end; gap: 15px; margin-top: 30px; } .btn { padding: 10px 20px; border-radius: 5px; font-weight: 500; cursor: pointer; transition: var(--transition); display: inline-flex; align-items: center; gap: 8px; } .btn-primary { background-color: var(--primary); color: white; border: none; } .btn-primary:hover { background-color: var(--secondary); } .btn-outline { background-color: transparent; border: 1px solid var(--primary); color: var(--primary); } .btn-outline:hover { background-color: rgba(67, 97, 238, 0.1); } .btn-danger { background-color: var(--danger); color: white; border: none; } .btn-danger:hover { background-color: #d90429; } /* Responsive */ @media (max-width: 768px) { .info-grid { grid-template-columns: 1fr; } .photos-grid { grid-template-columns: repeat(3, 1fr); } } @media (max-width: 480px) { .material-header { flex-direction: column; align-items: flex-start; } .material-title { margin-bottom: 10px; } .photos-grid { grid-template-columns: repeat(2, 1fr); } .actions-section { flex-direction: column; } .btn { width: 100%; justify-content: center; } } </style> </head> <body> <div class="container"> <!-- Breadcrumbs --> <div class="breadcrumbs"> <a href="index.html">Главная</a> <i class="fas fa-chevron-right"></i> <a href="boxes.html">Коробки</a> <i class="fas fa-chevron-right"></i> <a href="box.html?id=001">Коробка №001</a> <i class="fas fa-chevron-right"></i> <span>Полевой дневник</span> </div> <!-- Header --> <div class="material-header"> <h1 class="material-title">Полевой дневник <span class="material-id">№001</span></h1> <span class="status-badge status-available">В наличии</span> </div> <!-- Main Content --> <div class="content-section"> <h2 class="section-title"><i class="fas fa-info-circle"></i> Основная информация</h2> <div class="info-grid"> <div class="info-card"> <div class="info-label">Тип материала</div> <div class="info-value">Полевой дневник</div> </div> <div class="info-card"> <div class="info-label">Носитель</div> <div class="info-value">Бумажный</div> </div> <div class="info-card"> <div class="info-label">Инвентарный номер</div> <div class="info-value">0001</div> </div> <div class="info-card"> <div class="info-label">Старый инв. номер</div> <div class="info-value">1</div> </div> <div class="info-card"> <div class="info-label">Номер описи</div> <div class="info-value">001 0001</div> </div> <div class="info-card"> <div class="info-label">Коробка</div> <div class="info-value"><a href="box.html?id=001">Коробка №001</a></div> </div> <div class="info-card"> <div class="info-label">Объект</div> <div class="info-value">Аккор</div> </div> <div class="info-card"> <div class="info-label">Участок</div> <div class="info-value">Северный</div> </div> <div class="info-card"> <div class="info-label">Партия</div> <div class="info-value">233</div> </div> <div class="info-card"> <div class="info-label">Год</div> <div class="info-value">1999</div> </div> <div class="info-card"> <div class="info-label">Автор</div> <div class="info-value no-data">не указан</div> </div> <div class="info-card"> <div class="info-label">Фондовый номер</div> <div class="info-value no-data">не указан</div> </div> </div> <div class="details-section"> <h2 class="section-title"><i class="fas fa-align-left"></i> Описание</h2> <div class="details-content"> <p>Полевой дневник геологических исследований месторождения "Аккор" за 1999 год. Содержит подробные записи о проведенных работах, описания проб, замеры и наблюдения.</p> <p>Дневник велся ежедневно в период с 15 мая по 30 сентября 1999 года. Включает 120 страниц рукописного текста, схемы и зарисовки геологических разрезов.</p> <p>Состояние: хорошее, все страницы целы, текст читаем. Имеются незначительные следы загрязнения на обложке.</p> </div> </div> <div class="photos-section"> <h2 class="section-title"><i class="fas fa-camera"></i> Фотографии</h2> <div class="photos-grid"> <div class="photo-item"> <img src="https://via.placeholder.com/400x400?text=Обложка" alt="Обложка дневника"> </div> <div class="photo-item"> <img src="https://via.placeholder.com/400x400?text=Страница+1" alt="Страница 1"> </div> <div class="photo-item"> <img src="https://via.placeholder.com/400x400?text=Страница+2" alt="Страница 2"> </div> <div class="photo-item"> <img src="https://via.placeholder.com/400x400?text=Схема" alt="Геологическая схема"> </div> </div> </div> <div class="actions-section"> <button class="btn btn-outline"> <i class="fas fa-edit"></i> Редактировать </button> <button class="btn btn-primary"> <i class="fas fa-exchange-alt"></i> Выдать/принять </button> <button class="btn btn-danger"> <i class="fas fa-trash-alt"></i> Удалить </button> </div> </div> </div> </body> </html>Добавлено (2025-08-07, 11:36) --------------------------------------------- <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Полевой дневник №001 | Архив геологических материалов</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <style> :root { --primary: #4361ee; --secondary: #3f37c9; --accent: #4895ef; --light: #f8f9fa; --dark: #212529; --gray: #6c757d; --success: #4cc9f0; --warning: #f72585; --card-shadow: 0 4px 6px rgba(0,0,0,0.05), 0 1px 3px rgba(0,0,0,0.1); --transition: all 0.3s ease; } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; line-height: 1.6; color: var(--dark); background-color: #f5f7ff; padding: 20px; } .container { max-width: 1200px; margin: 0 auto; } /* Header */ .material-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; padding-bottom: 15px; border-bottom: 1px solid rgba(0,0,0,0.1); } .material-title { font-size: 28px; font-weight: 700; color: var(--secondary); } .material-id { display: inline-block; background-color: var(--primary); color: white; padding: 5px 15px; border-radius: 20px; font-size: 16px; margin-left: 10px; vertical-align: middle; } /* Breadcrumbs */ .breadcrumbs { display: flex; align-items: center; margin-bottom: 20px; font-size: 14px; color: var(--gray); } .breadcrumbs a { color: var(--primary); text-decoration: none; transition: var(--transition); } .breadcrumbs a:hover { text-decoration: underline; } .breadcrumbs i { margin: 0 8px; font-size: 12px; color: var(--gray); } /* Main Content */ .content-section { background: white; border-radius: 10px; padding: 25px; margin-bottom: 30px; box-shadow: var(--card-shadow); } .section-title { font-size: 20px; font-weight: 600; margin-bottom: 20px; color: var(--secondary); display: flex; align-items: center; } .section-title i { margin-right: 10px; color: var(--accent); } /* Material Info */ .meta-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px; } .meta-item { margin-bottom: 5px; } .meta-label { font-size: 13px; color: var(--gray); margin-bottom: 3px; } .meta-value { font-size: 15px; font-weight: 500; } .meta-value a { color: var(--primary); text-decoration: none; cursor: pointer; transition: var(--transition); border-bottom: 1px dashed var(--primary); } .meta-value a:hover { color: var(--secondary); border-bottom-color: var(--secondary); } .no-data { color: #adb5bd; font-style: italic; font-size: 14px; } /* Status */ .status-badge { display: inline-block; padding: 5px 12px; border-radius: 15px; font-size: 14px; font-weight: 600; } .status-available { background-color: rgba(76, 201, 240, 0.1); color: var(--success); } .status-issued { background-color: rgba(247, 37, 133, 0.1); color: var(--warning); } /* Report Section */ .report-section { margin-top: 25px; padding-top: 15px; border-top: 1px solid rgba(0,0,0,0.1); } .report-title { font-size: 16px; font-weight: 600; margin-bottom: 10px; color: var(--secondary); } .report-content { font-size: 15px; line-height: 1.5; padding: 10px; background-color: #f8f9ff; border-radius: 6px; } /* Notes Section */ .notes-section { margin-top: 25px; } .notes-title { font-size: 16px; font-weight: 600; margin-bottom: 10px; color: var(--secondary); } .notes-content { font-size: 15px; line-height: 1.5; padding: 10px; background-color: #f8f9ff; border-radius: 6px; min-height: 50px; } /* Files Section */ .files-section { margin-top: 25px; } .files-title { font-size: 16px; font-weight: 600; margin-bottom: 10px; color: var(--secondary); } .files-list { list-style-type: none; } .files-item { padding: 10px; border-bottom: 1px solid rgba(0,0,0,0.05); display: flex; align-items: center; } .files-item:last-child { border-bottom: none; } .files-item i { margin-right: 10px; color: var(--accent); } .files-link { color: var(--dark); text-decoration: none; transition: var(--transition); } .files-link:hover { color: var(--primary); } /* Responsive */ @media (max-width: 768px) { .meta-grid { grid-template-columns: 1fr; } } </style> </head> <body> <div class="container"> <!-- Breadcrumbs --> <div class="breadcrumbs"> <a href="index.html">Главная</a> <i class="fas fa-chevron-right"></i> <a href="boxes.html">Коробки</a> <i class="fas fa-chevron-right"></i> <a href="box.html?id=001">Коробка №001</a> <i class="fas fa-chevron-right"></i> <span>Полевой дневник</span> </div> <!-- Header --> <div class="material-header"> <h1 class="material-title">Полевой дневник <span class="material-id">№001</span></h1> <span class="status-badge status-available">В наличии</span> </div> <!-- Main Content --> <div class="content-section"> <h2 class="section-title"><i class="fas fa-info-circle"></i> Основная информация</h2> <div class="meta-grid"> <div class="meta-item"> <div class="meta-label">Тип материала</div> <div class="meta-value">Полевой дневник</div> </div> <div class="meta-item"> <div class="meta-label">Носитель</div> <div class="meta-value">Бумажный</div> </div> <div class="meta-item"> <div class="meta-label">Инвентарный номер</div> <div class="meta-value">0001</div> </div> <div class="meta-item"> <div class="meta-label">Старый инв. номер</div> <div class="meta-value">1</div> </div> <div class="meta-item"> <div class="meta-label">Номер описи</div> <div class="meta-value">001 0001</div> </div> <div class="meta-item"> <div class="meta-label">Коробка</div> <div class="meta-value"><a href="box.html?id=001">Коробка №001</a></div> </div> <div class="meta-item"> <div class="meta-label">Объект</div> <div class="meta-value"><a>Аккор</a></div> </div> <div class="meta-item"> <div class="meta-label">Участок</div> <div class="meta-value"><a>Северный</a></div> </div> <div class="meta-item"> <div class="meta-label">Партия</div> <div class="meta-value"><a>233</a></div> </div> <div class="meta-item"> <div class="meta-label">Год</div> <div class="meta-value"><a>1999</a></div> </div> <div class="meta-item"> <div class="meta-label">Автор</div> <div class="meta-value no-data">не указан</div> </div> <div class="meta-item"> <div class="meta-label">Фондовый номер</div> <div class="meta-value no-data">не указан</div> </div> </div> <!-- Report Section --> <div class="report-section"> <div class="report-title">Отчет</div> <div class="report-content"> Полный геологический отчет по исследованию месторождения "Аккор" за 1999 год. Включает детальный анализ проб, карты местности, рекомендации по разработке. </div> </div> <!-- Notes Section --> <div class="notes-section"> <div class="notes-title">Примечание</div> <div class="notes-content"> <p>Полевой дневник геологических исследований месторождения "Аккор" за 1999 год. Содержит подробные записи о проведенных работах, описания проб, замеры и наблюдения.</p> <p>Дневник велся ежедневно в период с 15 мая по 30 сентября 1999 года. Включает 120 страниц рукописного текста, схемы и зарисовки геологических разрезов.</p> <p>Состояние: хорошее, все страницы целы, текст читаем. Имеются незначительные следы загрязнения на обложке.</p> </div> </div> <!-- Files Section --> <div class="files-section"> <div class="files-title">Файлы</div> <ul class="files-list"> <li class="files-item"> <i class="fas fa-file-pdf"></i> <a href="#" class="files-link">Скан_дневника_001.pdf (24.5 MB)</a> </li> <li class="files-item"> <i class="fas fa-file-image"></i> <a href="#" class="files-link">Обложка_001.jpg (3.2 MB)</a> </li> <li class="files-item"> <i class="fas fa-file-image"></i> <a href="#" class="files-link">Страницы_001-010.jpg (8.7 MB)</a> </li> </ul> </div> </div> </div> </body> </html>
|
<div class="card-buttons"> {{ $buttons := split .Inner "|" }} <!-- Разделяем кнопки по символу | --> {{ range $index, $button := $buttons }} {{ if modBool $index 2 }} <!-- Если индекс нечётный (1, 3...) --> <div class="button-row"> <a href="{{ index $buttons (sub $index 1) }}" class="btn">{{ index $buttons (sub $index 1) }}</a> <a href="{{ $button }}" class="btn">{{ $button }}</a> </div> {{ end }} {{ end }} </div>Добавлено (2025-08-14, 12:53) --------------------------------------------- .card-buttons { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 1rem; }
.button-row { display: flex; justify-content: center; gap: 1rem; }
.btn { padding: 0.5rem 1rem; background: #3498db; color: white; text-decoration: none; border-radius: 4px; text-align: center; min-width: 120px; } Добавлено (2025-08-14, 12:55) --------------------------------------------- --- title: "Страница с кнопками" css: | .custom-buttons { display: flex; flex-direction: column; gap: 1rem; margin: 2rem 0; } .button-row { display: flex; justify-content: center; gap: 1.5rem; } .btn { padding: 0.6rem 1.2rem; background: #3f51b5; color: white; border-radius: 6px; text-decoration: none; } ---
|
<!DOCTYPE html> <html> <head> <title>{{ .Title }} | {{ .Site.Title }}</title> <style> .icons-container { max-width: 1200px; margin: 0 auto; padding: 20px; } .icons-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 20px; margin-top: 20px; } .icon-card { border: 1px solid #eee; border-radius: 8px; padding: 15px; text-align: center; transition: transform 0.2s; } .icon-card:hover { transform: translateY(-5px); box-shadow: 0 5px 15px rgba(0,0,0,0.1); } .icon-svg { width: 48px; height: 48px; margin: 0 auto 10px; display: block; } .icon-name { font-family: monospace; font-size: 14px; color: #666; word-break: break-word; } table { width: 100%; border-collapse: collapse; margin-top: 20px; } th, td { border: 1px solid #ddd; padding: 12px; text-align: left; } th { background-color: #f8f9fa; font-weight: bold; } </style> </head> <body> <div class="icons-container"> <h1>{{ .Title }}</h1> <p>Всего иконок: {{ len .Site.Data.icons }}</p> <!-- Вариант 1: В виде карточек --> <div class="icons-grid"> {{ range $name, $svg := .Site.Data.icons }} <div class="icon-card"> <div class="icon-svg">{{ $svg | safeHTML }}</div> <div class="icon-name">{{ $name }}</div> </div> {{ end }} </div> <!-- Вариант 2: В виде таблицы --> <h2>Табличное представление</h2> <table> <thead> <tr> <th>Название</th> <th>SVG код</th> <th>Предпросмотр</th> </tr> </thead> <tbody> {{ range $name, $svg := .Site.Data.icons }} <tr> <td><code>{{ $name }}</code></td> <td> <details> <summary>Показать код</summary> <pre>{{ $svg }}</pre> </details> </td> <td> <div style="width: 32px; height: 32px;"> {{ $svg | safeHTML }} </div> </td> </tr> {{ end }} </tbody> </table> </div> </body> </html>
|
### Вариант 2: Создать кастомный layout
**Создайте layouts/partials/icons-gallery.html:** ```html <section class="icons-gallery"> <h2>Галерея иконок</h2> <div class="icons-grid"> {{ range $name, $svg := .Site.Data.icons }} <div class="icon-card"> <div class="icon-svg">{{ $svg | safeHTML }}</div> <div class="icon-name">{{ $name }}</div> </div> {{ end }} </div> </section>
<style> .icons-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 20px; margin: 20px 0; } .icon-card { border: 1px solid #e1e5e9; border-radius: 12px; padding: 20px; text-align: center; transition: all 0.3s ease; background: white; } .icon-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); } .icon-svg { width: 48px; height: 48px; margin: 0 auto 15px; display: block; } .icon-name { font-family: 'Monaco', 'Menlo', monospace; font-size: 13px; color: #555; word-break: break-word; } </style>
|
<section class="icons-gallery"> <h2>Галерея иконок</h2> <div class="icons-grid"> {{ range $name, $svg := .Site.Data.icons }} <div class="icon-card"> <div class="icon-svg">{{ $svg | safeHTML }}</div> <div class="icon-name">{{ $name }}</div> </div> {{ end }} </div> </section>
<style> .icons-gallery { margin: 40px 0; } .icons-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 20px; margin: 20px 0; } .icon-card { border: 1px solid #e1e5e9; border-radius: 12px; padding: 20px; text-align: center; transition: all 0.3s ease; background: white; } .icon-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); } .icon-svg { width: 48px; height: 48px; margin: 0 auto 15px; display: block; } .icon-name { font-family: 'Monaco', 'Menlo', monospace; font-size: 13px; color: #555; word-break: break-word; } </style>
|
<div class="icons-gallery"> <h2>Галерея иконок</h2> {{ if .Site.Data.icons }} <div class="icons-controls"> <div class="icons-stats"> Всего иконок: <strong>{{ len .Site.Data.icons }}</strong> </div> <input type="text" id="iconsSearch" placeholder="Поиск по названию иконки..." class="search-input" onkeyup="searchIcons()" > </div> <div class="icons-table-container"> <table class="icons-table" id="iconsTable"> <thead> <tr> <th>Иконка</th> <th>Название</th> <th>Размер</th> </tr> </thead> <tbody> {{ range $name, $svg := .Site.Data.icons }} <tr class="icon-row" data-name="{{ $name | lower }}"> <td class="icon-cell"> <div class="icon-svg-small">{{ $svg | safeHTML }}</div> </td> <td class="name-cell"> <code>{{ $name }}</code> </td> <td class="size-cell"> 16×16 px </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: 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; }
.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; }
.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; }
.name-cell code { background: #f5f5f5; padding: 4px 8px; border-radius: 4px; border: 1px solid #eee; font-size: 12px; }
.size-cell { color: #888; font-size: 12px; text-align: center; }
.no-results { text-align: center; padding: 40px; color: #888; font-style: italic; }
.error-message { color: #d32f2f; padding: 20px; border: 2px solid #ffcdd2; border-radius: 8px; background: #ffebee; }
/* Адаптивность */ @media (max-width: 768px) { .icons-controls { flex-direction: column; align-items: stretch; } .search-input { min-width: auto; width: 100%; } .icons-table { font-size: 14px; } .icons-table th, .icons-table td { padding: 10px 12px; } } </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'); if (iconName.includes(searchTerm)) { row.style.display = ''; visibleCount++; } else { row.style.display = 'none'; } }); // Показываем/скрываем сообщение "нет результатов" if (visibleCount === 0 && searchTerm !== '') { noResults.style.display = 'block'; } else { noResults.style.display = 'none'; } }
// Добавляем обработчик для очистки поиска при нажатии Escape document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('iconsSearch'); searchInput.addEventListener('keydown', function(e) { if (e.key === 'Escape') { this.value = ''; searchIcons(); } }); }); </script>
|
<div class="icons-gallery"> <h2>Галерея иконок</h2> {{ if .Site.Data.icons }} <div class="icons-controls"> <div class="icons-stats"> Всего иконок: <strong>{{ len .Site.Data.icons }}</strong> </div> <input type="text" id="iconsSearch" placeholder="Поиск по названию иконки..." class="search-input" > </div> <div class="icons-table-container"> <table class="icons-table" id="iconsTable"> <thead> <tr> <th>Иконка</th> <th>Название</th> <th>Размер</th> <th>Код для вставки</th> </tr> </thead> <tbody> {{ range $name, $svg := .Site.Data.icons }} <tr class="icon-row" data-name="{{ $name | lower }}"> <td class="icon-cell"> <div class="icon-svg-small">{{ $svg | safeHTML }}</div> </td> <td class="name-cell"> <code>{{ $name }}</code> </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> <span class="copy-success">✓ Скопировано!</span> </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: 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; }
.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; }
.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; }
.name-cell code { background: #f5f5f5; padding: 4px 8px; border-radius: 4px; border: 1px solid #eee; font-size: 12px; }
.size-cell { color: #888; font-size: 12px; text-align: center; width: 80px; }
.code-cell { width: 200px; }
.code-snippet { position: relative; background: #f8f9fa; padding: 8px 12px; border-radius: 6px; border: 1px solid #e9ecef; cursor: pointer; transition: all 0.3s ease; font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 12px; }
.code-snippet:hover { background: #e3f2fd; border-color: #2196f3; }
.code-snippet code { background: none; border: none; padding: 0; color: #1976d2; }
.copy-tooltip { position: absolute; top: -30px; left: 50%; transform: translateX(-50%); background: #333; color: white; padding: 4px 8px; border-radius: 4px; font-size: 11px; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; white-space: nowrap; }
.code-snippet:hover .copy-tooltip { opacity: 1; }
.copy-success { position: absolute; top: -30px; left: 50%; transform: translateX(-50%); background: #4caf50; color: white; padding: 4px 8px; border-radius: 4px; font-size: 11px; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; }
.copy-success.show { opacity: 1; }
.no-results { text-align: center; padding: 40px; color: #888; font-style: italic; }
.error-message { color: #d32f2f; padding: 20px; border: 2px solid #ffcdd2; border-radius: 8px; background: #ffebee; }
/* Адаптивность */ @media (max-width: 1024px) { .icons-table { font-size: 14px; } .code-snippet { font-size: 11px; padding: 6px 8px; } }
@media (max-width: 768px) { .icons-controls { flex-direction: column; align-items: stretch; } .search-input { min-width: auto; width: 100%; } .icons-table th, .icons-table td { padding: 10px 12px; } .code-cell { display: none; } } </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'); if (iconName.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 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'); // Обработчик поиска с debounce let searchTimeout; searchInput.addEventListener('input', function(e) { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchIcons(); }, 300); }); // Останавливаем всплытие события, чтобы не срабатывал глобальный поиск searchInput.addEventListener('keydown', function(e) { e.stopPropagation(); if (e.key === 'Escape') { this.value = ''; searchIcons(); } }); // Предотвращаем всплытие при клике searchInput.addEventListener('click', function(e) { e.stopPropagation(); }); }); </script>
|
<div class="icons-gallery"> <h2>Галерея иконок</h2> {{ if .Site.Data.icons }} <div class="icons-controls"> <div class="icons-stats"> Всего иконок: <strong>{{ len .Site.Data.icons }}</strong> </div> <input type="text" id="iconsSearch" placeholder="Поиск по названию иконки..." class="search-input" > </div> <div class="icons-table-container"> <table class="icons-table" id="iconsTable"> <thead> <tr> <th>Иконка</th> <th>Название</th> <th>Размер</th> <th>Код для вставки</th> </tr> </thead> <tbody> {{ range $name, $svg := .Site.Data.icons }} <tr class="icon-row" data-name="{{ $name | lower }}"> <td class="icon-cell"> <div class="icon-svg-small" onclick="copySvgCode(this, {{ $svg | jsonify }})" title="Кликните чтобы скопировать SVG код"> {{ $svg | safeHTML }} <span class="copy-svg-tooltip">Копировать SVG</span> <span class="copy-success-svg">✓</span> </div> </td> <td class="name-cell"> <code>{{ $name }}</code> </td> <td class="size-cell"> 16×16 px </td> <td class="code-cell"> <div class="code-snippet" onclick="copyShortcode(this, '{{ $name }}')"> <code>{{ "{{<" }}icon "{{ $name }}"{{ ">"}}}}</code> <span class="copy-tooltip">Кликните для копирования</span> <span class="copy-success">✓ Скопировано!</span> </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: 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; }
.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; cursor: pointer; position: relative; transition: transform 0.2s ease; }
.icon-svg-small:hover { transform: scale(1.2); }
.icon-svg-small svg { width: 16px; height: 16px; min-width: 16px; min-height: 16px; }
.copy-svg-tooltip { position: absolute; top: -35px; left: 50%; transform: translateX(-50%); background: #333; color: white; padding: 6px 10px; border-radius: 6px; font-size: 11px; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; white-space: nowrap; z-index: 1000; }
.icon-svg-small:hover .copy-svg-tooltip { opacity: 1; }
.copy-success-svg { position: absolute; top: -30px; left: 50%; transform: translateX(-50%); background: #4caf50; color: white; padding: 6px 10px; border-radius: 50%; font-size: 14px; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; }
.copy-success-svg.show { opacity: 1; }
.name-cell { font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 13px; color: #333; }
.name-cell code { background: #f5f5f5; padding: 4px 8px; border-radius: 4px; border: 1px solid #eee; font-size: 12px; }
.size-cell { color: #888; font-size: 12px; text-align: center; width: 80px; }
.code-cell { width: 300px; /* Увеличили ширину на 50% */ }
.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; }
.code-snippet:hover { background: #e3f2fd; border-color: #2196f3; }
.code-snippet code { background: none; border: none; padding: 0; color: #1976d2; word-break: break-all; }
.copy-tooltip { position: absolute; top: -40px; left: 50%; transform: translateX(-50%); background: #333; color: white; padding: 8px 12px; border-radius: 6px; 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: -45px; left: 50%; transform: translateX(-50%); background: #4caf50; color: white; padding: 8px 16px; border-radius: 20px; font-size: 12px; opacity: 0; transition: all 0.3s ease; pointer-events: none; display: flex; align-items: center; gap: 6px; }
.copy-success::before { content: "✓"; font-size: 14px; font-weight: bold; }
.copy-success.show { opacity: 1; transform: translateX(-50%) translateY(-5px); }
.no-results { text-align: center; padding: 40px; color: #888; font-style: italic; }
.error-message { color: #d32f2f; padding: 20px; border: 2px solid #ffcdd2; border-radius: 8px; background: #ffebee; }
/* Адаптивность */ @media (max-width: 1024px) { .icons-table { font-size: 14px; } .code-cell { width: 250px; } .code-snippet { font-size: 12px; padding: 8px 10px; } }
@media (max-width: 768px) { .icons-controls { flex-direction: column; align-items: stretch; } .search-input { min-width: auto; width: 100%; } .icons-table th, .icons-table td { padding: 10px 12px; } .code-cell { display: none; } } </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'); if (iconName.includes(searchTerm)) { row.style.display = ''; visibleCount++; } else { row.style.display = 'none'; } }); if (visibleCount === 0 && searchTerm !== '') { noResults.style.display = 'block'; } else { noResults.style.display = 'none'; } }
// Функция для копирования shortcode function copyShortcode(element, iconName) { const code = `{{<icon "${iconName}">}}`; copyToClipboard(code, element.querySelector('.copy-success')); }
// Функция для копирования SVG кода function copySvgCode(element, svgCode) { copyToClipboard(svgCode, element.querySelector('.copy-success-svg')); }
// Универсальная функция копирования function copyToClipboard(text, successElement) { navigator.clipboard.writeText(text).then(() => { successElement.classList.add('show'); setTimeout(() => { successElement.classList.remove('show'); }, 2000); }).catch(err => { // Fallback для старых браузеров const textArea = document.createElement('textarea'); textArea.value = text; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); successElement.classList.add('show'); setTimeout(() => { successElement.classList.remove('show'); }, 2000); }); }
// Инициализация после загрузки DOM document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('iconsSearch'); // Обработчик поиска с debounce let searchTimeout; searchInput.addEventListener('input', function(e) { e.stopPropagation(); // Останавливаем всплытие clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchIcons(); }, 300); }); // Останавливаем всплытие всех событий searchInput.addEventListener('keydown', function(e) { e.stopPropagation(); if (e.key === 'Escape') { this.value = ''; searchIcons(); } }); searchInput.addEventListener('keyup', function(e) { e.stopPropagation(); }); searchInput.addEventListener('keypress', function(e) { e.stopPropagation(); }); searchInput.addEventListener('click', function(e) { e.stopPropagation(); }); searchInput.addEventListener('focus', function(e) { e.stopPropagation(); }); searchInput.addEventListener('blur', function(e) { e.stopPropagation(); }); // Предотвращаем всплытие для всех элементов таблицы document.querySelectorAll('.icon-svg-small, .code-snippet').forEach(el => { el.addEventListener('click', function(e) { e.stopPropagation(); }); }); }); </script>
|
<div class="icons-gallery"> <h2>Галерея иконок</h2> {{ if .Site.Data.icons }} <div class="icons-controls"> <div class="icons-stats"> Всего иконок: <strong>{{ len .Site.Data.icons }}</strong> </div> <input type="text" id="iconsSearch" placeholder="Поиск по названию иконки..." class="search-input" > </div> <div class="icons-table-container"> <table class="icons-table" id="iconsTable"> <thead> <tr> <th>Иконка</th> <th>Название</th> <th>Размер</th> <th>Код для вставки</th> </tr> </thead> <tbody> {{ range $name, $svg := .Site.Data.icons }} <tr class="icon-row" data-name="{{ $name | lower }}"> <td class="icon-cell"> <div class="icon-svg-small" onclick="copySvgCode(this, '{{ $svg }}')" title="Кликните чтобы скопировать SVG код"> {{ $svg | safeHTML }} <span class="copy-svg-tooltip">Копировать SVG</span> <span class="copy-success-svg">✓</span> </div> </td> <td class="name-cell"> <code>{{ $name }}</code> </td> <td class="size-cell"> 16×16 px </td> <td class="code-cell"> <div class="code-snippet" onclick="copyShortcode(this, '{{ $name }}')"> <code>{{ "{{<" }}icon "{{ $name }}"{{ ">"}}}}</code> <span class="copy-tooltip">Кликните для копирования</span> <span class="copy-success">✓ Скопировано!</span> </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: 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; }
.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; cursor: pointer; position: relative; transition: transform 0.2s ease; }
.icon-svg-small:hover { transform: scale(1.2); }
.icon-svg-small svg { width: 16px; height: 16px; min-width: 16px; min-height: 16px; }
.copy-svg-tooltip { position: absolute; top: -35px; left: 50%; transform: translateX(-50%); background: #333; color: white; padding: 6px 10px; border-radius: 6px; font-size: 11px; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; white-space: nowrap; z-index: 1000; }
.icon-svg-small:hover .copy-svg-tooltip { opacity: 1; }
.copy-success-svg { position: absolute; top: -30px; left: 50%; transform: translateX(-50%); background: #4caf50; color: white; padding: 6px 10px; border-radius: 50%; font-size: 14px; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; }
.copy-success-svg.show { opacity: 1; }
.name-cell { font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 13px; color: #333; }
.name-cell code { background: #f5f5f5; padding: 4px 8px; border-radius: 4px; border: 1px solid #eee; font-size: 12px; }
.size-cell { color: #888; font-size: 12px; text-align: center; width: 80px; }
.code-cell { width: 300px; }
.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; }
.code-snippet:hover { background: #e3f2fd; border-color: #2196f3; }
.code-snippet code { background: none; border: none; padding: 0; color: #1976d2; word-break: break-all; }
.copy-tooltip { position: absolute; top: -40px; left: 50%; transform: translateX(-50%); background: #333; color: white; padding: 8px 12px; border-radius: 6px; 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: -45px; left: 50%; transform: translateX(-50%); background: #4caf50; color: white; padding: 8px 16px; border-radius: 20px; font-size: 12px; opacity: 0; transition: all 0.3s ease; pointer-events: none; display: flex; align-items: center; gap: 6px; }
.copy-success::before { content: "✓"; font-size: 14px; font-weight: bold; }
.copy-success.show { opacity: 1; transform: translateX(-50%) translateY(-5px); }
.no-results { text-align: center; padding: 40px; color: #888; font-style: italic; }
.error-message { color: #d32f2f; padding: 20px; border: 2px solid #ffcdd2; border-radius: 8px; background: #ffebee; }
@media (max-width: 1024px) { .icons-table { font-size: 14px; } .code-cell { width: 250px; } .code-snippet { font-size: 12px; padding: 8px 10px; } }
@media (max-width: 768px) { .icons-controls { flex-direction: column; align-items: stretch; } .search-input { min-width: auto; width: 100%; } .icons-table th, .icons-table td { padding: 10px 12px; } .code-cell { display: none; } } </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'); if (iconName.includes(searchTerm)) { row.style.display = ''; visibleCount++; } else { row.style.display = 'none'; } }); if (visibleCount === 0 && searchTerm !== '') { noResults.style.display = 'block'; } else { noResults.style.display = 'none'; } }
// Функция для копирования shortcode function copyShortcode(element, iconName) { const code = '{{<icon "' + iconName + '">}}'; copyToClipboard(code, element.querySelector('.copy-success')); }
// Функция для копирования SVG кода function copySvgCode(element, svgCode) { copyToClipboard(svgCode, element.querySelector('.copy-success-svg')); }
// Универсальная функция копирования function copyToClipboard(text, successElement) { // Создаем временный textarea для копирования const textArea = document.createElement('textarea'); textArea.value = text; textArea.style.position = 'fixed'; textArea.style.opacity = '0'; document.body.appendChild(textArea); textArea.select(); try { const successful = document.execCommand('copy'); if (successful) { // Показываем успешное сообщение successElement.classList.add('show'); setTimeout(() => { successElement.classList.remove('show'); }, 2000); } } catch (err) { console.error('Ошибка при копировании:', err); } document.body.removeChild(textArea); }
// Инициализация после загрузки DOM document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('iconsSearch'); // Обработчик поиска с debounce let searchTimeout; searchInput.addEventListener('input', function(e) { e.stopPropagation(); clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchIcons(); }, 300); }); // Останавливаем всплытие всех событий const stopPropagation = function(e) { e.stopPropagation(); if (e.key === 'Escape') { this.value = ''; searchIcons(); } }; searchInput.addEventListener('keydown', stopPropagation); searchInput.addEventListener('keyup', stopPropagation); searchInput.addEventListener('keypress', stopPropagation); searchInput.addEventListener('click', function(e) { e.stopPropagation(); }); searchInput.addEventListener('focus', function(e) { e.stopPropagation(); }); searchInput.addEventListener('blur', function(e) { e.stopPropagation(); }); // Предотвращаем всплытие для всех элементов таблицы document.querySelectorAll('.icon-svg-small, .code-snippet').forEach(el => { el.addEventListener('click', function(e) { e.stopPropagation(); }); }); });
// Глобальная остановка событий для поискового поля document.addEventListener('keydown', function(e) { const searchInput = document.getElementById('iconsSearch'); if (document.activeElement === searchInput) { e.stopImmediatePropagation(); } });
document.addEventListener('keyup', function(e) { const searchInput = document.getElementById('iconsSearch'); if (document.activeElement === searchInput) { e.stopImmediatePropagation(); } }); </script>
|
<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'); if (iconName.includes(searchTerm)) { row.style.display = ''; visibleCount++; } else { row.style.display = 'none'; } }); if (visibleCount === 0 && searchTerm !== '') { noResults.style.display = 'block'; } else { noResults.style.display = 'none'; } }
// Функция для копирования shortcode function copyShortcode(element, iconName) { const code = '{{<' + 'icon "' + iconName + '"' + '>' + '}}'; copyToClipboard(code, element.querySelector('.copy-success')); }
// Функция для копирования SVG кода function copySvgCode(element, svgCode) { copyToClipboard(svgCode, element.querySelector('.copy-success-svg')); }
// Универсальная функция копирования function copyToClipboard(text, successElement) { // Создаем временный textarea для копирования const textArea = document.createElement('textarea'); textArea.value = text; textArea.style.position = 'fixed'; textArea.style.opacity = '0'; document.body.appendChild(textArea); textArea.select(); try { const successful = document.execCommand('copy'); if (successful) { // Показываем успешное сообщение successElement.classList.add('show'); setTimeout(() => { successElement.classList.remove('show'); }, 2000); } } catch (err) { console.error('Ошибка при копировании:', err); } document.body.removeChild(textArea); }
// Инициализация после загрузки DOM document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('iconsSearch'); // Обработчик поиска с debounce let searchTimeout; searchInput.addEventListener('input', function(e) { e.stopPropagation(); clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchIcons(); }, 300); }); // Останавливаем всплытие всех событий const stopPropagation = function(e) { e.stopPropagation(); if (e.key === 'Escape') { this.value = ''; searchIcons(); } }; searchInput.addEventListener('keydown', stopPropagation); searchInput.addEventListener('keyup', stopPropagation); searchInput.addEventListener('keypress', stopPropagation); searchInput.addEventListener('click', function(e) { e.stopPropagation(); }); searchInput.addEventListener('focus', function(e) { e.stopPropagation(); }); searchInput.addEventListener('blur', function(e) { e.stopPropagation(); }); // Предотвращаем всплытие для всех элементов таблицы document.querySelectorAll('.icon-svg-small, .code-snippet').forEach(el => { el.addEventListener('click', function(e) { e.stopPropagation(); }); }); });
// Глобальная остановка событий для поискового поля document.addEventListener('keydown', function(e) { const searchInput = document.getElementById('iconsSearch'); if (document.activeElement === searchInput) { e.stopImmediatePropagation(); } });
document.addEventListener('keyup', function(e) { const searchInput = document.getElementById('iconsSearch'); if (document.activeElement === searchInput) { e.stopImmediatePropagation(); } }); </script>
|
<div class="icons-gallery"> <h2>Галерея иконок</h2> {{ if .Site.Data.icons }} <div class="icons-controls"> <div class="icons-stats"> Всего иконок: <strong>{{ len .Site.Data.icons }}</strong> </div> <input type="text" id="iconsSearch" placeholder="Поиск по названию иконки..." class="search-input" > </div> <div class="icons-table-container"> <table class="icons-table" id="iconsTable"> <thead> <tr> <th>Иконка</th> <th>Название</th> <th>Размер</th> <th>Код для вставки</th> </tr> </thead> <tbody> {{ range $name, $svg := .Site.Data.icons }} <tr class="icon-row" data-name="{{ $name | lower }}"> <td class="icon-cell"> <div class="icon-svg-small"> {{ $svg | safeHTML }} </div> </td> <td class="name-cell"> <code>{{ $name }}</code> </td> <td class="size-cell"> 16×16 px </td> <td class="code-cell"> <div class="code-snippet" onclick="copyShortcode(this, '{{ $name }}')"> <code>{{ "{{<" }}icon "{{ $name }}"{{ ">"}}}}</code> <span class="copy-tooltip">Кликните для копирования</span> <span class="copy-success">✓ Скопировано!</span> </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: 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; }
.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; }
.name-cell code { background: #f5f5f5; padding: 4px 8px; border-radius: 4px; border: 1px solid #eee; font-size: 12px; }
.size-cell { color: #888; font-size: 12px; text-align: center; width: 80px; }
.code-cell { width: 300px; }
.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; }
.code-snippet:hover { background: #e3f2fd; border-color: #2196f3; }
.code-snippet code { background: none; border: none; padding: 0; color: #1976d2; word-break: break-all; }
.copy-tooltip { position: absolute; top: -40px; left: 50%; transform: translateX(-50%); background: #333; color: white; padding: 8px 12px; border-radius: 6px; 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: -45px; left: 50%; transform: translateX(-50%); background: #4caf50; color: white; padding: 8px 16px; border-radius: 20px; font-size: 12px; opacity: 0; transition: all 0.3s ease; pointer-events: none; display: flex; align-items: center; gap: 6px; }
.copy-success::before { content: "✓"; font-size: 14px; font-weight: bold; }
.copy-success.show { opacity: 1; transform: translateX(-50%) translateY(-5px); }
.no-results { text-align: center; padding: 40px; color: #888; font-style: italic; }
.error-message { color: #d32f2f; padding: 20px; border: 2px solid #ffcdd2; border-radius: 8px; background: #ffebee; }
@media (max-width: 1024px) { .icons-table { font-size: 14px; } .code-cell { width: 250px; } .code-snippet { font-size: 12px; padding: 8px 10px; } }
@media (max-width: 768px) { .icons-controls { flex-direction: column; align-items: stretch; } .search-input { min-width: auto; width: 100%; } .icons-table th, .icons-table td { padding: 10px 12px; } .code-cell { display: none; } } </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'); if (iconName.includes(searchTerm)) { row.style.display = ''; visibleCount++; } else { row.style.display = 'none'; } }); if (visibleCount === 0 && searchTerm !== '') { noResults.style.display = 'block'; } else { noResults.style.display = 'none'; } }
// Функция для копирования shortcode function copyShortcode(element, iconName) { const code = '{{<' + 'icon "' + iconName + '"' + '>' + '}}'; // Создаем временный textarea для копирования const textArea = document.createElement('textarea'); textArea.value = code; textArea.style.position = 'fixed'; textArea.style.opacity = '0'; document.body.appendChild(textArea); textArea.select(); try { const successful = document.execCommand('copy'); if (successful) { // Показываем успешное сообщение const successElement = element.querySelector('.copy-success'); successElement.classList.add('show'); setTimeout(() => { successElement.classList.remove('show'); }, 2000); } } catch (err) { console.error('Ошибка при копировании:', err); } document.body.removeChild(textArea); }
// Инициализация после загрузки DOM document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('iconsSearch'); // Обработчик поиска с debounce let searchTimeout; searchInput.addEventListener('input', function(e) { e.stopPropagation(); clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchIcons(); }, 300); }); // Останавливаем всплытие всех событий const stopPropagation = function(e) { e.stopPropagation(); if (e.key === 'Escape') { this.value = ''; searchIcons(); } }; searchInput.addEventListener('keydown', stopPropagation); searchInput.addEventListener('keyup', stopPropagation); searchInput.addEventListener('keypress', stopPropagation); searchInput.addEventListener('click', function(e) { e.stopPropagation(); }); searchInput.addEventListener('focus', function(e) { e.stopPropagation(); }); searchInput.addEventListener('blur', function(e) { e.stopPropagation(); }); // Предотвращаем всплытие для элементов с кодом document.querySelectorAll('.code-snippet').forEach(el => { el.addEventListener('click', function(e) { e.stopPropagation(); }); }); });
// Глобальная остановка событий для поискового поля document.addEventListener('keydown', function(e) { const searchInput = document.getElementById('iconsSearch'); if (document.activeElement === searchInput) { e.stopImmediatePropagation(); } });
document.addEventListener('keyup', function(e) { const searchInput = document.getElementById('iconsSearch'); if (document.activeElement === searchInput) { e.stopImmediatePropagation(); } }); </script>
|
<div class="icons-gallery"> <h2>Галерея иконок</h2> {{ if .Site.Data.icons }} <div class="icons-controls"> <div class="icons-stats"> Всего иконок: <strong>{{ len .Site.Data.icons }}</strong> </div> <input type="text" id="iconsSearch" placeholder="Поиск по названию иконки..." class="search-input" > </div> <div class="icons-table-container"> <table class="icons-table" id="iconsTable"> <thead> <tr> <th>Иконка</th> <th>Название</th> <th>Размер</th> <th>Код для вставки</th> </tr> </thead> <tbody> {{ range $name, $svg := .Site.Data.icons }} <tr class="icon-row" data-name="{{ $name | lower }}"> <td class="icon-cell"> <div class="icon-svg-small"> {{ $svg | safeHTML }} </div> </td> <td class="name-cell"> <code>{{ $name }}</code> </td> <td class="size-cell"> 16×16 px </td> <td class="code-cell"> <div class="code-snippet"> <code>{{ "{{<" }}icon "{{ $name }}"{{ ">"}}}}</code> </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: 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; }
.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; }
.name-cell code { background: #f5f5f5; padding: 4px 8px; border-radius: 4px; border: 1px solid #eee; font-size: 12px; }
.size-cell { color: #888; font-size: 12px; text-align: center; width: 80px; }
.code-cell { width: 300px; }
.code-snippet { background: #f8f9fa; padding: 10px 14px; border-radius: 6px; border: 1px solid #e9ecef; font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 13px; }
.code-snippet code { background: none; border: none; padding: 0; color: #1976d2; word-break: break-all; }
.no-results { text-align: center; padding: 40px; color: #888; font-style: italic; }
.error-message { color: #d32f2f; padding: 20px; border: 2px solid #ffcdd2; border-radius: 8px; background: #ffebee; }
@media (max-width: 1024px) { .icons-table { font-size: 14px; } .code-cell { width: 250px; } .code-snippet { font-size: 12px; padding: 8px 10px; } }
@media (max-width: 768px) { .icons-controls { flex-direction: column; align-items: stretch; } .search-input { min-width: auto; width: 100%; } .icons-table th, .icons-table td { padding: 10px 12px; } .code-cell { display: none; } } </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'); if (iconName.includes(searchTerm)) { row.style.display = ''; visibleCount++; } else { row.style.display = 'none'; } }); if (visibleCount === 0 && searchTerm !== '') { noResults.style.display = 'block'; } else { noResults.style.display = 'none'; } }
// Инициализация после загрузки DOM document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('iconsSearch'); // Обработчик поиска с debounce let searchTimeout; searchInput.addEventListener('input', function(e) { e.stopPropagation(); clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchIcons(); }, 300); }); // Останавливаем всплытие всех событий const stopPropagation = function(e) { e.stopPropagation(); if (e.key === 'Escape') { this.value = ''; searchIcons(); } }; searchInput.addEventListener('keydown', stopPropagation); searchInput.addEventListener('keyup', stopPropagation); searchInput.addEventListener('keypress', stopPropagation); searchInput.addEventListener('click', function(e) { e.stopPropagation(); }); searchInput.addEventListener('focus', function(e) { e.stopPropagation(); }); searchInput.addEventListener('blur', function(e) { e.stopPropagation(); }); });
// Глобальная остановка событий для поискового поля document.addEventListener('keydown', function(e) { const searchInput = document.getElementById('iconsSearch'); if (document.activeElement === searchInput) { e.stopImmediatePropagation(); } });
document.addEventListener('keyup', function(e) { const searchInput = document.getElementById('iconsSearch'); if (document.activeElement === searchInput) { e.stopImmediatePropagation(); } }); </script>
|
<div class="icons-gallery"> <h2>Галерея иконок</h2> {{ if .Site.Data.icons }} <div class="icons-controls"> <div class="icons-stats"> Всего иконок: <strong>{{ len .Site.Data.icons }}</strong> </div> <input type="text" id="iconsSearch" placeholder="Поиск по названию иконки..." class="search-input" > </div> <div class="icons-table-container"> <table class="icons-table" id="iconsTable"> <thead> <tr> <th>Иконка</th> <th>Название</th> <th>Размер</th> <th>Код для вставки</th> </tr> </thead> <tbody> {{ range $name, $svg := .Site.Data.icons }} <tr class="icon-row" data-name="{{ $name | lower }}"> <td class="icon-cell"> <div class="icon-svg-small">{{ $svg | safeHTML }}</div> </td> <td class="name-cell"> <code>{{ $name }}</code> </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: 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; }
.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; }
.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; }
.name-cell code { background: #f5f5f5; padding: 4px 8px; border-radius: 4px; border: 1px solid #eee; font-size: 12px; }
.size-cell { color: #888; font-size: 12px; text-align: center; width: 80px; }
.code-cell { width: 300px; /* Увеличили ширину на 50% */ }
.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; }
.error-message { color: #d32f2f; padding: 20px; border: 2px solid #ffcdd2; border-radius: 8px; background: #ffebee; }
/* Адаптивность */ @media (max-width: 1024px) { .icons-table { font-size: 14px; } .code-cell { width: 250px; } .code-snippet { font-size: 12px; padding: 8px 12px; } }
@media (max-width: 768px) { .icons-controls { flex-direction: column; align-items: stretch; } .search-input { min-width: auto; width: 100%; } .icons-table th, .icons-table td { padding: 10px 12px; } .code-cell { display: none; } } </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'); if (iconName.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 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'); // Полностью отключаем всплытие событий function stopPropagation(e) { e.stopPropagation(); e.stopImmediatePropagation(); return false; } // Обработчик поиска с debounce let searchTimeout; searchInput.addEventListener('input', function(e) { stopPropagation(e); clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchIcons(); }, 300); }); // Останавливаем все события searchInput.addEventListener('keydown', stopPropagation); searchInput.addEventListener('keyup', stopPropagation); searchInput.addEventListener('keypress', stopPropagation); searchInput.addEventListener('click', stopPropagation); searchInput.addEventListener('mousedown', stopPropagation); searchInput.addEventListener('mouseup', stopPropagation); searchInput.addEventListener('focus', stopPropagation); searchInput.addEventListener('blur', stopPropagation); // Отдельно обрабатываем Escape searchInput.addEventListener('keydown', function(e) { if (e.key === 'Escape') { this.value = ''; searchIcons(); e.stopPropagation(); } }); // Предотвращаем всплытие для всего контейнера const galleryContainer = document.querySelector('.icons-gallery'); if (galleryContainer) { galleryContainer.addEventListener('keydown', function(e) { if (e.target === searchInput) { e.stopPropagation(); } }); } }); </script>
|
<div class="icons-gallery"> <h2>Галерея иконок</h2> {{ if .Site.Data.icons }} <div class="icons-controls"> <div class="icons-stats"> Всего иконок: <strong>{{ len .Site.Data.icons }}</strong> </div> <input type="text" id="iconsSearch" placeholder="Поиск по названию иконки..." class="search-input" > </div> <div class="icons-table-container"> <table class="icons-table" id="iconsTable"> <thead> <tr> <th>Иконка</th> <th>Название</th> <th>Размер</th> <th>Код для вставки</th> </tr> </thead> <tbody> {{ range $name, $svg := .Site.Data.icons }} <tr class="icon-row" data-name="{{ $name | lower }}"> <td class="icon-cell"> <div class="icon-svg-small">{{ $svg | safeHTML }}</div> </td> <td class="name-cell"> <code>{{ $name }}</code> </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: 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; }
.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; }
.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; }
.name-cell code { background: #f5f5f5; padding: 4px 8px; border-radius: 4px; border: 1px solid #eee; font-size: 12px; }
.size-cell { color: #888; font-size: 12px; text-align: center; width: 80px; }
.code-cell { width: 300px; }
.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; }
.error-message { color: #d32f2f; padding: 20px; border: 2px solid #ffcdd2; border-radius: 8px; background: #ffebee; }
/* Адаптивность */ @media (max-width: 1024px) { .icons-table { font-size: 14px; } .code-cell { width: 250px; } .code-snippet { font-size: 12px; padding: 8px 12px; } }
@media (max-width: 768px) { .icons-controls { flex-direction: column; align-items: stretch; } .search-input { min-width: auto; width: 100%; } .icons-table th, .icons-table td { padding: 10px 12px; } .code-cell { display: none; } } </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'); if (iconName.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 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'); // Полностью изолируем поле поиска function isolateSearchInput() { // Отключаем все стандартные обработчики const originalAddEventListener = searchInput.addEventListener; searchInput.addEventListener = function(type, listener, options) { if (type !== 'input' && type !== 'click' && type !== 'focus') { return originalAddEventListener.call(this, type, function(e) { e.stopImmediatePropagation(); if (listener) listener(e); }, options); } return originalAddEventListener.call(this, type, listener, options); }; // Перехватываем все события const events = ['keydown', 'keyup', 'keypress', 'input', 'click', 'mousedown', 'mouseup', 'focus', 'blur']; events.forEach(eventType => { searchInput.addEventListener(eventType, function(e) { e.stopImmediatePropagation(); if (eventType === 'keydown' && e.key === 'Escape') { this.value = ''; searchIcons(); } }, true); // Используем capture phase }); // Специально для input событий searchInput.addEventListener('input', function(e) { e.stopImmediatePropagation(); clearTimeout(searchInput._searchTimeout); searchInput._searchTimeout = setTimeout(() => { searchIcons(); }, 300); }, true); } // Запускаем изоляцию isolateSearchInput(); // Дополнительная защита - оборачиваем в Shadow DOM если поддерживается if (typeof ShadowRoot !== 'undefined') { const container = searchInput.closest('.icons-controls'); if (container && !container.shadowRoot) { const shadow = container.attachShadow({mode: 'open'}); const style = document.createElement('style'); style.textContent = ` .search-input { padding: 12px 16px; border: 2px solid #e1e5e9; border-radius: 8px; font-size: 14px; min-width: 250px; } .search-input:focus { outline: none; border-color: #007acc; } `; shadow.appendChild(style); shadow.appendChild(searchInput.cloneNode(true)); container.removeChild(searchInput); // Обновляем ссылку на input const shadowInput = shadow.querySelector('input'); shadowInput.id = 'iconsSearch'; // Переинициализируем обработчики для shadow input setTimeout(() => { const newSearchInput = shadow.querySelector('#iconsSearch'); if (newSearchInput) { newSearchInput.addEventListener('input', function(e) { clearTimeout(searchInput._searchTimeout); searchInput._searchTimeout = setTimeout(() => { searchIcons(); }, 300); }); newSearchInput.addEventListener('keydown', function(e) { if (e.key === 'Escape') { this.value = ''; searchIcons(); } }); } }, 100); } } }); </script>
|
<div class="icons-gallery"> <h2>Галерея иконок</h2> {{ if .Site.Data.icons }} <div class="icons-controls"> <div class="icons-stats"> Всего иконок: <strong>{{ len .Site.Data.icons }}</strong> </div> <input type="text" id="iconsSearch" placeholder="Поиск по названию иконки..." class="search-input" > </div> <div class="icons-table-container"> <table class="icons-table" id="iconsTable"> <thead> <tr> <th>Иконка</th> <th>Название</th> <th>Размер</th> <th>Код для вставки</th> </tr> </thead> <tbody> {{ range $name, $svg := .Site.Data.icons }} <tr class="icon-row" data-name="{{ $name | lower }}"> <td class="icon-cell"> <div class="icon-svg-small">{{ $svg | safeHTML }}</div> </td> <td class="name-cell"> <code>{{ $name }}</code> </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: 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; }
.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; }
.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; }
.name-cell code { background: #f5f5f5; padding: 4px 8px; border-radius: 4px; border: 1px solid #eee; font-size: 12px; }
.size-cell { color: #888; font-size: 12px; text-align: center; width: 80px; }
.code-cell { width: 300px; }
.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; }
.error-message { color: #d32f2f; padding: 20px; border: 2px solid #ffcdd2; border-radius: 8px; background: #ffebee; }
/* Адаптивность */ @media (max-width: 1024px) { .icons-table { font-size: 14px; } .code-cell { width: 250px; } .code-snippet { font-size: 12px; padding: 8px 12px; } }
@media (max-width: 768px) { .icons-controls { flex-direction: column; align-items: stretch; } .search-input { min-width: auto; width: 100%; } .icons-table th, .icons-table td { padding: 10px 12px; } .code-cell { display: none; } } </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'); if (iconName.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 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'); if (!searchInput) return; // Простой и эффективный обработчик let searchTimeout; // Обработчик input с debounce searchInput.addEventListener('input', function(e) { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchIcons(); }, 300); }); // Останавливаем всплытие только для keydown событий searchInput.addEventListener('keydown', function(e) { // Останавливаем всплытие для всех клавиш кроме Tab if (e.key !== 'Tab') { e.stopPropagation(); } if (e.key === 'Escape') { this.value = ''; searchIcons(); e.preventDefault(); } }); // Также останавливаем всплытие для keyup searchInput.addEventListener('keyup', function(e) { if (e.key !== 'Tab') { e.stopPropagation(); } }); // Предотвращаем всплытие для кликов searchInput.addEventListener('click', function(e) { e.stopPropagation(); }); // Предотвращаем всплытие для фокуса searchInput.addEventListener('focus', function(e) { e.stopPropagation(); }); // Предотвращаем всплытие для blur searchInput.addEventListener('blur', function(e) { e.stopPropagation(); }); // Дополнительно: находим глобальный поиск и временно отключаем его function temporarilyDisableGlobalSearch() { const globalSearch = document.querySelector('input[type="search"], [id*="search"], [class*="search"]'); if (globalSearch && globalSearch !== searchInput) { // Сохраняем оригинальные обработчики const originalOnInput = globalSearch.oninput; const originalOnKeydown = globalSearch.onkeydown; // Временно отключаем globalSearch.oninput = null; globalSearch.onkeydown = null; // Восстанавливаем через 5 секунд setTimeout(() => { if (originalOnInput) globalSearch.oninput = originalOnInput; if (originalOnKeydown) globalSearch.onkeydown = originalOnKeydown; }, 5000); } } // Вызываем при фокусе на нашем поиске searchInput.addEventListener('focus', temporarilyDisableGlobalSearch); }); </script>
|