oscript-ui
oscript-ui

Пагинация

Пагинация делит длинный список на страницы: «Назад» слева, «Вперёд» справа, между ними — где человек сейчас. Адреса страниц собирает сам компонент из основы списка и параметров отбора, поэтому поиск и фильтр не теряются при переходе.

Когда использовать#

  • Список длиннее, чем разумно отдать одним ответом: журнал, документы, участники.
  • Порядок записей устойчив, и «страница 3» означает одно и то же при повторном заходе.
  • Список отфильтрован, и отбор должен пережить переход на следующую страницу.

Не берите пагинацию для разделов одного объекта — для этого есть вкладки и дерево разделов. Если записей нет вовсе, покажите пустое состояние, а не навигацию по нулю страниц.

Число страниц известно#

Задайте Страница, ВсегоСтраниц и Основа — путь списка. Посередине стоит «Страница 3 из 7», по краям — шаги в виде кнопок Material с обводкой.

Середина списка

HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ВсегоСтраниц, Основа", 3, 7, "/документы"));

В дереве холста пагинация собирается словами: основа, страница и число страниц позицией, отбор и подписи шагов — словами (см. Язык узлов).

Узлом холста — словами

HTML = Кит.Пагинация("/документы", 2, 4).Параметры("q", "отчёт").Рендер();

На краях списка лишний шаг не печатается: с первой страницы назад идти некуда, с последней — вперёд.

Первая страница — без «Назад»

HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ВсегоСтраниц, Основа", 1, 7, "/документы"));

Последняя страница — без «Вперёд»

HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ВсегоСтраниц, Основа", 7, 7, "/документы"));

Номер вне диапазона компонент поправляет сам: «страница 0» станет первой, «страница 40 из 7» — седьмой.

Одна страница — навигации нет вовсе: переходить некуда.

Одна страница — навигации нет

этот вызов не печатает ничего

HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ВсегоСтраниц, Основа", 1, 1, "/документы"));

Сколько записей: «41–60 из 137»#

Знаете, сколько записей в списке после отбора, — скажите словами Всего и НаСтранице (размер страницы). Рядом с номером страницы встанет диапазон: какие записи на экране и сколько их всего. Число страниц кит посчитает сам, если его не передали позицией; последняя страница кончается последней записью, а не полной страницей. Текст диапазона — ключ словаря pagination.of (%1–%2 из %3).

Диапазон записей

HTML = Кит.Пагинация("/проекты", 3).Всего(137).НаСтранице(20).Рендер();

Последняя страница — до последней записи

HTML = Кит.Пагинация("/проекты", 7).Всего(137).НаСтранице(20).Рендер();

Одного числа мало: без размера страницы диапазон не посчитать, и он не печатается. Все записи на одной странице — навигации нет, как и прежде.

Без перезагрузки#

Слово БезПерезагрузки() делает ссылки страниц тихими: у каждой — признак data-quiet, тот же, что у тихой формы. Скрипт кита берёт страницу запросом в фоне и кладёт ответ на место: список меняется, а прокрутка и фокус остаются. Адрес вкладки уходит в её историю, поэтому «Назад» браузера возвращает прежнюю страницу — тоже без перезагрузки и на ту же прокрутку. Номер страницы объявлен живой областью (aria-live="polite"): скринридер прочтёт «Страница 2 из 7» сам.

Тихие ссылки страниц

HTML = Кит.Пагинация("/проекты", 2).Всего(137).НаСтранице(20) .Параметры("q", "бета").БезПерезагрузки().Рендер();

Сервер ничего нового не учит: он отвечает на адрес страницы тем же, чем ответил бы браузеру, — всей страницей списка. Без скрипта это обычные ссылки. Вместе со строкой поиска и сортировкой колонки пагинация собирает список, который листается и отбирается на месте, — живой образец с сервером: список проектов.

Отбор переживает переход#

Параметры — пары Имя, Значение, которые войдут в адрес каждой страницы. Значения кодируются для URL, пустые пары пропускаются. Без этого вторая страница поиска показала бы весь список.

С сохранением отбора

Отбор = Новый Массив(); Отбор.Добавить(Новый Структура("Имя, Значение", "q", "отчёт")); HTML = Набор.Пагинация().Отрисовать( Новый Структура("Страница, ВсегоСтраниц, Основа, Параметры", 2, 4, "/документы", Отбор));

Имя параметра страницы по умолчанию — page. Если список уже занял это имя, задайте своё полем Параметр. Подписи шагов меняются полями ПодписьНазад и ПодписьВперёд.

Свой параметр и подписи шагов

HTML = Набор.Пагинация().Отрисовать( Новый Структура("Страница, ВсегоСтраниц, Основа, Параметр, ПодписьНазад, ПодписьВперёд", 2, 5, "/журнал", "p", "Раньше", "Позже"));

Адрес страницы нужен и вне пагинации — ссылка «К первой странице» после смены отбора, переход после сохранения. Кит.АдресСтраницы(Основа, Номер, Параметр, Параметры) собирает его тем же правилом, что ссылки пагинации (дев-сборка 10; прежний вход — Пагинация.АдресСтраницы).

Ссылка на первую страницу с тем же отбором

Отбор = Новый Массив(); Отбор.Добавить(Новый Структура("Имя, Значение", "q", "отчёт")); HTML = Кит.Примечание(Кит.Ссылка(Кит.АдресСтраницы("/журнал", 1, "p", Отбор), "К первой странице")).Рендер();

Число страниц неизвестно#

Сосчитать строки бывает дороже, чем их показать. Тогда вместо ВсегоСтраниц передайте ЕстьСледующая: выбрали на одну запись больше, чем помещается, — значит, дальше есть. Посередине печатается только номер страницы, без «из».

Число страниц неизвестно, дальше есть

HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ЕстьСледующая, Основа", 1, Истина, "/настройки/журнал"));

«Назад» печатается по номеру текущей страницы: с третьей страницы вернуться можно, даже если дальше пусто.

Число страниц неизвестно, дальше пусто

HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ЕстьСледующая, Основа", 3, Ложь, "/настройки/журнал"));

Основа обязательна#

Без Основы ссылки страниц вели бы относительно текущего адреса, а с опасной схемой (javascript:) — исполняли бы код. Компонент отказывает в обоих случаях, и проверка стоит раньше всего остального: забытая основа всплывёт и на коротком списке из одной страницы.

Пустая основа — исключение с объяснением

Попытка HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ВсегоСтраниц", 1, 1)); Исключение HTML = Набор.Тост().Отрисовать(Новый Структура("Текст, Вид", ИнформацияОбОшибке().Описание, "ошибка")); КонецПопытки;

Гайдлайны#

ДелайтеШаги подписаны словами, стрелки рисует кит
Код
HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ВсегоСтраниц, Основа",
	2, 5, "/документы"));
Не делайтеСтрелки в подписях: значок стоит дважды, а слова нет
Код
HTML = Набор.Пагинация().Отрисовать(
	Новый Структура("Страница, ВсегоСтраниц, Основа, ПодписьНазад, ПодписьВперёд",
		2, 5, "/документы", "←", "→"));
ДелайтеЧисло страниц не знаете — так и скажите: ЕстьСледующая
Код
HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ЕстьСледующая, Основа",
	1, Истина, "/журнал"));
Не делайтеВыдуманное «из 999»: обещание, которое список не сдержит
Код
HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ВсегоСтраниц, Основа",
	1, 999, "/журнал"));
ДелайтеОтбор передан в Параметры — вторая страница того же поиска
Код
Отбор = Новый Массив();
Отбор.Добавить(Новый Структура("Имя, Значение", "q", "отчёт"));
HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ВсегоСтраниц, Основа, Параметры",
	1, 3, "/документы", Отбор));
Не делайтеОтбор вклеен в Основу руками: значение не кодируется, а отбор живёт в двух местах
Код
HTML = Набор.Пагинация().Отрисовать(Новый Структура("Страница, ВсегоСтраниц, Основа",
	1, 3, "/документы?q=отчёт"));

Доступность#

  • Навигация печатается <nav> с aria-label «Постраничная навигация»; своё имя — поле Заголовок.
  • Шаги — ссылки с rel="prev" и rel="next": браузер и поисковик понимают, что это соседние страницы одного списка.
  • Состояние «Страница 3 из 7» напечатано текстом, а не только видом шагов. Стрелки-значки декоративны: имя шага — его подпись.
  • Шаг, которого нет, не печатается вовсе, а не блокируется: мёртвой ссылки клавиатура не встретит.
  • Со словом БезПерезагрузки состояние «Страница 3 из 7» — живая область (aria-live="polite"): страница сменилась без перезагрузки, и скринридер скажет об этом сам. Фокус остаётся на нажатом шаге.
  • Диапазон «41–60 из 137» напечатан текстом рядом с состоянием; живой областью он не объявлен, чтобы скринридер не читал смену дважды.

Узлом холста#

На холсте пагинация — узел рода «страницы». Ставьте его сразу под таблицей списка.

Пагинация узлом дерева

HTML = Кит.Пагинация("/документы", 2, 5).Рендер();

Модель#

Структура ниже — прежний вид модели; в дереве холста её поля пишут слова Кит.Пагинация, а пара отбора — словом Параметры(Имя, Значение). Слова выпуска 0.13 — Всего(Число), НаСтранице(Число) и БезПерезагрузки() — пишут одноимённые поля.

Пагинация.Отрисовать()src/Классы/компоненты/Пагинация.os

Отрисовывает постраничную навигацию.

Параметры:
 Модель - Структура - Страница (текущая, с 1), ВсегоСтраниц, ЕстьСледующая (Булево —
          для списков, где число страниц неизвестно: за ним нет счёта строк), Основа
          (базовый путь списка, ОБЯЗАТЕЛЕН), Параметр (имя параметра страницы, "page"),
          Параметры (массив структур Имя, Значение — переживают переход), ПодписьНазад,
          ПодписьВперёд, Заголовок (aria-label). Выпуск 0.13: Всего (сколько записей
          в списке) и НаСтранице (сколько их на странице) — вместе печатают «41–60 из 137»
          текстом словаря «pagination.of» и, если ВсегоСтраниц не задано, считают его;
          БезПерезагрузки (Булево) — ссылки страниц уходят тихо (data-quiet), а состояние
          читается скринридером при смене (aria-live).

Возвращаемое значение:
 Строка - фрагмент <nav class="pagination"> либо "" при единственной странице. Кидается
          исключением, если Основа пуста или её схема недопустима.

Кит.Пагинация()src/Классы/холст/Кит.os

Постраничная навигация длинного списка. Слова: ЕстьСледующая, Параметр, Параметры(Имя,
Значение), ПодписьНазад, ПодписьВперёд, Заголовок; выпуск 0.13 — Всего(Число записей)
и НаСтранице(Число) печатают «41–60 из 137», БезПерезагрузки — ссылки страниц тихие.

Параметры:
 Модель       - Строка, Структура - базовый путь списка (Основа); Структура — прежний
                вид модели.
 Страница     - Число - (необязательный) текущая страница, с 1.
 ВсегоСтраниц - Число - (необязательный) сколько страниц; 0 — неизвестно.

Возвращаемое значение:
 ЭлементЭкрана

Адрес любой страницы списка собирается той же функцией, что и шаги, — пригодится для ссылки «к первой странице» после удаления записи.

Кит.АдресСтраницы()src/Классы/холст/Кит.os

Адрес страницы списка — тем же правилом, что ссылки пагинации: основа, сохраняемые
параметры (URL-кодируются) и параметр страницы; основа с запросом продолжается через «&».

Параметры:
 Основа    - Строка - базовый путь списка.
 Номер     - Число - номер страницы, с 1.
 Параметр  - Строка - (необязательный, по умолчанию "page") имя параметра страницы.
 Параметры - Массив из Структура, Неопределено - (необязательный) сохраняемые параметры:
             Имя, Значение; пустые не печатаются.

Возвращаемое значение:
 Строка - относительный URL.

Пагинация.АдресСтраницы()src/Классы/компоненты/Пагинация.os

Собирает адрес страницы: основа, сохраняемые параметры и параметр страницы.
Значения параметров URL-кодируются.

Параметры:
 Модель - Структура - модель пагинации, см. Отрисовать.
 Номер  - Число     - номер страницы.

Возвращаемое значение:
 Строка - относительный URL.

ЭлементЭкрана.Всего()src/Классы/холст/ЭлементЭкрана.os

Сколько записей в списке пагинации. Вместе со словом НаСтранице печатает «41–60 из 137»
и считает число страниц, если оно не задано позицией.

Параметры:
 Число_ - Число - число записей списка (после отбора).

Возвращаемое значение:
 ЭлементЭкрана - этот же элемент.

ЭлементЭкрана.НаСтранице()src/Классы/холст/ЭлементЭкрана.os

Сколько записей на одной странице пагинации — размер страницы.

Параметры:
 Число_ - Число - размер страницы.

Возвращаемое значение:
 ЭлементЭкрана - этот же элемент.

ЭлементЭкрана.БезПерезагрузки()src/Классы/холст/ЭлементЭкрана.os

Форма уходит без перезагрузки страницы: скрипт кита отправляет её запросом в фоне
и кладёт ответ сервера на страницу на место — прокрутка, фокус и раскрытые раскрывашки
остаются как были. Сервер отвечает тем же, что и браузеру (обычно перенаправлением
обратно на страницу), а без скрипта форма отправляется обычной навигацией.

Не для формы, которая отдаёт файл или уводит на чужой сайт (вход через провайдера):
такому ответу место во вкладке, а не на текущей странице.

Выпуск 0.13: у пагинации тихо уходят ссылки страниц, у строки поиска и формы отбора —
GET-форма (и сама, по изменению поля, с задержкой), у таблицы — ссылки сортировки в
заголовках колонок. Адрес вкладки меняется в её истории, и «Назад» возвращает прежнее.

Возвращаемое значение:
 ЭлементЭкрана - этот же элемент.