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

561

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

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

bloudermilk
источник
1
Вы можете попытаться свести это к нескольким предложениям того, что требуется, и что я делаю?
mkoryak
Я думаю, что вам нужно изучить фокус и размытие событий ( docs.jquery.com/Events/focus and docs.jquery.com/Events/blur )
Wolfr
Я опубликовал ответ на связанный вопрос: «Есть ли« фокус »в JavaScript (или jQuery)?» , Я улучшил [подход cletus, процитированный gnarf] (# 2684561).
Луиггитама

Ответы:

928

JQuery 1.6+

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

JQuery 1,5 и ниже

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

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

Цитируется Матиасом Биненсом здесь :

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

Вы определяете новый селектор. Смотрите плагины / авторинг . Тогда вы можете сделать:

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 );
gnarf
источник
4
Это может вызвать ложные срабатывания. См. Stackoverflow.com/questions/967096/… для получения дополнительной информации (спасибо Бену Алману и Диего Перини).
Матиас Биненс
@Mathias Bynens - Спасибо за обновление (вы можете редактировать этот вики-ответ сообщества!)
gnarf
Как насчет того, когда вам это нужно для работы с 1,5 и 1,6? Я не хочу переопределять собственный селектор фокуса в jQuery. Что то типа if (!jQuery.expr[':'].focus) { /* gist from Ben Alman */ }?
Бетамос
@betamos - Совершенно верно ... Я добавлю кое-что в ответ, чтобы отразить это.
Gnarf
2
@Alex - Пожалуйста, предоставьте сокращенный тестовый пример для jsFiddle, показывающий проблему, потому что, насколько я могу судить, нет причин, по которым это не должно работать на «динамических» элементах. Я называю махинации ...
Gnarf
46

CSS:

.focus {
    border-color:red;
}

JQuery:

  $(document).ready(function() {

    $('input').blur(function() {
        $('input').removeClass("focus");
      })
      .focus(function() {
        $(this).addClass("focus")
      });
  });
Даниэль Моура
источник
22

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

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

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

(Взято из этой сущности по Бен Alman .)

Матиас Биненс
источник
13

Апрель 2015 Обновление

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

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

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

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

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

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

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

jbutler483
источник
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;
        });
});
Джеймс
источник
Это то, что я сделал, но я использовал произвольный класс CSS, а не глобальную переменную javascript.
bloudermilk
Я использовал вариацию этого. Не требуется новый плагин jQuery. Это делает меня счастливым туристом!
День Дениса
1

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

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

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

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

cllpse
источник
1

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

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

Следите за обоими состояниями (hovered, focus) как за флагами true / false, и всякий раз, когда один из них изменяется, запускайте функцию, которая удаляет рамку, если оба имеют значение false, в противном случае показывает рамку.

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

Blixt
источник
0

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

У меня обычно есть переменная с именем «noFocus» и она имеет значение true. Затем я добавляю событие фокуса ко всем входам, что делает noFocus ложным. Затем я добавляю событие размытия ко всем входам, которые возвращают noFocus значение true.

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

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

Райан Флоренс
источник
0

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

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

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

$ (FormObj) .select ();

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

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

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

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

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

Брайан
источник
0

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

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

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

bloudermilk
источник
-2

просто

 <input type="text" /> 



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

    alert("I am in Focus");

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