Jak dowiedzieć się, który element DOM ma focus?

Chciałbym się dowiedzieć, w JavaScript, który element ma obecnie focus. Przeglądałem DOM i nie znalazłem jeszcze tego, czego potrzebuję. Czy jest na to sposób i jak?

Powód, dla którego tego szukałem:

Staram się, aby klawisze takie jak Strzałki i enter poruszały się po tabeli elementów wejściowych. Zakładka działa teraz, ale wejść, i strzałki nie domyślnie wydaje. Mam ustawioną część obsługi klucza, ale teraz muszę wymyślić, jak przesunąć ostrość over w funkcjach obsługi zdarzeń.

 1067
Author: Luca Kiebel, 2009-01-30

16 answers

Użycie document.activeElement, jest on obsługiwany we wszystkich głównych przeglądarkach.

Poprzednio, jeśli próbowałeś dowiedzieć się, które pole formularza ma fokus,nie mogłeś. Aby emulować wykrywanie w starszych przeglądarkach, dodaj obsługę zdarzenia "focus" do wszystkich pól i zapisz ostatnio ustawione pole w zmiennej. Dodaj funkcję obsługi "rozmycie", aby wyczyścić zmienną po zdarzeniu rozmycia dla Ostatnio ustawionego pola.

Powiązane linki:

 1266
Author: Dave Jarvis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-23 14:39:34

Jak powiedział JW, nie można znaleźć bieżącego elementu skupionego, przynajmniej w sposób niezależny od przeglądarki. Ale jeśli Twoja aplikacja jest TYLKO IE (niektóre są...), można go znaleźć w następujący sposób:

document.activeElement

EDIT: wygląda na to, że IE nie miało wszystkiego źle, jest to część HTML5 draft i wydaje się być wspierany przez najnowszą wersję Chrome, Safari i Firefox przynajmniej.

 108
Author: Wookai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-18 16:50:50

Jeśli możesz używać jQuery, obsługuje teraz :focus, tylko upewnij się, że używasz wersji 1.6+.

To polecenie spowoduje wyświetlenie aktualnie skupionego elementu.

$(":focus")

From: Jak wybrać element, który ma na nim fokus za pomocą jQuery

 78
Author: William Denniss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:28

document.activeElement jest teraz częścią projektu roboczego HTML5 specyfikacji, ale może nie być jeszcze obsługiwany w niektórych innych / mobilnych / starszych przeglądarkach. Możesz wrócić do querySelector (jeśli jest to obsługiwane). Warto również wspomnieć, że document.activeElement zwróci document.body Jeśli żaden element nie jest fokusowany - nawet jeśli okno przeglądarki nie ma Fokusa.

Poniższy kod będzie działał wokół tego problemu i powróci do querySelector dając nieco lepsze wsparcie.

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

Dodatkiem do notki jest różnica wydajności między tymi dwoma metodami. Odpytywanie dokumentu za pomocą selektorów zawsze będzie znacznie wolniejsze niż uzyskiwanie dostępu do właściwości activeElement. Zobacz to jsperf.com test .

 40
Author: Andy E,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-19 13:01:06

Sam w sobie, document.activeElement może nadal zwracać element, jeśli dokument nie jest skupiony (a więc nic w dokumencie nie jest skupione!)

Ty możesz chcieć takiego zachowania, lub to Może nie mieć znaczenia (np. w ramach zdarzenia keydown), ale jeśli chcesz wiedzieć, że coś jest rzeczywiście skupione, możesz dodatkowo sprawdzić document.hasFocus().

Poniżej znajdziesz element skupiony, jeśli taki istnieje, lub null.

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

Aby sprawdzić, czy konkretny element ma fokus, jest prostszy:

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

Aby sprawdzić, czy cokolwiek jest skupione, to znowu jest bardziej złożone:

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

Uwaga solidności: w kodzie, w którym sprawdza się przed document.body i document.documentElement, dzieje się tak dlatego, że niektóre przeglądarki zwracają jedną z nich lub null, gdy nic nie jest skupione.

Nie wyjaśnia, czy <body> (a może <html>) miał atrybut tabIndex, a zatem Może być faktycznie skupiony . Jeśli jesteś pisząc bibliotekę lub coś i chcesz, aby była solidna, prawdopodobnie powinieneś sobie z tym jakoś poradzić.


Oto ( heavy airquotes) "one-liner" wersja getting The focused element, która jest koncepcyjnie bardziej skomplikowana , ponieważ musisz wiedzieć o zwarciu, a wiesz, to oczywiście nie pasuje do jednej linii, zakładając, że chcesz, aby było czytelne.
Nie polecam tego. Ale jeśli jesteś 1337 hax0r, idk... jest tam.
Mógłbyś usuń również || null część, jeśli nie masz nic przeciwko temu, aby uzyskać false w niektórych przypadkach. (Można jeszcze dostać null Jeśli document.activeElement jest null):

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

Aby sprawdzić, czy dany element jest skupiony, alternatywnie można użyć zdarzeń, ale w ten sposób wymaga konfiguracji (i potencjalnie tearddown), i co ważne, przyjmuje stan początkowy :

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

Możesz naprawić początkowe założenie stanu, używając Nie-eventowego sposobu, ale równie dobrze możesz użyć tego zamiast tego.

 15
Author: 1j01,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-01 22:29:10

document.activeElement może być domyślnym elementem <body>, jeśli nie ma elementów fokusowalnych. Dodatkowo, jeśli element jest skupiony, a okno przeglądarki jest zamazane, activeElement będzie nadal trzymać element skupiony.

Jeśli jedno z tych dwóch zachowań nie jest pożądane, rozważ podejście oparte na CSS: document.querySelector( ':focus' ).

 13
Author: Nate Whittaker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-06 19:32:17

Podobało mi się podejście stosowane przez Joela S, ale uwielbiam też prostotę document.activeElement. Użyłem jQuery i połączyłem te dwa. Starsze przeglądarki, które nie obsługują document.activeElement, będą używać jQuery.data() do przechowywania wartości 'hasFocus'. Nowsze przeglądarki będą używać document.activeElement. Zakładam, że document.activeElement będzie miał lepszą wydajność.

(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);
 10
Author: Jason,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-08 18:47:29

Mały pomocnik, którego używałem do tych celów w 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);

W ten sposób można sprawdzić, czy element ma focus z el.hasFocus() pod warunkiem, że startFocusTracking() został wywołany na danym elemencie.

 9
Author: Joel S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-22 12:18:17

JQuery obsługuje pseudo-klasę :focus od current. Jeśli szukasz go w dokumentacji JQuery, sprawdź w sekcji "selektory", gdzie wskazuje na W3C CSS docs. Testowałem z Chrome, FF i IE 7+. Zauważ, że aby działał w IE, <!DOCTYPE... musi istnieć na stronie html. Oto przykład zakładając, że przypisałeś id do elementu, który ma focus:

$(":focus").each(function() {
  alert($(this).attr("id") + " has focus!");
});
 7
Author: DeezCashews,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-10 23:10:36

Jeśli chcesz uzyskać obiekt, który jest instancją Element, musisz użyć document.activeElement, ale jeśli chcesz uzyskać obiekt, który jest instancją Text, musisz użyć document.getSelection().focusNode.

Mam nadzieję, że pomoże.
 7
Author: rplaurindo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-16 19:12:03

Istnieją potencjalne problemy z używaniem dokumentu.activeElement. Consider:

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

Jeśli użytkownik skupia się na wewnętrznym-div, to document.activeElement nadal odwołuje się do zewnętrznego div. Nie można używać dokumentu.activeElement to determine which of the inner div ' s has focus.

Następująca funkcja obejdzie to i zwróci węzeł focused:

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

Jeśli wolisz uzyskać element skupiony, użyj:

function active_element(){
  var anchor = window.getSelection().anchorNode;
  if(anchor.nodeType == 3){
        return anchor.parentNode;
  }else if(anchor.nodeType == 1){
        return anchor;
  }
}
 6
Author: Nathan K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-01 07:36:58

Czytanie innych odpowiedzi i próba siebie, wydaje się document.activeElement da ci element, którego potrzebujesz w większości przeglądarek.

Jeśli masz przeglądarkę, która nie obsługuje dokumentu.activeElement jeśli masz jQuery w pobliżu, powinieneś być w stanie wypełnić go na wszystkich zdarzeniach focus z czymś bardzo prostym, takim jak to (niesprawdzone, ponieważ nie mam przeglądarki spełniającej te kryteria): {]}

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
  });
}
 5
Author: rjmunro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-04 23:20:21

Jeśli używasz jQuery, możesz użyć tego, aby dowiedzieć się, czy element jest aktywny:

$("input#id").is(":active");
 5
Author: Arne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-14 19:29:01

Z dojo możesz używać dijit.getFocus ()

 4
Author: Daniel Hartmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-13 11:55:48

Po prostu umieszczam to tutaj, aby dać rozwiązanie, które w końcu wymyśliłem.

Utworzyłem właściwość o nazwie document.activeInputArea, i użyłem jQuery ' s HotKeys addon do pułapek zdarzeń klawiatury dla klawiszy strzałek, tab i enter, i stworzyłem obsługę zdarzeń do klikania w elementy wejściowe.

Następnie dostosowałem activeInputArea za każdym razem, gdy zmieniałem ostrość, więc mogłem użyć tej właściwości, aby dowiedzieć się, gdzie jestem.

Łatwo to spieprzyć, bo jeśli masz błąd w system i ostrość nie jest tam, gdzie myślisz, że jest, to bardzo trudno jest przywrócić prawidłową ostrość.

 3
Author: Tony Peterson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 12:48:51

Poniższy fragment okazał się przydatny podczas próby określenia, który element ma aktualnie fokus. Skopiuj następujące elementy do konsoli przeglądarki, a co sekundę wydrukuje szczegóły bieżącego elementu, który ma fokus.

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

Możesz zmodyfikować console.log, aby wylogować coś innego, co pomoże Ci zlokalizować dokładny element, jeśli wydrukowanie całego elementu nie pomoże Ci zlokalizować elementu.

 3
Author: vegemite4me,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-20 11:20:01