Различать событие фокусировки, вызванное клавиатурой/мышью

Я использую jquery ui autocomplete и хочу расшифровать события фокуса, вызванные взаимодействием клавиатуры и взаимодействием с мышью. Как я могу это сделать?

$('input').autocomplete({
    source: function(request, response) {
        ...
    },
    focus: function(event, ui) {
        // If focus triggered by keyboard interaction
            alert('do something');
        // If focus event triggered by mouse interaction
            alert('do something else');
    }
});

Спасибо

Ответы

Ответ 1

Единственный способ, которым я могу это сделать, - это прослушивание обработчиком событий keypress и click, а также включение/выключение булевого флага. Затем на обработчике focus вашего ввода вы можете просто проверить, что такое значение вашего флага, и оттуда.

Возможно, что-то вроде

var isClick;
$(document).bind('click', function() { isClick = true; })
           .bind('keypress', function() { isClick = false; })
           ;

var focusHandler = function () {
    if (isClick) {
        // clicky!
    } else {
        // tabby!
    }
}

$('input').focus(function() {
    // we set a small timeout to let the click / keypress event to trigger
    // and update our boolean
    setTimeout(focusHandler,100);
});

Взбитый небольшой рабочий прототип на jsFiddle (вам не нравится только этот сайт?). Проверьте, хотите ли вы.

Конечно, это все работает с событием focus на <input>, но обработчик focus на автозаполнении работает одинаково.

setTimeout представит немного отставания, но в 100 мс он может быть незначительным, исходя из ваших потребностей.

Ответ 2

Фактически вы должны определить это из события-объекта, который передается в фокус-событие. В зависимости от структуры кода это может быть другим, но обычно существует свойство originalEvent, которое может быть вложено в некоторую глубину. Осмотрите объект event более подробно, чтобы определить правильный синтаксис. Затем выполните проверку на mousenter или keydown с помощью регулярного выражения. Что-то вроде этого:

focus: function(event, ui){
  if(/^key/.test(event.originalEvent.originalEvent.type)){
    //code for keydown
  }else{
    //code for mouseenter and any other event
  }
}

Ответ 3

Самый простой и элегантный способ, который я нашел для этого, - использовать What Input?" library. Он крошечный (~ 2K minified) и дает вам доступ к типу события как в сценариях:

if (whatInput.ask() === 'mouse') {
  // do something
}

... а также (с помощью одного атрибута данных, который он добавляет к стилю документа body):

[data-whatinput="mouse"] :focus,
[data-whatinput="touch"] :focus {
  // focus styles for mouse and touch only
}

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

Ответ 4

Первое, что приходит в голову, это то, что вы можете найти положение мыши и проверить, не находится ли внутри этого элемента элемент

Используйте это, чтобы сохранить позицию элемента:

var input = $('#your_autocompleted_element_id'),
    offset = input.offset(),
    input_x = offset.top,
    input_y = offset.left,
    input_w = input.outerWidth(),
    input_h = input.outerHeight();

Затем используйте это, чтобы найти абсолютное положение мыши в окне:

var cur_mx, cur_my;
$(document).mousemove(function(e){
   cur_mx = e.pageX;
   cur_my = e.pageY;
});

Затем в настройке автозаполнения:

focus: function(event, ui) {
   // mouse is doing the focus when...
   // mouse x is greater than input x and less than input x + input width
   // and y is greater than input y and less than input y + input height
   if (cur_mx >= input_x && cur_mx <= input_x + input_w && cur_my >= input_y && cur_my <= input_y + input_h) {
      // do your silly mouse focus witchcraft here
   } else {
      // keyboard time!
   }
}