Как узнать, какой элемент DOM имеет фокус?

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

Я искал это:

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

Ответ 1

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

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

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

Ответ 2

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

document.activeElement

EDIT: похоже, что у IE не было ничего плохого, это часть черновика HTML5 и, по-видимому, поддерживается последней версией Chrome, Safari и Firefox по крайней мере.

Ответ 4

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

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

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

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

Ответ 5

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

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

Ответ 6

Мне понравился подход, используемый Джоэлем С., но мне также нравится простота 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);

Ответ 7

Небольшой помощник, который я использовал для этих целей в 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() был вызван для данного элемента.

Ответ 8

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

$(":focus").each(function() {
  alert($(this).attr("id") + " has focus!");
});

Ответ 9

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

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

if (typeof document.activeElement === 'undefined') { // Check browser doesn't do it anyway
  $('*').live('focus', function () { // Attach to all focus events using .live()
    document.activeElement = this; // Set activeElement to the element that has been focussed
  });
}

Ответ 10

Если вы используете jQuery, вы можете использовать это, чтобы узнать, активен ли элемент:

$("input#id").is(":active");

Ответ 11

Существуют потенциальные проблемы с использованием document.activeElement. Рассмотрим:

<div contentEditable="true">
  <div>Some text</div>
  <div>Some text</div>
  <div>Some text</div>
</div>

Если пользователь фокусируется на внутреннем-div, тогда document.activeElement по-прежнему ссылается на внешний div. Вы не можете использовать document.activeElement, чтобы определить, какой из внутренних div имеет фокус.

Следующая функция обходит вокруг этого и возвращает сфокусированный node:

function active_node(){
  return window.getSelection().anchorNode;
}

Если вы предпочитаете получать сфокусированный элемент, используйте:

function active_element(){
  var anchor = window.getSelection().anchorNode;
  if(anchor.nodeType == 3){
        return anchor.parentNode;
  }else if(anchor.nodeType == 1){
        return anchor;
  }
}

Ответ 12

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

Я надеюсь, что это поможет.

Ответ 13

Сам по себе document.activeElement может возвращать элемент, если документ не сфокусирован. Возможно, вы захотите этого поведения, но если вы этого не сделаете, вы можете проверить document.hasFocus():

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

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

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

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

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

Ответ 14

С помощью dojo вы можете использовать dijit.getFocus()

Ответ 15

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

Я создал свойство document.activeInputArea и использовал аддон jQuery HotKeys для блокировки событий клавиатуры для клавиш со стрелками, вкладки и ввода, и я создал обработчик событий для щелчка по входным элементам.

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

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

Ответ 16

Почти независимый от браузера способ достичь этого был сделан Quirksmode давным-давно. У него могут быть проблемы с Safari, поскольку Safari не всегда устанавливает события на тех же элементах, что и Chrome или Firefox. Иногда Safari даже устанавливает событие на текстовое поле вместо содержащего элемента. Это может быть исправлено после времени (путем проверки nodeType).

Вот он:

  function getFocus(e){
    var focused;
    if (!e) var e = window.event;
    if (e.target) focused = e.target;
    else if (e.srcElement) focused = e.srcElement;
    if (focused.nodeType == 3) focused = focused.parentNode;
    if (document.querySelector) {
      return focused.id;
    } else if (!focused || focused == document.documentElement) {
      return focused;
    }
  }

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


Благодаря Quirksmode

Ответ 17

Google Chrome (по крайней мере, до 33) имеет раздражающую ошибку с document.activeElement: в документах XHTML document.activeElement есть undefined. Я не тестировал другие браузеры на основе webkit, они также могут быть затронуты.

Ответ 18

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

setInterval(function() { console.log(document.querySelector(":focus")); }, 1000);

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