Pregunta ¿Cómo averiguo qué elemento DOM tiene el foco?


Me gustaría averiguar, en Javascript, qué elemento tiene actualmente foco. He estado buscando en el DOM y todavía no he encontrado lo que necesito. ¿Hay alguna manera de hacer esto y cómo?

La razón por la que estaba buscando esto:

Estoy tratando de hacer llaves como las flechas y enter navegar a través de una tabla de elementos de entrada. La pestaña funciona ahora, pero la entrada y las flechas no aparecen de manera predeterminada. Tengo la parte de manejo de claves configurada, pero ahora necesito descubrir cómo mover el foco en las funciones de manejo de eventos.


1038
2018-01-30 20:21


origen


Respuestas:


Utilizar document.activeElement, es compatible con todos los principales navegadores.

Anteriormente, si intentabas averiguar qué campo de formulario tiene foco, no podrías. Para emular la detección en navegadores antiguos, agregue un manejador de eventos de "enfoque" a todos los campos y registre el último campo enfocado en una variable. Agregue un controlador de "desenfoque" para borrar la variable sobre un evento de desenfoque para el último campo enfocado.

Enlaces relacionados:


1222
2018-01-30 20:34



Como dijo JW, no puedes encontrar el elemento enfocado actual, al menos de una manera independiente del navegador. Pero si su aplicación es solo IE (algunas son ...), puede encontrarla de la siguiente manera:

document.activeElement

EDITAR: Parece que IE no tenía todo mal, después de todo, esto es parte del borrador HTML5 y parece ser compatible con la última versión de Chrome, Safari y Firefox al menos.


106
2017-08-27 17:33



Si puede usar jQuery, ahora es compatible con: focus, solo asegúrese de estar usando la versión 1.6+.

Esta declaración te dará el elemento actualmente enfocado.

$(":focus")

De: Cómo seleccionar un elemento que tenga foco en él con jQuery


77
2017-10-19 13:01



document.activeElement es ahora parte del borrador de trabajo HTML5 especificación, pero es posible que todavía no sea compatible con algunos navegadores no principales / móviles / anteriores. Puedes recurrir a querySelector (si eso es compatible). También vale la pena mencionar eso document.activeElement regresará document.body si ningún elemento está enfocado, incluso si la ventana del navegador no tiene foco.

El siguiente código resolverá este problema y se reducirá a querySelector dando un poco mejor apoyo.

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

Una cosa adicional a tener en cuenta es la diferencia de rendimiento entre estos dos métodos. Consultar el documento con selectores siempre será mucho más lento que acceder al activeElement propiedad. Mira esto Prueba jsperf.com.


39
2017-08-06 19:32



document.activeElement puede por defecto a la <body> elemento si no hay elementos enfocables en foco. Además, si un elemento está enfocado y la ventana del navegador está borrosa, activeElement continuará manteniendo el elemento enfocado.

Si alguno de estos dos comportamientos no es deseable, considere un enfoque basado en CSS: document.querySelector( ':focus' ).


13
2017-11-29 18:51



Por sí mismo, document.activeElement todavía puede devolver un elemento si el documento no está enfocado (y por lo tanto nada en el documento ¡esta enfocado!)

mayo quiere ese comportamiento, o mayo no importa (por ejemplo, dentro de keydown evento), pero si necesita saber que algo está realmente enfocado, también puede verificar document.hasFocus().

Lo siguiente le dará el elemento enfocado si hay uno, o bien null.

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

Para verificar si específico el elemento tiene foco, es más simple:

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

Para verificar si cualquier cosa está enfocado, es más complejo de nuevo:

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

Nota de robustez: En el código donde los controles contra document.body y document.documentElement, esto se debe a que algunos navegadores devuelven uno de estos o null cuando nada está enfocado

No cuenta si el <body> (o tal vez <html>) tenía una tabIndex atributo y por lo tanto podría ser enfocado. Si está escribiendo una biblioteca o algo así y quiere que sea robusto, probablemente debería manejar eso de alguna manera.


Aquí está un (pesado airquotes) versión "one-liner" de obtener el elemento enfocado, que es conceptualmente más complicado porque tienes que saber sobre el cortocircuito, y sabes, obviamente no cabe en una línea, suponiendo que quieras que sea legible.
No voy a recomendar este. Pero si eres un 1337 hax0r, idk ... está ahí.
También puedes eliminar el || null parte si no te importa obtener false en algunos casos. (Aún puedes obtener null Si document.activeElement es null)

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

Para verificar si un elemento específico está enfocado, alternativamente podría usar eventos, pero de esta manera requiere configuración (y potencialmente desmontaje) y, lo que es más importante, asume un estado inicial:

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

Podría corregir la suposición de estado inicial utilizando la forma no codificada, pero también podría utilizarla.


12
2017-09-08 18:47



Me gustó el enfoque utilizado por Joel S, pero también me gusta la simplicidad de document.activeElement. Usé jQuery y combiné los dos. Navegadores antiguos que no son compatibles document.activeElement utilizará jQuery.data() para almacenar el valor de 'hasFocus'. Los navegadores más nuevos usarán document.activeElement. yo asumo eso document.activeElement tendrá un mejor rendimiento.

(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
2018-02-04 12:36



Un pequeño ayudante que he usado para estos propósitos en 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);

De esta forma puedes verificar si el elemento tiene foco con el.hasFocus() siempre que startFocusTracking() ha sido llamado en el elemento dado.


9
2018-03-10 23:10



JQuery no admite el :focus pseudo-clase como de actual. Si lo está buscando en la documentación de JQuery, verifique en "Selectores", donde lo indica al W3C CSS documentos. Probé con Chrome, FF e IE 7+. Tenga en cuenta que para que funcione en IE, <!DOCTYPE... debe existir en la página html. Aquí hay un ejemplo, suponiendo que ha asignado una identificación al elemento que tiene foco:

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

7
2017-07-17 05:52



Si quieres obtener un objeto que sea instancia de Element, debes usar document.activeElement, pero si quieres obtener un objeto que sea instancia de Text, debes usar document.getSelection().focusNode.

Espero ayuda


7
2018-03-01 07:36