GriffinJS
Опциональный слой виджетов с состоянием: слайдер, галерея, лайтбокс, параллакс, мегаменю. Один файл, одна строка подключения; страница без него — законное и рабочее состояние.
Обзорная страница слоя. Семейство прокрутки — страница «Слайды»: дорожка, слайдер, галерея, лайтбокс, движок fade, — параллакс и семейство выпадающего: мегаменю плюс контроллеры дропдауна и подсказки на странице «Слои поверх страницы», — и окна и комбобокс; закраску ползунка и пару «от — до» слой добавляет форме — «Формы», а сортировку строк — таблице: «Таблицы». Расширенные поля форм — маска, телефон, дата, файл, оценка, одноразовый код, счётчик и сводка ошибок — лежат вторым файлом, «Поля форм»: простой проект за них не платит. Устройство слоя — на странице «Архитектура».
Подключение
Слой лежит внутри пакета griffincss-ui и подключается одной
строкой после стилей. У него свой глобал — window.GriffinJS,
отдельный от window.Griffincss; от рантаймов ядра, компонентов
и утилит он не зависит и работает при подключённом одном CSS.
<link rel="stylesheet" href="griffincss-ui.css">
<link rel="stylesheet" href="griffinjs.css">
<script defer src="griffinjs.js"></script>
defer — потому что до первой отрисовки слою ставить нечего:
разметка до его старта живёт базой без скрипта, а в блокирующем пути
остаются только тема и раскладки («Что
в <head>, что defer»). Стартует слой, когда поставка
зарегистрирована целиком: отложенный тег — на DOMContentLoaded,
после всех defer-тегов, включая griffinjs-fields.js
и griffinjs-countries.js; тег, вставленный скриптом в готовый
документ, — сразу после своего файла. Набор «ядро + нужное», вставляемый
скриптом по одному тегу, поднимают вручную: data-auto="false"
на теге ядра и GriffinJS.start() после последнего модуля.
Атрибут data-auto="false"
отключает автозапуск — как у остальных рантаймов библиотеки;
data-fields и data-countries называют пути
второго бандла, который слой догрузит сам, встретив первое поле
(«Догрузка по потребности»).
Слой поднимает и снимает виджеты сам, по MutationObserver,
и ему всё равно, кто вставил узел. Поэтому пакетов-обёрток под React
и Vue нет и не планируется: их работу делает сканер. Что при этом нужно
знать — оговорки жизненного цикла и готовый хук — на странице
«Griffincss в React и Vue».
Два рода вещей
Документация различает новые виджеты и
контроллеры. У новых виджетов — слайдера, галереи,
лайтбокса, параллакса, мегаменю, комбобокса — своя разметка и свои стили
в griffinjs.css; как компонентов ui их не существует,
и описываются они только в этом разделе. Контроллеры — модалка, панель,
дропдаун, подсказка, ползунок, сортируемая таблица — ничего не меняют
в разметке существующих компонентов:
скрипт добавляет к ним атрибуты и поведение, а описание живёт на странице
компонента в подразделе «С подключённым griffinjs.js».
С griffinjs.js и без
Каждый виджет обязан иметь «базу без JS». Матрица заполняется по мере появления виджетов; сейчас в ней только то, что уже решено планом.
| Виджет | С griffinjs.js | База без JS |
|---|---|---|
| Дорожка | клавиатура, aria-current/inert, --gr-progress, griffin:change | scroll-snap-дорожка |
| Слайдер | точки, кнопки, автоплей с паузой, цикл | scroll-snap-дорожка; органы управления скрыты |
| Галерея | превью ведут дорожку и следуют за ней | две дорожки без синхронизации |
| Лайтбокс | <dialog> + дорожка, группы по атрибуту, видео и iframe | ссылка на большое изображение |
| Параллакс | --gr-progress на любом блоке; рецепты эффектов в CSS | статичный блок (запасное значение в var()) |
| Движок fade | стопка слайдов, переход прозрачностью, следование за пальцем | первый слайд |
| Мегаменю | наведение с задержкой намерения и безопасным треугольником, одна открытая панель, клавиатура disclosure navigation, ajax-панели, закрытие с анимацией темы (closing), аккордеон на узком экране | .gr-navbar + <details> в пунктах .gr-nav: щелчок раскрывает панель, CSS кладёт её под полосу |
| Дропдаун контроллер | роли меню, клавиатура menu button, Esc и щелчок мимо для <details>, закрытие с анимацией темы (closing), позиция popover-панели без anchor positioning, наведение с задержкой | .gr-dropdown как есть: <details>, popover или наведение из ui |
| Окна контроллер | data-gr-open, стек, блокировка прокрутки под окном (и на iOS), остановка видео, ajax-содержимое, hash с кнопкой «Назад», плавный рост окна по grow | .gr-modal / .gr-drawer как есть: showModal() и <form method="dialog"> |
| Комбобокс | роли combobox/listbox, aria-activedescendant, дебаунс, отмена запроса, кеш, группы, подсветка, выбор | обычное поле в форме поиска |
| Ползунок контроллер | доля пройденного пути — след до ручки красит CSS; пара «от — до» держит порядок значений, шлёт griffin:change и параметром fields связывается с числовыми полями | .gr-range как есть: ползунок работает, следа нет (в Firefox есть — его рисует платформа) |
| Сортируемая таблица контроллер | круг aria-sort «нет → по возрастанию → по убыванию», стабильная перестановка строк, числа и ISO-даты числами, остальное — Intl.Collator с локалью документа, клавиатура на заголовке | .gr-table как есть: порядок строк тот, что пришёл с сервера; указатель направления рисуется из aria-sort и без скрипта |
| Подсказка контроллер | верхний слой (popover) по наведению с задержкой и по фокусу, позиция у якоря, Esc | .gr-tooltip-anchor как есть: :hover и :focus-within из ui |
Второй бандл — поля форм (griffinjs-fields.js, в griffinjs.js не входят) | ||
| Маска | формат токенами, литералы, каретка, подсказка и inputmode из формата | <input pattern inputmode> — проверяет платформа |
| Телефон | маска по коду страны, имя и флаг от платформы, полный номер с плюсом выбирает страну; таблица стран отдельным файлом | type="tel" и <select> кодов |
| Дата и время | на указателе мыши — маска по локали, календарь, ISO в спутнике, проверка границ; на тач-устройстве — ничего; пара «с — по» атрибутом to — границы друг друга и отрезок в панели | нативный <input type="date"> |
| Сумма | разряды и дробь по локали на экране, число в спутнике, каретка держится за цифрой, границы через спутник | текстовое поле — сервер получает набранное |
| Файл | список выбранного, удаление по одному через DataTransfer, накопление | <input type="file" multiple> |
| Ввод оценки | --gr-rating и слово в aria-label, наведение, подписи поверх знаков | пять радиокнопок в <fieldset> |
| Одноразовый код | фокус по ячейкам, вставка и автозаполнение раскладываются, griffin:complete | ряд ячеек maxlength="1" |
| Счётчик символов | остаток к maxlength с aria-live, состояния у порога | maxlength действует сам |
| Сводка ошибок | непройденные поля ссылками с сообщениями платформы, фокус на первой, aria-invalid | пузырь браузера |
Модульная сборка
Кроме griffinjs.js целиком в dist/ лежат
griffinjs-core.js, по файлу на общую часть — дорожка
track, анимация motion, жест gesture,
медиазапросы media, позиционирование у якоря anchor —
и по файлу на каждый движок и виджет. В ядре осталось только то, без чего
не обходится ни один виджет; всё остальное подключается после него
и лишь тем, кому нужно. Размеры по модулям — на странице
«Архитектура».
Весь слой одним файлом — 19,2 КБ gzip. Но берут его обычно не целиком: ядро, нужное любому набору, весит 2,8 КБ, а остальное подключается по потребности. Каждый модуль объявляет, что берёт из ядра, и таблица собрана из этих объявлений при сборке — разойтись с кодом ей нечем.
| Виджет | Подключить после griffinjs-core.js | Набор целиком |
|---|---|---|
data-gr-track | griffinjs-motion.js + griffinjs-track.js + griffinjs-scroll.js | 6,6 КБ |
data-gr-slider | griffinjs-motion.js + griffinjs-track.js + griffinjs-scroll.js + griffinjs-slider.js | 7,7 КБ |
data-gr-gallery | griffinjs-motion.js + griffinjs-track.js + griffinjs-scroll.js + griffinjs-slider.js + griffinjs-gallery.js | 8,1 КБ |
data-gr-lightbox | griffinjs-motion.js + griffinjs-track.js + griffinjs-scroll.js + griffinjs-lightbox.js | 7,9 КБ |
data-gr-parallax | griffinjs-motion.js + griffinjs-parallax.js | 3,6 КБ |
data-gr-megamenu | griffinjs-media.js + griffinjs-megamenu.js | 5,0 КБ |
data-gr-dropdown | griffinjs-anchor.js + griffinjs-dropdown.js | 5,0 КБ |
data-gr-tooltip | griffinjs-anchor.js + griffinjs-tooltip.js | 3,9 КБ |
data-gr-dialog | griffinjs-dialog.js | 4,4 КБ |
data-gr-combobox | griffinjs-combobox.js | 5,3 КБ |
data-gr-range | griffinjs-range.js | 3,5 КБ |
data-gr-sortable | griffinjs-sortable.js | 3,6 КБ |
Порядок тегов свободный, кроме одного: griffinjs-core.js идёт
первым — он создаёт window.GriffinJS. Если в наборе чего-то
не хватает, слой скажет об этом в консоли при старте, а не молча
недоработает: GriffinJS: «dropdown» не работает без
griffinjs-anchor.js.
<script src="griffinjs-core.js"></script>
<script src="griffinjs-anchor.js"></script>
<script src="griffinjs-media.js"></script>
<script src="griffinjs-dropdown.js"></script>
<script src="griffinjs-megamenu.js"></script>
Полигон
Страница-полигон собирает все виджеты слоя
на одном экране. Её проверяют браузерные тесты на трёх движках — и второй
раз с отключённым скриптом: каждый пример без бейджа «нужен
griffinjs.js» обязан работать и так.