6.6 KiB
Интерактивные билеты охотника (a1-tir.ru/bilety)
Проект: скачать страницу билетов для экзамена на гражданское оружие и превратить в интерактивный тренажёр.
Возможности: номер правильного ответа скрыт · ответы кликабельны · выбранный неправильный → красный, правильный → зелёный.
Файлы (исходники в ~/Downloads/):
bilety.html— скачанная + расширенная страница (инъекция CSS/JS + метаданные)bilety.js— enhancer: парсер вопросов + click-логикаbilety.css— стили подсветки (зелёный/красный)a1-tir_bilety_raw.html— оригинальная скачанная копия (667 КБ)
Статус
- ✅ Страница скачана и переработана в интерактив.
- ⏸️ Доставка в Eagle Dashboard Pages не завершена — упирается в права:
/Library/WebServer/Documents/root-owned,sudo cpтребует пароль из неинтерактивного шелла. Нужно либо получить sudo-пароль от Alex, либо он запустит вручную:После копирования страница появится вsudo cp ~/Downloads/bilety.html ~/Downloads/bilety.js ~/Downloads/bilety.css /Library/WebServer/Documents/http://localhost:8880/?tab=pagesпод именемbilety(title/purpose/contains уже заполнены). Рестарт дашборда не нужен.
Источник и структура (Tilda)
Страница — Tilda-лендинг, весь исходный HTML на одной строке (a1-tir_bilety_raw.html, строка 228 содержит контент).
Экзамен разложен по 4 блокам data-record-type="106" (Tilda text-блок div.field-text.t-text):
rec465410787— «Правовая подготовка», вопросы 1.1–1.49rec1120437831— без заголовка (продолжение правовой), 1.50–1.93rec1120438216— «Огневая подготовка», 2.1–2.41rec465410788— без заголовка (правила охоты), 58–103 · вопросы из нескольких<strong>- Итого ~180 вопросов.
Структура одного вопроса в DOM (проверено по сырым данным)
Каждый блок — один большой div; внутри childNodes:
<br/>— разделители (шум)<strong>Вопрос</strong>— текст вопроса; может занимать несколько подряд<strong>(напр. вопрос 58); внутри возможен вложенный<a>(consultantplus)- шапка раздела —
<p><strong>Заголовок</strong></p>(strong вложен в p → не ловится как вопрос) - текстовые узлы ответов:
"1. Текст","2. ...","3. ..."(бывают ведущие пробелы) <em>N</em>— номер правильного ответа (чистое число)- примечание —
<em><u>Примечание</u>: …</em>(НЕ номер, сохранить) - шум:
<strong> </strong>,<em> </em>, пустой<em>с<strong data-redactor-tag>
Контентных <img>/<svg> в блоках вопросов нет — только текст.
Решение — чисто клиентский JS (без библиотек/backend)
bilety.js на DOMContentLoaded обрабатывает каждый [data-record-type="106"] .t-text:
Парсер parseQuiz (конечный автомат по childNodes):
<strong>с непустым текстом, не : если у текущего вопроса ещё нет ответов и фазаquestion→ мержим текст (многострочный вопрос); иначе → новый вопрос.- текстовый узел, матчащий
^\d+[\.\s:]и при отсутствии заданногоcorrect→ ответ{n, text}(фаза →answers); иначе — продолжение последнего ответа. <em>с чистым числом →question.correct = N(только в фазеanswers, чтобы не спутать с «Примечание»); с текстом →question.note = innerHTML(сохранить); пустой/ → шум.<p>приcur === nullи нет вопросов →headerHTML(заголовок раздела сохраняем).- фильтр: оставляем только вопросы с
correct !== null.
Рендер renderQuestion: карточка .whale-q → .whale-q-text (вопрос, textContent, жирный) + .whale-answers с кнопками .whale-a (data-n = номер ответа) + опционально .whale-note.
Click-логика: первый клик блокируется (data-locked). Если n === correct → класс correct (зелёный); иначе класс wrong (красный) и правильный ответ получает correct (чтобы показать верный). Управляется data-correct на карточке.
Инъекция в страницу:
<link rel="stylesheet" href="bilety.css">перед</head><script src="bilety.js" charset="utf-8"></script>перед</body>- мета для дашборда в
<head>:eagle-test-purpose,eagle-test-contains.
Дизайн .whale-a: карточки-кнопки (flex column), #f5f5f5, hover #ececec; .correct=#d4edda/#28a745, .wrong=#f8d7da/#dc3545 (с !important).
Pitfall: локальное открытие file://
Страница Tilda использует sessionStorage для анимации появления .t-records — при открытии локально это работает. Просто открыть bilety.html двойным кликом достаточно для проверки функционала.
Связанное
- Доставка в дашборд — механика Pages:
personal/projects/personal-os/eagle-dashboard.md.