Как узнать, какой элемент DOM имеет фокус? - PullRequest
1176 голосов
/ 30 января 2009

Я хотел бы выяснить в JavaScript, какой элемент в настоящее время имеет фокус. Я просматривал DOM и пока не нашел то, что мне нужно. Есть ли способ сделать это и как?

Причина, по которой я искал это:

Я пытаюсь сделать клавиши, подобные стрелкам, и enter перемещаться по таблице элементов ввода. Вкладка теперь работает, но вводи, а стрелки не по умолчанию вроде бы. У меня настроена часть обработки ключей, но теперь мне нужно выяснить, как переместить фокус в функции обработки событий.

Ответы [ 16 ]

1391 голосов
/ 30 января 2009

Используйте document.activeElement, это поддерживается во всех основных браузерах.

Ранее, если вы пытались выяснить, какое поле формы имеет фокус, вы не могли этого сделать. Чтобы эмулировать обнаружение в старых браузерах, добавьте обработчик события «focus» ко всем полям и запишите последнее сфокусированное поле в переменной. Добавьте обработчик «размытия», чтобы очистить переменную после события размытия для последнего сфокусированного поля.

Ссылки по теме:

114 голосов
/ 30 января 2009

Как сказал JW, вы не можете найти текущий фокусированный элемент, по крайней мере, независимо от браузера. Но если ваше приложение предназначено только для IE (некоторые из них ...), вы можете найти его следующим образом:

document.activeElement

РЕДАКТИРОВАТЬ: Похоже, что IE не все не так, в конце концов, это часть проекта HTML5 и, кажется, поддерживается по крайней мере последней версии Chrome, Safari и Firefox.

78 голосов
/ 27 августа 2011

Если вы можете использовать jQuery, он теперь поддерживает: focus, просто убедитесь, что вы используете версию 1.6 +.

Это утверждение даст вам текущий элемент.

$(":focus")

С: Как выбрать элемент, который на нем фокусируется с помощью jQuery

41 голосов
/ 19 октября 2011

document.activeElement теперь является частью рабочего проекта HTML5 спецификации, но может еще не поддерживаться в некоторых не основных / мобильных / старых браузерах. Вы можете вернуться к querySelector (если это поддерживается). Также стоит упомянуть, что document.activeElement вернет document.body, если ни один элемент не сфокусирован & mdash; даже если окно браузера не имеет фокуса.

Следующий код поможет обойти эту проблему и вернется к querySelector, обеспечив немного лучшую поддержку.

var focused = document.activeElement;
if (!focused || focused == document.body)
    focused = null;
else if (document.querySelector)
    focused = document.querySelector(":focus");

Кроме того, следует отметить разницу в производительности между этими двумя методами. Запрос к документу с помощью селекторов всегда будет намного медленнее, чем доступ к свойству activeElement. Смотрите этот jsperf.com тест .

17 голосов
/ 29 ноября 2016

Сам по себе document.activeElement все еще может вернуть элемент, если документ не сфокусирован (и, следовательно, ничто в документе не сфокусировано!)

Вы можете хотеть такого поведения, или оно может не имеет значения (например, в рамках события keydown), но если вам нужно знать, что что-то действительно сфокусировано, вы можете дополнительно чек document.hasFocus().

Следующее даст вам сфокусированный элемент, если таковой имеется, или же null.

var focused_element = null;
if (
    document.hasFocus() &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement
) {
    focused_element = document.activeElement;
}

Чтобы проверить, имеет ли фокус определенный элемент, проще:

var input_focused = document.activeElement === input && document.hasFocus();

Чтобы проверить, сфокусировано ли что-нибудь , снова сложнее:

var anything_is_focused = (
    document.hasFocus() &&
    document.activeElement !== null &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement
);

Надежность Примечание : В коде, в котором проверяются document.body и document.documentElement, это происходит потому, что некоторые браузеры возвращают один из них или null, когда ничего не сфокусировано.

Не учитывается, если <body> (или, может быть, <html>) имеет атрибут tabIndex и, таким образом, может на самом деле быть сфокусированным . Если вы пишете библиотеку или что-то еще и хотите, чтобы она была надежной, вам, вероятно, следует как-то с этим справиться.


Вот ( тяжелые воздушные кавычки) "однострочная" версия получения сфокусированного элемента, которая концептуально более сложна , потому что вы должны знать о коротком замыкании, и y 'знаете, он явно не помещается в одну строку, при условии, что вы хотите, чтобы он был читабельным.
Я не буду рекомендовать это. Но если вы 1337 hax0r, idk ... это там.
Вы также можете удалить часть || null, если не против получить false в некоторых случаях. (Вы можете получить null, если document.activeElement равно null):

var focused_element = (
    document.hasFocus() &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement &&
    document.activeElement
) || null;

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

var input_focused = false;
input.addEventListener("focus", function() {
    input_focused = true;
});
input.addEventListener("blur", function() {
    input_focused = false;
});

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

14 голосов
/ 06 августа 2014

document.activeElement может по умолчанию использовать элемент <body>, если фокусируемые элементы не находятся в фокусе. Кроме того, если элемент сфокусирован, а окно браузера размыто, activeElement продолжит удерживать сфокусированный элемент.

Если любое из этих двух поведений нежелательно, рассмотрите подход на основе CSS: document.querySelector( ':focus' ).

10 голосов
/ 08 сентября 2010

Мне понравился подход, использованный Джоэлем С, но мне также нравится простота document.activeElement. Я использовал jQuery и объединил их. Старые браузеры, которые не поддерживают document.activeElement, будут использовать jQuery.data() для хранения значения hasFocus. Новые браузеры будут использовать document.activeElement. Я предполагаю, что document.activeElement будет иметь лучшую производительность.

(function($) {
var settings;
$.fn.focusTracker = function(options) {
    settings = $.extend({}, $.focusTracker.defaults, options);

    if (!document.activeElement) {
        this.each(function() {
            var $this = $(this).data('hasFocus', false);

            $this.focus(function(event) {
                $this.data('hasFocus', true);
            });
            $this.blur(function(event) {
                $this.data('hasFocus', false);
            });
        });
    }
    return this;
};

$.fn.hasFocus = function() {
    if (this.length === 0) { return false; }
    if (document.activeElement) {
        return this.get(0) === document.activeElement;
    }
    return this.data('hasFocus');
};

$.focusTracker = {
    defaults: {
        context: 'body'
    },
    focusedElement: function(context) {
        var focused;
        if (!context) { context = settings.context; }
        if (document.activeElement) {
            if ($(document.activeElement).closest(context).length > 0) {
                focused = document.activeElement;
            }
        } else {
            $(':visible:enabled', context).each(function() {
                if ($(this).data('hasFocus')) {
                    focused = this;
                    return false;
                }
            });
        }
        return $(focused);
    }
};
})(jQuery);
9 голосов
/ 04 февраля 2010

Маленький помощник, который я использовал для этих целей в Mootools:

FocusTracker = {
    startFocusTracking: function() {
       this.store('hasFocus', false);
       this.addEvent('focus', function() { this.store('hasFocus', true); });
       this.addEvent('blur', function() { this.store('hasFocus', false); });
    },

    hasFocus: function() {
       return this.retrieve('hasFocus');
    }
}

Element.implement(FocusTracker);

Таким образом, вы можете проверить, имеет ли элемент фокус с el.hasFocus(), при условии, что startFocusTracking() был вызван для данного элемента.

7 голосов
/ 17 июля 2016

Если вы хотите получить объект, который является экземпляром Element, вы должны использовать document.activeElement, но если вы хотите получить объект, который является экземпляром Text, вы должны использовать document.getSelection().focusNode.

Надеюсь, поможет.

7 голосов
/ 11 марта 2011

JQuery поддерживает псевдокласс :focus на текущий момент. Если вы ищете его в документации JQuery, отметьте в разделе «Селекторы», где он указывает на W3C CSS документ . Я тестировал с Chrome, FF и IE 7+. Обратите внимание, что для работы в IE на странице html должна существовать <!DOCTYPE.... Вот пример, предполагающий, что вы присвоили идентификатор элементу, который имеет фокус:

$(":focus").each(function() {
  alert($(this).attr("id") + " has focus!");
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...