2009-03-31 3 views
21

Я бы хотел, чтобы браузер действовал так, как если бы пользователь нажал клавишу Tab, когда они нажимают на что-то. В обработчик щелчка я попытался следующие подходы:Моделирование нажатия клавиш с помощью JavaScript

var event = document.createEvent('KeyboardEvent'); 
event.initKeyEvent("keypress", true, true, null, false, false, false, false, 9, 0); 
this.input.focus()[0].dispatchEvent(event); 

И JQuery:

this.input.focus().trigger({ type : 'keypress', which : 9 }); 

... который я взял из here.

Первый подход, кажется, лучший выбор, но не совсем работает. Если я изменил последние два параметра на 98, 98, действительно, в поле ввода вводится «b». Но 9, 0 и 9, 9 (первый из которых я взял прямо с веб-сайта МЦС) оба дают мне эти ошибки в поджигатель под FF3:

Permission denied to get property XULElement.popupOpen 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Permission denied to get property XULElement.overrideValue 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Permission denied to get property XULElement.selectedIndex 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Permission denied to set property XULElement.selectedIndex 
[Break on this error] this.input.focus()[0].dispatchEvent(event); 

Я слышал такие (без четкого определения «такие») события «ненадежны», что может объяснить эти ошибки.

Второй подход вызывает любое значение, которое я ставлю как event.which должен быть передан как event.which, но без эффекта (даже если я использую 98 вместо 9, в поле не вводится «b»). Если Я пытаюсь установить event.data в объекте, который я передаю, он заканчивается неопределенным, когда событие запускается. Ниже приводится код, который я использую для его просмотра:

$('#hi').keypress(function(e) { 
    console.log(e); 
}); 

Другие идеи?

+0

Что вы хотите вызвать? Вы пытаетесь переместить их на следующий вход? – hunter

+0

Да. Но следующий «вход» не обязательно является элементом ввода или другим элементом с естественным вкладом. И это не обязательно неестественно - tabstopped (т. Е. $ ("[Tabindex]")). Физически нажатая вкладка (или shift + tab) делает именно то, что я хочу ... – Kev

+0

Спасибо. Меня интересовал только первый пример кода вашего вопроса, который действительно помог :) –

ответ

4

Решение, с которым я столкнулся, состоит в том, чтобы создать div div «focus stealer» (с tabindex = -1 - может иметь фокус, но не может быть наложено первоначально) по обе стороны от области, в которой я хотите вручную управлять фокусом. Затем я помещаю возбуждающий истину прослушиватель событий для фокусировки и размытия по всей области. Когда в области происходит какой-либо фокус, значения табуиндекса изменяются на -1, и когда происходит размытие, они меняются на 0. Это означает, что, сосредоточившись в области, вы можете вывести вкладку или сдвинуть-вкладку из нее и правильно заканчиваются на других элементах страницы или элементах пользовательского интерфейса браузера, но как только вы фокусируетесь оттуда, фокусщики становятся табулируемыми, и в фокусе они правильно настраивают область управления и шунтируют фокус на элемент на конце, как если бы вы нажали на один конец или другой области руководства.

1

На самом деле, я думаю, что есть способ, даже если это большой PITA. Я могу убедиться, что каждый элемент, даже если, естественно, табу-стоп, имеет Xtabindex, каким-то образом в правильном порядке, хотя я буду бросать в чужие виджеты и поэтому с помощью jQuery добавлять их после факта, а не быть в состоянии указать его прямо в HTML или другом исходном строительном коде. Тогда вся моя форма будет иметь настоящий tabindex. В то время как он имеет фокус, он будет поглощать нажатия клавиш, и если они являются вкладками или сдвигами +, переместите фальшивый фокус на основе Xtabindex. Если вкладка нажата на последней (или сдвиге + вкладке на первом) элементе в форме, она не будет сожрать нажатие клавиши, что позволяет браузеру правильно сфокусироваться на других элементах интерфейса страницы или браузера вне формы с помощью клавиатуры.

Я могу только догадываться, какие виды непреднамеренных побочных эффектов этот подход представит.

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

+0

http: // lists .whatwg.org/htdig.cgi/whatwg-whatwg.org/2008-December/017980.html поднял интересный момент: «Но что тогда, если пользовательский агент не делает вещи, используя цикл, но вместо этого использует управление направленным фокусом , как и многие телефоны? – Kev

3

Это решение я использовал на нашем веб-приложение для двух пользовательских элементов управления, всплывающего календаря и селектор веса всплывающее блок/значение (нажав на текстовое поле всплывает DIV с двумя выбирает)

function tab_focus(elem) 
    var fields = elem.form.getElements() 
    for(var i=0;i<fields.length;i++) { 
    if(fields[i].id == elem.id){ 
     for(i=i+1;i<fields.length;i++){ 
     if(fields[i].type != 'hidden'){ 
      fields[i].focus() 
      return  
     } 
     } 
     break; 
    } 
    } 
    elem.form.focusFirstElement(); 
} 

Это использует оболочку Prototype и ожидает в качестве параметра расширенный элемент (то есть $ ('thing_id')).

Он получает форму, которой принадлежит элемент, и проходит через элементы формы до тех пор, пока не найдет себя.

Затем он ищет первый элемент после него, который не скрыт, и передает ему фокус.

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

+0

Дело в том, что некоторые из моих настраиваемых элементов пользовательского интерфейса не являются элементами формы, потому что это пользовательские виджеты. – Kev

+1

Для пользователей jquery заменить первую строку этой функции на: var fields = $ ('form') [0]; Пропустить элементы формы. – eniac

0

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

setAttribute('autocomplete','off') 
1

Я создал simple jQuery plugin, который действительно решает эту проблему. Он использует селектор «: tabbable» пользовательского интерфейса jQuery, чтобы найти следующий элемент «tabbable» и выбирает его.

Пример использования:

// Simulate tab key when element is clicked 
$('.myElement').bind('click', function(event){ 
    $.tabNext(); 
    return false; 
}); 
Смежные вопросы