Pull to refresh
58.82
Rating
Netcracker
Технологическое перерождение телеком разработки

Web без мышки

Netcracker corporate blogUsabilityAccessibility
Наверное, все при взгляде на этот экран мысленно переносят обе руки на клавиатуру. Да, тут можно было навигироваться без мышки и это было быстро и хорошо! Многие до сих пор используют подобные менеджеры (Total commander, Far etc).

С другой стороны, почти на всех современных сайтах, порталах и решениях, построенных для веба, пользователь вынужден постоянно отрывать руки от клавиатуры, целиться мышкой в кнопку/иконку/поле, а затем опять возвращать руки на клавиатуру для ввода текста.

Как же достичь удобства навигации без мышки в вебе?


Большая часть продуктов, которые разрабатывает и внедряет наша компания, выходит на конечного пользователя. Операторы колл-центров, инженеры, менеджеры – все они работают с пользовательским интерфейсом «для внутреннего использования» – B2B интерфейсами. Возможность работы с системой с клавиатуры без использования мыши – важное требование в B2B интерфейсах. Почему?

  • В первую очередь – скорость работы. Пользователю не нужно изменять положение рук и переключаться на мышку, напротив, у него есть мгновенный доступ к функциям.
  • Пользователю сложнее сделать ошибку (нужно целиться в кнопку, а не в пиксель).
  • Поддержка людей с ограниченными возможностями.
  • Снижение нагрузки на глаза (многие функции можно выполнять вообще не смотря на монитор).


Такая навигация может выглядеть не «секси» и требовать больше времени на обучение, но бонусы от использования значительно превышают эти минусы.

Итак, задача


Есть большое количество web-based пользовательских интерфейсов. Необходимо:
  • с минимумом усилий позволить использовать весь функционал наших решений без мыши
  • иметь возможность быстро адаптировать любые новые страницы для использования без мыши
  • иметь возможность тонкой настройки навигации по АРМам для увеличения эффективности работы всех пользователей
  • все это с минимальным воздействием на существующий код


Анализируем


Существует четыре основных подхода к навигации клавиатурой, рассмотрим их:
  • табуляция (tab)
  • хоткеи (hotkeys)
  • пространственная навигация (spatial)
  • каретка (caret)


Табуляция

Табуляция — переход между элементами интерфейса с помощью клавиши tab (shift+tab).

  • + поддержка по умолчанию во всех популярных браузерах
  • − всего два направления (+shift)
  • − ограниченные возможности конфигурации (ring)...


Горячие клавиши

Горячие клавиши (в просторечии хоткеи) — сочетание клавиш, которое вызывает определённую функцию. Это позволяет упростить доступ к основным функциям системы. Всё больше сайтов начинают использовать хоткеи на свои страницах для доступа к самым востребованным функциям, среди них: Habrahabr, яндекс, гугл почта и другие. Но что делать, если функций много, и на каждой странице разные? Просто невозможно будет запомнить все хоткеи, а значит, использование не будет эффективным. Так же есть проблема контекста: когда на странице несколько таблиц и несколько кнопок save, например.

  • + мгновенный вызов любой функции
  • − требует обучения (запоминания сочетаний клавиш)
  • − при большом количестве функций сложно запомнить сочетания (особенно если несколько страниц как у нас)

Пример реализации: расширения для Firefox используют подход с hotkeys, очень распространены в десктоп приложениях (пример — аутлук).
  • + не нужно менять существующий код
  • − только браузер Firefox
  • − несколько кнопок save
  • − никакой семантики, такие хоткеи сложно запомнить
  • − на разных страницах одни и те же действия могут иметь разные хоткеи


Пространственная навигация

Когда элементы на веб страницах стали позиционировать с помощью css, навигация табом перестала справляться со своей задачей: курсор перескакивал по элементам дизайна в порядке их объявления в html документе, а не в том, в каком их видит пользователь. Тогда некоторые браузеры (Firefox, Opera) реализовали пространственную навигацию. Они позволяли пользователям использовать сочетания shift+стрелки для перемещения между элементами дизайна, причём следующий элемент определялся исходя из его фактического расположения на экране.

  • + позволяет навигироваться по незнакомому интерфейсу
  • + поддержка OOB в некоторых браузерах
  • − поддержка не во всех браузерах
  • − там, где поддержка есть, она включается опционально
  • − нет стандарта сочетаний клавиш для переходов


Перемещение каретки

Особенность этого подхода в том, что курсор пользователя перемещается не только по элементам форм и ссылкам, а по всему содержимому страницы (как в ворде). Перемещаться можно, как и в пространственном подходе, в четырёх направлениях.

  • + позволяет выделять, копировать фрагменты текста
  • − сфокусирован на контенте, а не элементах управления
  • − медленнее, чем пространственная навигация


Вышеприведенные решения as is нам не подходят из-за отсутствия поддержки во всех браузерах, в них отсутствует возможность тонкой настройки для конкретных страниц, а также хотелось бы, чтобы и хоткеи и пространственная навигация настраивались единообразно в одном месте.

Представляем Mouseless




Ключевыми особенностями Mouseless являются:

  • простая конфигурация для всех страниц приложения, используя CSS селекторы
  • работа во всех браузерах
  • возможность тонкой настройки
  • не конфликтует с существующими решениями
  • хоткеи и пространственная навигация в одном флаконе


Принцип работы Mouseless

Страница делится на блоки с помощью привычных CSS селекторов. Блоки могут иметь дочерние блоки. Внутри каждого блока определяется свой набор хоткеев (JSON объект). Хоткеи могут наследоваться внутренними блоками, т.е. у хоткеев появляется область видимости, которым можно управлять (например, хоткей для сохранения один и тот же в разных блоках, но работает по-разному в зависимости от текущего блока).


На рисунке показано разделение на блоки и подблоки.

Конфигурация каждого блока представляет из себя json объект, json объекты для всех блоков образуют конфигурацию страницы.

Пространственная навигация в данном случае является частным случаем хоткеев. Сводим к минимуму кол-во обязательных параметров конфигурации, базовая поддержка должна быть доступна с минимумом действий. Простейшая конфигурация:
new MouselessBlock({  //объявление блока
	selector: "#blockId", // селектор задаёт границы блока
	childSelector: “a”, // селектор определяет элементы на которые будет перемещаться фокус
	keys: [ // массив хранит все хоткеи, используемые в данном блоке
		new MouselessAction({key: ncKey.KEY_LEFT, action: ncKey.gotoPrevElem }), //по нажатию на клавишу влево выполнить переход на предыдущий элемент
		new MouselessAction({key: ncKey.KEY_RIGHT, action: ncKey.gotoNextElem })
	]
});

Внутри блока #blockId можно перемещать фокус между ссылками клавишами влево и вправо. gotoPrevElem/gotoNextElem служебные функции, можно так же использовать свои кастомные функции.

На реальных кейсах расширяем базовую библиотеку:

  • кольца. Чтобы навигироваться по списку вновь и вновь по кругу, нужно в блок добавить параметр ring: true
  • элементы блока, получающие фокус по умолчанию: возможность указать элемент, который первым получает фокус при попадании в блок defaultChildIndex:2
  • поддержка пользовательских функций: можно установить свою собственную функцию, которая будет вызвана по нажатию клавиш. new MouselessAction({key: ncKey.KEY_LEFT, action: customFunction })
  • работа с диалоговыми окнами (попапами): модальные окна работают в отдельном контексте, их конфигурация осуществляется независимо от основной
    ncKey.addBaseConf(parentSelector, blocks); //добавление блоков в основную конфигурацию
    ncKey.addCustomConf(parentSelector, blocks); //добавление блоков в конфигурацию динамически подключаемых модальных блоков
    //parentSelector - селектор родительского блока, если "" - добавление в корень конфигурации.
    //blocks - массив блоков для добавления
    
  • сохранение/восстановление фокуса применяется в основном совместно с модальными окнами для приведения фокуса в состояние до открытия окна
    var curFocus = ncKey.saveFocus(); 
    …
    ncKey.restoreFocus(curFocus);
    
  • наследование ncKeyAction'ов, поддержка глобальных хоткеев: например, на странице есть несколько таблиц, у каждой кнопка save. Хотим, чтобы в любой ячейке таблицы можно было выполнить сохранение по хоткею (частный случай — глобальные хоткеи). Т.е. ncKeyAction, назначенные в родительском блоке, будут работать во всех дочерних:
    ncKey.addCustomConf("", [new MouselessBlock({//блок, описывающий попап
            selector:"#popup-window",
            childSelector: ncKey.FOCUSABLE_SELECTOR,
            keys: [new MouselessAction({key: ncKey.KEY_ESCAPE,  action: closePopup}), 
                   new MouselessAction({key: ncKey.KEY_S,  action: saveAndClosePopup})
            ],
            childBlocks: [new MouselessBlock({ //дочерний блок с контентом
                    selector:"#popup-window .body",
                    childSelector: ncKey.FOCUSABLE_SELECTOR,
                    ring: false,
                    keys: [...]
                }),
                new MouselessBlock({ //дочерний блок с кнопками
                    selector:"#popup-window .btns",
                    childSelector: ncKey.FOCUSABLE_SELECTOR,
                    ring: false,
                    keys: [...]
               })
    		]
    	})
    ]);
    

    Закрытие попапа с сохранением и без будет работать во всех блоках.


Конфигурация блока на примере NavigationTree (раскрывающее дерево):
new MouselessBlock({ 
selector: "#navigationTree",
childSelector: "li > a:visible",
ring: true,
keys: [ new MouselessAction({key: ncKey.KEY_LEFT, action: ncKey.gotoPrevBlock, ctrl: true}),
           new MouselessAction({key: ncKey.KEY_RIGHT, action: ncKey.gotoNextBlock, ctrl: true}),
           new MouselessAction({key: ncKey.KEY_UP, action: ncKey.gotoPrevElem, ctrl: false}),
           new MouselessAction({key: ncKey.KEY_DOWN, action: ncKey.gotoNextElem, ctrl: false}), 
           new MouselessAction({key: ncKey.KEY_RIGHT, action: openNavTreeNode, ctrl: false}), 
           new MouselessAction({key: ncKey.KEY_LEFT, action: closeNavTreeNode, ctrl: false}) 
]});

Теперь можно ходить по дереву стрелками вверх-вниз, открывать-закрывать ветки влево-вправо. Функции openNavTreeNode/closeNavTreeNode были написаны до внедрения Mouseless (были опубликованы как api к дереву).

Таким образом, даже в этом случае не пришлось писать новый код, обходимся простой конфигурацией.
CSS легко заменяется под любую тему, достаточно описать правила для подсветки активируемых элементов и активного. Можно добавить свои, более сложные, для конкретных блоков или элементов.

Итого


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

Дополнительным бонусом стало то, что мы покрыли часть рекомендаций W3C “Web Content Accessibility Guidelines” ( www.w3.org/TR/WCAG20 ).

Работа в этом направлении не закончена, будем продолжать, ждём реакцию сообщества.
Tags:wcaguxhotkeys
Hubs: Netcracker corporate blog Usability Accessibility
Total votes 41: ↑33 and ↓8+25
Views39K

Information

Founded
Location
США
Website
www.netcracker.com
Employees
5,001–10,000 employees
Registered