Pull to refresh

Выделение строк в многостраничных списках на веб

Reading time4 min
Views2.3K
На веб-сайтах нередко встречаются списки и таблицы, разбитые на много страниц с возможностью перехода между ними. Иногда над строками таких списков можно выполнять какие-то операции. Вот несколько примеров:
  • Модерация веб-форума: массовый перенос, блокировка, удаление тем.
  • Почтовый клиент: отметить выделенные письма как (не)прочитанные, добавить метку, перенести в спам.
  • Система обработки научных данных: выделить интересующие строки в подмножество, пометить цветом, как заслуживающие внимания.
Во всех этих случаях проблемы с юзабилити возникают, когда страниц больше одной. Можно ли выделить все строки списка, а не только текущую страницу? А все без одной? Правильно инвертировать выделение? Выделить все строки от 1245-й и до конца, при том, что на одной странице всего 100 строк, а всего строк в списке 5000?

Я придумал простую штуку, которая позволяет решить все эти эти задачи. Она внедрена в одном коммерческом веб-приложении и хорошо себя зарекомендовала. Не видел более удобного решения, поэтому представляю на суд общественности.

Для начала пара существующих решений. Вот GMail (на примере папки со спамом):

Можно выбрать текущую страницу, и GMail выкручивается, показывая надпись «выбрать все цепочки»:

Теперь, если я сниму одну галочку, что будет выбрано, 2735 сообщений или только 24 на текущей странице? Я уже не уверен, и это нигде не написано. По факту получается 24, то есть удалить все кроме одного становится нетривиальной задачей. Если же я снял одну галочку и снова поставил, я как будто бы вернул всё как было, но в действительности стала выделена только текущая страница, причём мне уже не предлагают выделить всё. Возможности инвертировать выделение не предусмотрено вообще.

По-другому выкручивается старенький phpBB:

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

Моё решение выглядит так:

Если страница не первая, над списком появляется дополнительная галочка «+ X записей на предыдущих страницах». Если страница не последняя, под списком появляется галочка «+ Y записей на последующих страницах». Имеются отдельные кнопки «выделить страницу» (без этих двух галочек) и «выделить всё». Если список занимает одну страницу, кнопка «выделить страницу» исчезает.

Я вижу следующие плюсы:
  • В отличие от GMail всегда понятно, какие конкретно строки выделены, включая строки на других страницах.
  • Снятие и возврат любой галочки приводят выделение в прежнее состояние.
  • Легко и интуитивно выделить всё, снять выделение с пары строк и применить действие ко всем строкам кроме этой пары. Также легко применить действие только ко всем строкам данной страницы кроме нескольких. Нет необходимости в кнопках «выполнить для всех строк кроме выделенных».
  • Кнопка «инвертировать» просто переключает состояние всех галочек и при этом действительно правильно инвертирует выделение во всём списке.
  • Можно выполнять действия над строками «от начала списка и до данной» или «от данной и до конца списка» вне зависимости от расположения данной строчки. Выделять такие диапазоны легко и интуитивно с помощью shift, захватывая одну из новых галочек. Разумеется, такой диапазон тоже правильно инвертируется.
  • Новые галочки наряду с переключателем страниц дополнительно сигнализируют о том, является ли данная страница первой или последней. Это удобно и уменьшает количество ошибочных действий.
Как всегда, не обошлось и без минусов:
  • Дополнительная сложность реализации. Если обычные галочки могут ссылаться на уникальный идентификатор строки, то установка новых либо должна передать серверу идентификаторы всех строк на других страницах, либо сервер должен уметь восстановить, какие записи идут на следующих страницах. Если список можно по-разному сортировать и фильтровать, это тоже нужно учесть.
  • Трудности могут возникнуть, если список мог измениться в процессе работы. Скажем, на приведённом примере пришло новое письмо, а я поставил галочку «+25 на предыдущих страницах» и нажал «удалить». Нужно ли действие применить и к новому письму тоже, то есть фактически +26? Это может зависеть от семантики списка. Если нет, то сервер должен уметь восстановить список в том же виде, который был на момент загрузки страницы. Хранить порядок строк в сессии? Если пользователь в рамках одной сессии в разных окнах в разное время открыл список? Выдавать уникальный идентификатор и хранить все эти списки? В общем, кое-какие трудности имеются.
  • Непонятна поддержка таких возможностей как «выбрать прочитанные письма». Видимо, это по-прежнему будет работать в рамках текущей страницы, что не очень удобно.
В нашем приложении было проще, так как однажды созданный список не мог измениться, любые изменения создавали новую копию. Поэтому при совершении действия со списком передавались текущие параметры сортировки и фильтрации, и сервер мог точно восстановить порядок строк. Последней проблемы у нас тоже не стояло.

Буду рад, если кому-нибудь пригодится. Если кто-нибудь видел что-то подобное или лучше, пожалуйста, напишите в комментариях.
Tags:
Hubs:
Total votes 54: ↑44 and ↓10+34
Comments43

Articles