Изначально, операционная система FireFox OS была ориентирована на работу в устройствах, оснащённых сенсорным экраном. Разработчикам приложений не нужно было задумываться над тем, как происходит включение checkbox, переключение radiobutton, да и вообще передача фокуса элементу. За это все отвечала система.

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

Стандартными клавишами для навигации в телефонах на базе KaiOS являются:

  1. ОК
  2. Левая софт клавиша
  3. Правая софт клавиша
  4. Влево
  5. Вверх
  6. Вправо
  7. Вниз

Клавиши навигации

Создадим приложение, в интерфейсе которого будет checkbox, radiobutton и гиперссылка. Приложение не будет делать ничего полезного, однако на его примере будет видно, как происходит взаимодействие системы с клавиатурой.

Создадим новое приложение, и файле index.html пропишем следующее:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"> <!-- Явно указываем кодировку UTF-8 из-за русских букв -->
</head>
<body>
<input type="checkbox"> Чекбокс <!-- Чекбокс -->
<br>
<input type="radio" name="opt"> Первый <br> <!-- Первая радиокнопка -->
<input type="radio" name="opt"> Второй <br> <!-- Вторая радиокнопка -->
<a href="/link.html">Ссылка</a> <!-- Ссылка -->
</body>
</html>

Если мы его запустим, то увидим в окне симулятора следующее:

Навигация в KaiOS

Однако, если вы попробуете с помощью управляющих клавиш выбрать какой либо объект, у вас ничего не выйдет. Модифицируем код, добавив следующее:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<input type="checkbox" tabIndex=0 class="items"> Чекбокс
<br>
<input type="radio" name="opt" tabIndex=1 class="items"> Первый <br>
<input type="radio" name="opt" tabIndex=2 class="items"> Второй <br>
<a href="/link.html" tabIndex=3 class="items">Ссылка</a>
</body>
</html>

Мы добавили два атрибута:

  • class="items" - этот класс мы будем указывать всем объектам, на которые возможен переход фокуса. 
  • tabIndex - этим атрибутом мы обозначаем номер элемента, к которому возможен переход фокуса.

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

Для корректной работы каждого объекта, для которого вы установили class="items", необходимо установить номер tabIndex. Нумерация начинается с нуля. Для удобства, порядок элементов должен быть от меньшего к большему. Если нумерация tabIndex будет раскидана, перемещение фокуса при нажатии управляющей кнопки, будет происходить не в порядке отрисовки объектов на экране, а в порядке нумерации tabIndex.

Добавим в наш файл index.html следующие строки:

<!DOCTYPE html>
<html>
<head>
<script src="/app.js" defer></script> <!-- Внешний скрипт для управляющих клавиш -->
<meta charset="utf-8">
</head>
<body>
<input type="checkbox" tabIndex=0 class="items"> Чекбокс
<br>
<input type="radio" name="opt" tabIndex=1 class="items"> Первый <br>
<input type="radio" name="opt" tabIndex=2 class="items"> Второй <br>
<a href="/link.html" tabIndex=3 class="items">Ссылка</a>
<footer class="softkey"> <!-- Отображаем подписи к софт клавишам -->
<table><tr>
<th><div id="softkey-left">Left</div></th>
<th><div id="softkey-center">Ok</div></th>
<th><div id="softkey-right">Right</div></th>
</tr></table>
</footer>
</body>
</html>

В нижнем колонтитуле (футере), мы отображаем названия к софт клавишам. А в разделе <head> мы подключаем внешний скрипт, для взаимодействия с клавиатурой. Поместим файл app.js в корневой каталог программы, и напишем в нем следующее:

window.addEventListener("load", function() {
  document.querySelector(".items").focus();
});

Эта часть будет отвечать за то, что после загрузки приложения, фокус перейдёт к первому элементу класса items. Ниже, напишем следующую функцию:

function handleKeydown(e) {
  switch(e.key) {
    case 'ArrowUp':   // Клавиша вверх 
      nav(-1);
      break;
    case 'ArrowDown':   // Клавиша вниз 
      nav(1);
      break;
    case 'ArrowRight':   // Клавиша вправо
      nav(1);
      break;
    case 'ArrowLeft':   // Клавиша влево 
      nav(-1);
      break;
    case 'SoftLeft':   // Левая софт клавиша 
      softkeyCallback.left();
      break;
    case 'SoftRight':   // Правая софт клавиша 
      softkeyCallback.right();
      break;
    case 'Enter':   // Центральная софт клавиша 
      softkeyCallback.center();
      break;
  }

Эта функция отвечает за то, что при нажатии определённой клавиши, будет произведено определённое действие. Так, для примера, при нажатии клавиши «Вверх», мы передадим в функцию nav, значение «-1». А при нажатии левой функциональной клавиши, будет вызвана соответствующая функция. Теперь, напишем функцию nav:

function nav (move) {
  var currentIndex = document.activeElement.tabIndex;
  var items = document.querySelectorAll('.items');
  var next = currentIndex + move;
  if (next>items.length-1) {next=items.length-1;} else if (next<0) {next=0;}
  var targetElement = items[next];
  targetElement.focus();
};

После того, как в функцию поступило значение (если нажали клавишу вверх или влево, то это «-1», если вниз или вправо, то «1»), выполняется следующая последовательность действий:

  • currentIndex получает значение текущего элемента, на котором стоит фокус. 
  • items получает общее число элементов класса «items». 
  • next получает значение следующего номера элемента, на который перейдёт фокус. В случае нажатия клавиши вверх, например, переменная next станет на единицу меньше, а в случае нажатия клавиши вниз, на единицу больше. 
  • Проверяется, не вышли ли мы за пределы количества элементов (не больше общего количества и не меньше нуля).
  • targetElement получает имя элемента, на которое должен перейти фокус.
  • И, строка «targetElement.focus()» передаст фокус нужному элементу. 

Перемещение организовано. Теперь, необходимо организовать взаимодействие с выделенным элементом. Напишем следующее:

const softkeyCallback = {
    left: function() { 
      alert("Left Button");
     },
  
    center: function() { 
      var chk = document.activeElement;
      if (chk.type == "checkbox" || chk.type == "radio") {
      if (chk.checked == false) {chk.checked = true;} else {chk.checked = false;}}
      },
  
    right: function() { 
      alert("Right Button");
     }
};

Константа softkeyCallback отвечает за взаимодействие с тремя софт клавишами. На left и right мы привязали две одинаковые функции - alert - которые выводят сообщение на экран, о том, какая клавиша нажата. На центральную клавишу, мы привязали следующее:

  • Переменная chk получает активный элемент.
  • Если этим элементом является чекбокс или радиокнопка, то, проверяется, помечен ли этот элемент.
  • В случае, если он помечен, метка снимается, в противном случае метка ставиться. 

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

Осталось добавить последнюю строку:

document.activeElement.addEventListener('keydown', handleKeydown);

В ней мы указываем, что приложение должно «слушать» все нажатия на клавиши, и в случае нажатия, передавать её значение в функцию handleKeydown.

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

Навигация в KaiOS

При нажатии на левую или правую софт клавишу, мы получаем на экране всплывающее сообщение с текстом - функции работают. Обратите внимание, нажатие кнопки «ОК» после всплывающего сообщения приводит к сбою симулятора. Этот баг в будущих версиях будет исправлен.

Подписи в футере под софт клавишами находятся не в низу экрана (как должно быть), а под последним элементом. Это связано с тем, что мы не прописали в CSS правильное расположение элементов. Так же, из-за отсутствия CSS разметки, не очень понятно, к какому элементу перешёл фокус. В следующем материале («Начальный дизайн»), мы рассмотрим создание разметки для удобной навигации.

Добавить комментарий

Защитный код
Обновить