Имитация нажатия клавиш с помощью JavaScript - PullRequest
21 голосов
/ 31 марта 2009

Я бы хотел, чтобы браузер действовал так, как будто пользователь нажимал клавишу 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»). Если я попробуйте установить event.data в объекте, который я передаю, он заканчивается неопределенным, когда событие инициируется. Ниже приведен код, который я использую для просмотра:

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

Есть еще идеи?

Ответы [ 5 ]

4 голосов
/ 07 июля 2009

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

3 голосов
/ 26 июня 2009

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

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, но большинство наших страниц используют одну форму.

1 голос
/ 11 сентября 2013

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

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

// Simulate tab key when element is clicked 
$('.myElement').bind('click', function(event){
    $.tabNext();
    return false;
});
1 голос
/ 01 апреля 2009

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

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

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

0 голосов
/ 23 августа 2009

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

setAttribute('autocomplete','off')
...