Имитация нажатия клавиши табуляции с помощью JavaScript

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

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 });

... который я взял из здесь.

Первый подход кажется лучшим, но он не совсем работает. Если я изменю последние два параметра на 98, 98, действительно, в поле ввода будет введена буква «b». Но 9, 0 и 9, 9 (первый из которых я взял прямо с веб-сайта MDC) дают мне эти ошибки в firebug под 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».) Если я попытаюсь установить событие .data в объекте, который я передаю, он становится неопределенным при запуске события. Далее следует код, который я использую для просмотра:

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

Любые другие идеи?


person Kev    schedule 31.03.2009    source источник
comment
Что вы хотите вызвать? Вы пытаетесь переместить их на следующий вход?   -  person hunter    schedule 01.04.2009
comment
да. Но следующий «ввод» не обязательно является вводом или другим естественным элементом с табуляцией. И это не обязательно неестественно табуляция (т. е. $([tabindex]) ). Физическое нажатие вкладки (или Shift+Tab) делает именно то, что я хочу...   -  person Kev    schedule 01.04.2009
comment
Спасибо за это. Меня интересовал только первый пример кода вашего вопроса, который действительно помог :)   -  person Dan Rosenstark    schedule 22.12.2009
comment
Тоже столкнулся с этой проблемой, хотелось бы узнать список этих untrusted событий   -  person Dmitry Pashkevich    schedule 19.09.2012
comment
Связано: stackoverflow.com/questions/1601593/ В принятом ответе упоминается ...firing an event doesn't trigger the default result of the user action, for security reasons...   -  person Dmitry Pashkevich    schedule 19.09.2012


Ответы (5)


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

person Kev    schedule 07.07.2009

Это решение, которое я использовал в нашем веб-приложении для двух настраиваемых элементов управления, всплывающего календаря и всплывающего селектора веса единицы/значения (при нажатии на текстовое поле появляется 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, но большинство наших страниц используют одну форму.

person Tilendor    schedule 25.06.2009
comment
Дело в том, что некоторые из моих фокусируемых элементов пользовательского интерфейса не являются элементами формы, потому что они являются пользовательскими виджетами. - person Kev; 29.06.2009
comment
Для пользователей jquery замените первую строку этой функции на: var fields = $('form')[0]; Перебирать элементы формы. - person John Grant; 10.07.2009

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

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

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

person Kev    schedule 01.04.2009
comment
lists.whatwg.org/htdig.cgi/ whatwg-whatwg.org/2008-December/ поднял интересный вопрос: но что тогда, если пользовательский агент не использует цикл, а вместо этого использует управление направленным фокусом, как многие телефоны? - person Kev; 01.04.2009

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

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

// Simulate tab key when element is clicked 
$('.myElement').bind('click', function(event){
    $.tabNext();
    return false;
});
person Mark Lagendijk    schedule 11.09.2013

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

setAttribute('autocomplete','off')
person Justin Meyer    schedule 23.08.2009