Dom Traversal для автоматизации фокусировки клавиатуры - Пространственная навигация - PullRequest
4 голосов
/ 05 мая 2010

Я собираюсь начать с небольшого фона, который, надеюсь, поможет моему вопросу иметь больше смысла.

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

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

В настоящее время я устанавливаю атрибут (focusable = true) для любых элементов DOM, которые должны иметь возможность получать фокус. Что я хотел бы сделать, это определить предыдущий или следующий фокусируемый элемент (т.е. атрибут focusable = true) и применить фокус к элементу.

Я надеялся пройтись по дереву DOM, чтобы определить следующие и ранее фокусируемые элементы, но я не уверен, как это сделать в JQuery или вообще.

Я склонялся к попытке использовать методы обхода дерева JQuery, такие как next (), prev () и т. Д. Какой подход вы бы использовали для решения проблемы такого типа?

Спасибо

Ответы [ 3 ]

2 голосов
/ 05 мая 2010

Уловка, с которой вы можете столкнуться, это то, что «вниз» против «вправо» против «слева» и т. Д. Например. если у вас есть контент, представленный в виде таблицы (с использованием таблицы HTML) (3х3, как в крестики-нолики), и вы находитесь в центральной ячейке ...

+-----+-----+-----+
|     |  1  |     |
+-----+-----+-----+
|  2  |  x  |  3  |
+-----+-----+-----+
|     |  4  |     |
+-----+-----+-----+

квадраты 1, 2, 3, 4 будут теми, к которым вы будете перемещаться, если вы нажмете вверх, влево, вправо, вниз ... но в DOM-порядке они определены в порядке 1,2,3,4

Таким образом, «down» нужно знать, чтобы пропустить «3» и перейти к «4» ... еще хуже, может быть любое количество «фокусируемых» элементов от 3 до 4, если у вас таблица большего размера. (мой простой случай - таблица 3х3, но вы можете иметь все виды узлов, подузлов, плавающих узлов и т. д.)

Пример HTML:

<table>
  <tr>
    <td></td>
    <td>1</td>
    <td></td>
  </tr>
  <tr>
    <td>2</td>
    <td>x</td>
    <td>3</td>
  </tr>
  <tr>
    <td></td>
    <td>4</td>
    <td></td>
  </tr>
</table>

Возможно, лучше всего сделать каждый фокусируемый элемент button, в результате чего он будет иметь (или вы можете установить) tabIndex ... и затем вы можете использовать стрелки для перехода вперед / назад (только) через управление.

В противном случае вам нужно будет создать что-то достаточно умное, чтобы «геометрически» узнать, что внизу, слева, вверх… от того, где вы находитесь.

1 голос
/ 05 мая 2010

Вы можете использовать $(element).offset().top и $(element).offset().left, чтобы получить абсолютные позиции всех фокусируемых элементов на странице. Затем вам нужно будет сравнить позиции / размеры элемента [x, w, width, height] с позициями текущего сфокусированного элемента с учетом предполагаемого направления для навигации.

Например: если нажата UP, вам нужно будет найти все элементы НАД выше текущего сфокусированного элемента, сравнив их offset().top+height() с offset().top сфокусированного элемента, а затем определить, какой из этих элементов ближе всего [к текущему фокусированному элементу ]

Я начал писать код для этого, но это кажется довольно сложным. Идея такова:

var keys = {"UP":40,"DOWN":38/*etc*/};
var elements = $(".focusable");
var focused = $(".focused");
var positions = calculatePositions(elements); // returns [{"element":element,"dimensions":{"x": x, "y": y, "w": width, "h": height}];

$(document).keypress(e){
    var keycode = e.keycode,
    var candidates;
    // up
    switch (keycode){
        case keys.UP :
            candidates = filterToElementsAbove(focused, positions);
        break;
        case keys.DOWN :
            candidates = filterToElementsBelow(focused, positions);
        break;
        // etc...
        default;
            return true;
    }
    focused.removeClass("focused");
    focused = findClosestElement(focused, candidates).addClass("focused");
}

Приведенный выше код на самом деле не будет работать ... но он может направить вас в правильном направлении.

1 голос
/ 05 мая 2010

Имея риск предложить грубый ответ, рассматривали ли вы предварительный расчет названий элементов управления, на которые нужно перейти?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...