Використання jQuery для перевірки, чи вхід має фокус


561

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

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


1
ви можете спробувати звести це до кількох речень того, що потрібно, і що я відбуваю?
mkoryak

Я думаю, вам потрібно розглянути захоплення фокусу та розмиття подій ( docs.jquery.com/Events/focus і docs.jquery.com/Events/blur )
Wolfr

Я розмістив відповідь на відповідне запитання "Чи є" фокус "у JavaScript (або jQuery)?" . Я вдосконалив [клетовий підхід, цитований gnarf] (# 2684561).
luiggitama

Відповіді:


928

jQuery 1.6+

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

jQuery 1.5 і нижче

Редагувати: З часом змінюємось, ми знаходимо кращі методи тестування фокусу, новим улюбленим є ця суть від Бена Альмана :

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

Цитується від Mathias Bynens тут :

Зауважте, що (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 );

4
Це може спричинити помилкові позитиви. Дивіться stackoverflow.com/questions/967096/… для отримання додаткової інформації (дякую Бену Альману та Дієго Періні).
Mathias Bynens

@Mathias Bynens - Дякую за оновлення (ви більше ніж ласкаво просимо відредагувати цю спільноту у відповіді на wiki btw!)
gnarf

Що робити, коли вам це потрібно для роботи з 1.5- і 1.6? Я не хочу перекривати власний селектор фокусування jQuery. Щось на кшталт if (!jQuery.expr[':'].focus) { /* gist from Ben Alman */ }?
Бетамос

@betamos - Точно так ... Я додам щось у відповідь, щоб це відобразити.
gnarf

2
@Alex - Будь ласка, надайте зменшений тестовий випадок на jsFiddle, що показує проблему, тому що, наскільки я можу сказати, немає причин, щоб це не працювало над "динамічними" елементами. Я називаю shenanigans ...
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.


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

І тоді це лише питання доступу до стану елементів.



1

Чи думали ви про використання MouseOver і MouseOut для імітації цього. Також загляньте в mouseEnter та mouseLeave


Це, по суті, те, що я роблю з наведенням jQuery. Ви надаєте дві функції, одну для введення миші та одну для виходу миші.
bloudermilk

0

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

Отже: onfocus встановлює фокус = true, onblur встановлює фокус = false. onmouseover встановлює hovered = true, onmouseout встановлює hovered = false. Після кожного з цих подій запустіть функцію, яка додає / видаляє межу.


0

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

У мене зазвичай є змінна назва "noFocus" і встановлюю її в true. Потім я додаю подію фокусування до всіх входів, що робить noFocus false. Тоді я додаю подію розмиття до всіх входів, які повертають noFocus до істинного.

У мене клас MooTools, який обробляє це досить легко, я впевнений, що ви можете створити плагін jquery, щоб зробити те саме.

Після того, як це створено, ви можете зробити перевірку noFocus перед тим, як робити будь-яку заміну кордону.



0

Існує плагін, щоб перевірити, чи орієнтований елемент: http://plugins.jquery.com/project/focused

$('input').each(function(){
   if ($(this) == $.focused()) {
      $(this).addClass('focused');
   }
})

1
навіщо використовувати плагін, коли можна просто використовувати основний jquery?
Марсі Саттон

1
Ти правий. Але я не знав рішення цієї проблеми 2 роки тому.
Murat Çorlu

0

У мене було встановлено подію .live ("фокус"), щоб вибрати () (виділити) вміст тексту, щоб користувачеві не довелося вибирати його перед тим, як вводити нове значення.

$ (formObj) .select ();

Через химерність між різними браузерами вибір іноді буде замінений натисканням, що його спричинило, і він скасує вибір вмісту одразу після того, як на користь розміщення курсору в текстовому полі (працював здебільшого нормально у FF, але не вдався в IE)

Я думав, що зможу вирішити це, поставивши невелику затримку на вибір ...

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

Це спрацювало чудово, і вибір буде зберігатися, але виникла дивна проблема. Якщо ви переходите з одного поля в інше, фокус переходитиме на наступне поле до того, як відбувся вибір. Оскільки виділення викрадає фокус, то фокус буде повертатися назад і викликати нову подію "фокусування". Це закінчилося в каскаді введення, який вибирає танці по всьому екрану.

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


0

Що я завершив, це створити довільний клас під назвою .elementhasfocus, який додається та видаляється у функції jQuery focus (). Коли функція наведення курсора () запускається мишкою, вона перевіряє наявність .elementhasfocus:

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

Тож якщо у нього немає цього класу (читайте: жоден елемент у розділі не має фокусу), кордон видаляється. Інакше нічого не відбувається.


-2

Простий

 <input type="text" /> 



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

    alert("I am in Focus");

     });
 </script>

Це не говорить про те, який елемент на даний момент зосереджений. Він називається, коли новий елемент отримує фокус. Отже, якщо елемент вже має фокус, і ви хочете знати, чи є "це", цей код є марним.
Алексіс Вілке
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.