Использование jQuery для проверки фокусировки ввода

444

На первой странице сайта, который я создаю, несколько <div> используют псевдокласс класса CSS :hover, чтобы добавить границу, когда мышь над ними. Один из <div> содержит <form>, который, используя jQuery, будет удерживать границу, если вход в нее имеет фокус. Это прекрасно работает, за исключением того, что IE6 не поддерживает :hover для любых элементов, кроме <a> s. Итак, для этого браузера мы используем jQuery для имитации CSS :hover с помощью метода $(#element).hover(). Единственная проблема заключается в том, что теперь jQuery обрабатывает как форму focus(), так и hover(), когда вход имеет фокус, тогда пользователь перемещает мышь туда и обратно, граница уходит.

Я думал, что мы можем использовать какое-то условное условие, чтобы остановить это поведение. Например, если мы проверили мышь, если какой-либо из входов был в фокусе, мы могли бы остановить границу от прохода. AFAIK, нет селектора :focus в jQuery, поэтому я не уверен, как это сделать. Любые идеи?

  • 1
    Вы можете попытаться свести это к нескольким предложениям того, что требуется, и что я делаю?
  • 0
    Я думаю, что вам нужно изучить фокус и размытие событий ( docs.jquery.com/Events/focus and docs.jquery.com/Events/blur )
Показать ещё 1 комментарий
Теги:
javascript-events
jquery-on

15 ответов

768
Лучший ответ

jQuery 1.6 +

jQuery добавил селектор :focus, поэтому нам больше не нужно его добавлять. Просто используйте $("..").is(":focus")

jQuery 1.5 и ниже

Изменить: По мере изменения мы находим лучшие методы тестирования фокуса, новый фаворит этот смысл из Ben Alman:

jQuery.expr[':'].focus = function( elem ) {
  return elem === document.activeElement && ( elem.type || elem.href );
};

Цитата из Mathias Bynens здесь:

Обратите внимание, что тест (elem.type || elem.href) был добавлен для фильтрации ложных срабатываний, таких как тело. Таким образом, мы должны отфильтровать все элементы, кроме элементов управления формой и гиперссылок.

Вы определяете новый селектор. См. Plugins/Authoring. Затем вы можете сделать:

if ($("...").is(":focus")) {
  ...
}

или

$("input:focus").doStuff();

Любой jQuery

Если вы просто хотите выяснить, какой элемент имеет фокус, вы можете использовать

$(document.activeElement)

Если вы не уверены, что версия будет 1.6 или ниже, вы можете добавить селектор :focus, если он отсутствует:

(function ( $ ) {
    var filters = $.expr[":"];
    if ( !filters.focus ) { 
        filters.focus = function( elem ) {
           return elem === document.activeElement && ( elem.type || elem.href );
        };
    }
})( jQuery );
  • 4
    Это может вызвать ложные срабатывания. См. Stackoverflow.com/questions/967096/… для получения дополнительной информации (спасибо Бену Алману и Диего Перини).
  • 0
    @Mathias Bynens - Спасибо за обновление (вы можете редактировать это вики-ответ от сообщества!)
Показать ещё 7 комментариев
43

CSS

.focus {
    border-color:red;
}

JQuery

  $(document).ready(function() {

    $('input').blur(function() {
        $('input').removeClass("focus");
      })
      .focus(function() {
        $(this).addClass("focus")
      });
  });
18

Вот более надежный ответ, чем принятый в настоящее время:

jQuery.expr[':'].focus = function(elem) {
  return elem === document.activeElement && (elem.type || elem.href);
};

Обратите внимание, что тест (elem.type || elem.href) был добавлен для фильтрации ложных срабатываний, таких как body. Таким образом, мы должны отфильтровать все элементы, кроме элементов управления формой и гиперссылок.

(взято из этот смысл Бен Альман. )

9

Обновление апреля 2015 г.

Поскольку этот вопрос был довольно долгое время, и некоторые новые соглашения вступили в игру, я чувствую, что я должен упомянуть, что метод .live был обесценен.

Вместо этого теперь был введен метод .on.

Их документация весьма полезна для объяснения того, как она работает;

Метод .on() присоединяет обработчики событий к выбранному в данный момент набору элементов в объекте jQuery. Начиная с jQuery 1.7, метод .on() предоставляет все функции, необходимые для присоединения обработчиков событий. Для помощь в преобразовании из более старых методов события jQuery, см..bind(),.delegate() и .live().

Итак, для того, чтобы настроить таргетинг на событие, ориентированное на вход, вы можете использовать его в script. Что-то вроде:

$('input').on("focus", function(){
   //do some stuff
});

Это довольно надежный и даже позволяет использовать клавишу TAB.

2

Я не совсем уверен, что вам нужно, но похоже, что это может быть достигнуто путем сохранения состояния входных элементов (или div?) в качестве переменной:

$('div').each(function(){

    var childInputHasFocus = false;

    $(this).hover(function(){
        if (childInputHasFocus) {
            // do something
        } else { }
    }, function() {
        if (childInputHasFocus) {
            // do something
        } else { }
    });

    $('input', this)
        .focus(function(){
            childInputHasFocus = true;
        })
        .blur(function(){
            childInputHasFocus = false;
        });
});
  • 0
    Это то, что я сделал, но я использовал произвольный класс CSS, а не глобальную переменную javascript.
  • 0
    Я использовал вариацию этого. Не требуется новый плагин jQuery. Это делает меня счастливым туристом!
1

Альтернативой использованию классов для обозначения состояния элемента является внутренняя функция хранилища данных.

P.S.: Вы можете сохранять логические значения и все, что хотите, используя функцию data(). Это не только строки:)

$("...").mouseover(function ()
{
    // store state on element
}).mouseout(function ()
{
    // remove stored state on element
});

И тогда это просто вопрос доступа к состоянию элементов.

1

Вы думали об использовании mouseOver и mouseOut для имитации этого. Также загляните в mouseEnter и mouseLeave

  • 0
    По сути, это то, что я делаю с зависанием jQuery. Вы предоставляете две функции, одну для мыши и одну для мыши.
0

Если кто-то заботится, теперь гораздо лучший способ захватить фокус, $(foo).focus(...)

http://api.jquery.com/focus/

  • 1
    Вопрос не в том, чтобы установить фокус на элемент ...
0

Простой

 <input type="text" /> 



 <script>
     $("input").focusin(function() {

    alert("I am in Focus");

     });
 </script>
  • 0
    Это не говорит вам, какой элемент в данный момент находится в фокусе. Он вызывается, когда новый элемент получает фокус. Так что, если элемент уже имеет фокус, и вы хотите знать, является ли «this» тем, этот код бесполезен.
0

У меня было событие .live( "focus" ), чтобы выбрать() (выделить) содержимое текстового ввода, чтобы пользователь не должен был выбирать его, прежде чем вводить новое значение.

$(formObj).select();

Из-за причуд между различными браузерами выбор иногда заменяется щелчком, который вызвал его, и он отменил выбор содержимого сразу после того, как он помещал курсор в текстовое поле (работал в основном в FF, но не удался IE)

Я думал, что смогу это решить, слегка отложив выбор...

SetTimeout (функция() {$ (formObj).select();}, 200);

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

Работоспособным решением будет проверка того, что поле все еще имеет фокус перед выполнением select(), но, как уже упоминалось, нет простого способа проверить... Я в итоге просто отказался от всего автоматического выделения, а не поворачивал что должно быть единственным вызовом jQuery select() в огромную функцию, загруженную с помощью подпрограмм...

0

Существует плагин для проверки фокусировки элемента: http://plugins.jquery.com/project/focused

$('input').each(function(){
   if ($(this) == $.focused()) {
      $(this).addClass('focused');
   }
})
  • 1
    зачем использовать плагин, когда вы можете просто использовать ядро jquery?
  • 1
    Вы правы. Но я не знал решения этой проблемы 2 года назад.
0

Нет: фокус, но есть: selected http://docs.jquery.com/Selectors/selected

но если вы хотите изменить то, как все выглядит на основе выбранного, вы, вероятно, должны работать с событиями размытия.

http://docs.jquery.com/Events/blur

0

Следите за тем, чтобы оба состояния (зависающие, сфокусированные) были как флагов истина/ложь, и всякий раз, когда они меняются, запускайте функцию, которая удаляет границу, если оба они ложны, в противном случае отображается граница.

Итак: onfocus устанавливает focus = true, onblur устанавливает focus = false. onmouseover устанавливает hovered = true, onmouseout устанавливает hovered = false. После каждого из этих событий запускается функция, которая добавляет/удаляет границу.

0

Что я сделал, это создать произвольный класс с именем .elementhasfocus, который добавляется и удаляется в функции jQuery focus(). Когда функция hover() работает от мыши, она проверяет .elementhasfocus:

if(!$("#quotebox").is(".boxhasfocus")) $(this).removeClass("box_border");

Итак, если у него нет этого класса (читай: ни один элемент в div не имеет фокуса), граница будет удалена. В противном случае ничего не происходит.

0

Насколько я знаю, вы не можете запрашивать браузер, если какой-либо ввод на экране имеет фокус, вам нужно настроить какое-то отслеживание фокуса.

Обычно я имею переменную под названием "noFocus" и устанавливаю ее в true. Затем я добавляю событие фокусировки ко всем входам, которые делают noFocus false. Затем я добавляю событие размытия ко всем входам, которые возвращают noFocus в true.

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

Как только это будет создано, вы можете сделать check noFocus перед тем, как выполнить обмен границ.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню