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

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

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

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

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

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

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

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

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

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

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

Буду рад, если кому-нибудь пригодится. Если кто-нибудь видел что-то подобное или лучше, пожалуйста, напишите в комментариях.
+34
8 мая 2010, 10:19
26
lany 114,5

комментарии (43)

+1
G0ran #
Если честно вообще не встречал, хотя пользуюсь немного веб-интерфейсом для почты

А проблема на самом деле есть такая. Помню долго чистил ящик от всякой рекламы и спама, когда не заходил на него, а интернет еще был лимитный.

Так что здорово у вас сделано, а можно ссылку на пример тестовый если конечно есть. Вообще идея классная
0
lany #
> Так что здорово у вас сделано, а можно ссылку на пример тестовый если конечно есть.

К сожалению, я реализовывал это в программе, которая писалась под заказ не для широкого использования, так что показать не могу.
0
dimag0g #
Фраза «Буду рад, если кому-нибудь пригодится» слега вводит в заблуждение относительно открытости решения.
0
lany #
Идею отдаю нахаляву, а конкретную реализацию в конкретном продукте — нет.
+3
xaja #
идея то может и хорошая, но каждый день наблюдать эти строки сверху и снизу, для того чтобы иметь возможность раз в год ответить ВСЕ :\
0
Rumickon #
Как вариант, можно скрывать эти строки, пока пользователь не поставит хотя бы одну галку на текущей странице.
0
G0ran #
или просто при наведении на какое-то поле красиво выезжает менюшка, такое сделать несложно
+3
chetzof #
и сбоку взрывается вертолёт!
–1
ognevsky #
и все начинают грабить корованы:)
0
lany #
У меня, как у автора, глаз, конечно, замылен, но не отвлекают. На экране обычно гораздо больше пикселей используются неоптимально, например, для показа рекламы :-) Ну и часто присутствуют кнопочки, которыми вообще никогда не пользуешься. Ну осторожные люди могут разрешить пользователю отключать фичу в настройках учётной записи.
0
hardex #
С первого раза не понял, где GMail, а где ваш пример О_о
0
JerryJJ #
Строки с числом «предыдущих» и «последущих» сообщений работают согласовано или независимо друг от друга? Если я воставлю флажок в верхней строке, то будут ли выделены сообщения на «последующих» страницах?
0
G0ran #
незнаю как у автора данной системы, но по идее не должны, ведь чтобы выделить на последующих страницах — внизу флажок (+ сообщения на послед. страницах)… или вы про другое?
0
Rumickon #
К.О. шепнул мне на ухо, что строки эти работают независимо. Думаю, ему можно верить.
0
lany #
Независимо работают.
+1
bigdogsru #
Зачем обрабатывать то, что не видишь? Есть гарантия, что среди 2711 писем на остальных страницах спама нет случайно попавшего туда одного нужного? А то и десятка? И тем более — зачем инвертировать то, что не видишь?
0
LIAL #
Полностью согласен. Хотя реализация автора интересна и считаю что как идею использовать можно, только вот специфику поведения нужно каждому реализовывать под его потребности (Одному может список писем нужен, другому спиок задач и т.п.)
0
G0ran #
нужно просто продумать более гибкий выбор писем
например чтобы можно было выделить все письма от одного источника. Это можно сделать например отсортировав, но писем от него может быть много и не на одну страницу. Или например, мне нужно оставить все письма от нескольких источников (их тоже много), а остальное удалить

там функционал можно наращивать и наращивать, главное не переборщить, всё-таки пользоваться этим будут обычные пользователи, нужно соблюсти баланс
+2
xn__p2a #
Зачем обрабатывать то, что не видишь?
Позвольте пользователю самому решать, чего он хочет. Если он хочет выделить всё, даже не видя этого, то пускай он сможет это сделать. Исходите из того, что пользователь разумен и принимает обдуманные решения.

А то, например, для администрирования корпоративного антивируса Symantec Endpoint Protection разработчики консоли администрирования мало того, что разбили список компьютеров по страницам, так ещё и алфавитная сортировка работает только в пределах одной текущей страницы. Вот что рандомно попало на текущую страницу — только эти пункты и будут выстраиваться по алфавиту, без учёта всех остальных страниц.
Они, видимо, тоже руководствовались принципом «Зачем обрабатывать то, что не видишь?», в итоге получился убогий и неудобный интерфейс.
0
Zyava #
Примерно такие же веселые ребята писали VirtueMart. В админке при просмотре списка продуктов они забили в коде сортировку продуктов по дате добавления, хочешь по имени продукта или по SKU отсортировать — а вот фиг тебе. :)
+1
softwareteam #
Молодец, хорошо придумал.
Можно в первой и последней строках показывать информацию об отмеченных пользователем там записях (+ 25 записей на предыдущей страницы (выбрано вами 7)). Таким образом можно листать список, делать выделение и применять к выделенным записям какое-то действие.
0
Zyava #
Я думал оно так и показывает. Иначе какой особый смысл показывать сколько спереди писем а сколько сзади? Подписать выбрать все письма спереди и выбрать все сзади, от циферок большой пользы нет если все равно выберутся все (25 или 1000, какая разница, выбрались все до текущего или после текущего).
0
AirLight #
эх, детсад, проще панельку сделать, в которой сразу команды и диапазоны:

del 1-5, 7, 9, 25-…
+2
lany #
Зачем? Просто SQL-консоль вместо сайта =)
0
AirLight #
а сниппеты?
0
allter #
Кстати, шутки шутками, а одна из вещей, которая мне нравится в issue-трекере «Request Tracker» — это возможность гибкого сочинения поисковых запросов и их сохранения на будущее.

Было бы здорово, если бы больше продуктов могли использовать SQL/SPARQL для запросов внутри себя.
0
ibnteo #
Если уж выделять то чего не видно, можно сделать галку «выделить всё», при нажатии которой все остальные выделяются и блокируются.
0
13i #
+25 на предыдущей хорошо бы вниз сместить.
0
Zyava #
Зачем?
0
13i #
В смысле, объединить весь блок выделения страниц, либо снизу, либо сверху, чтобы не разделять схожие по идее элементы — +25 и +2662
0
lany #
Это менее интуитивно. В моём варианте галочки расположены в хронологическом порядке: +25 на предыдущей странице — это более новые сообщения, и их галочка идёт сверху, так как сортировка по дате. Если я хочу пометить все сообщения от определённой даты и новее, я выделю одним диапазоном с помощью шифта. Если галочку перенести вниз, диапазон будет разорван.
0
13i #
понял. не сразу понятно, что +25 не относятся к первой странице
0
Xpeh #
>Непонятна поддержка таких возможностей как «выбрать прочитанные письма». Видимо, это по-прежнему будет работать в рамках текущей страницы, что не очень удобно.

А почему бы не задействовать третье состояние переключателей? Будет показывать, что на предыдущих/следующих страницах выбраны некоторые, а не все элементы.
–1
Sho #
А почему у вас в спаме нет писем про виагру? Поделитесь секретом.
0
lany #
Да вроде попадались. Просто другого спама больше :-)
0
Dmitry_f #
А разве сейчас сложно реализовать обычный десктопный мультиселект в вебе? Ну там, где ctrl+клик, shift+click?
Вообще, идея кажется очень удобной
0
egorinsk #
Отличное решение.
0
lublushokolad #
Хорошее решение, почему мне не пришло :)

Но, думаю, оно решает следствие — ограниченный обзор.
А причина, корень зла, это паджинация. Скоро она везде умрет.

И ей на смену придет кнопка «показать ещё...», как в твиттере, а потом и в фейсбуке (могу ошибаться в хронологии) и очень большие мониторы. Колесико у всех уже есть наверное?

PS. вместо троеточия в кнопке должен быть связанный с направлением сортировки и атрибутом сортировки текст.
например «показать ещё более старый спам» ;)

0
lany #
Интересно, что не так давно на ютюбе так показывались комментарии через «показать ещё», но потом они вернулись назад к страничкам.
0
lublushokolad #
привычка победила…

а может быть дизайнеры :) им нравится блоки фиксированных размеров
я лично знаю 4 дизайнеров, которые испытывают бессознательный страх к скроллбару на странице
(блоки с overflow:scroll переносят с трудом, как необходимое зло)

0
cbx #
Скажите, а как вы решаете проблему «гонок»? Например, пользователь выбрал удаление всех записей (особенно если их несколько страниц) и нажал кнопку подтверждения, а в это время свалилось ещё одно сообщение. Система его тоже удалит?
0
lany #
Собственно, в статье это написано, где «минусы», второй пункт. Я думаю, логичней удалять то, что было на момент загрузки списка на клиента, но это может зависеть от задачи. У нас такой проблемы не стояло, потому что ввиду специфики задачи при любых изменениях списка создавалась копия (вроде как в системах контроля версий). Поэтому пользователь мог быть спокоен, что за время манипуляций с галочками ничего добавлено или удалено не будет.
0
cbx #
Ой, пардон, плюсы прочитал а минусы как-то пропустил :)

Наверное можно что-то придумать, например кроме списка строк текущей страницы передавать клиенту также номер самой первой и самой последней записи или timestamp если таковой имеется. Ну а после сабмита формы уже атомарно одним запросом к базе (с соответствующими условиями на максимум/минимум или время) удалять нужные строки.

Надо посмотреть чего GMail при подобных операциях на сервер шлёт…

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.