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

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

La razón por la que estaba buscando esto:

Estoy tratando de hacer llaves como flechas y enter navegar por una tabla de elementos de entrada. La pestaña funciona ahora, pero ingrese, y parece que las flechas no lo hacen por defecto. Tengo configurada la parte de manejo de claves, pero ahora necesito descubrir cómo mover el foco en las funciones de manejo de eventos.

preguntado el 30 de enero de 09 a las 18:01

Aquí hay un bookmarklet que console.log el elemento con foco: github.com/lingtalfi/where-is-focus-bookmarklet -

Puedes usar find-focused-element paquete: npmjs.com/package/find-focused-element -

Para mí, el bookmarklet no funciona como lo mencionó Ling. -

Vea un buen ejemplo de document.activeElement siendo utilizado aquí: stackoverflow.com/a/64176168/1599699 -

16 Respuestas

Utilice las document.activeElement, es compatible con los principales navegadores.

Anteriormente, si intentaba averiguar qué campo de formulario tiene el foco, no podía. Para emular la detección en los navegadores más antiguos, agregue un controlador 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 en un evento de desenfoque para el último campo enfocado.

Si necesita eliminar el activeElement puedes usar desenfoque; document.activeElement.blur(). Va a cambiar el activeElement a body.

Enlaces relacionados:

contestado el 08 de mayo de 20 a las 19:05

No estoy seguro de IE, pero FF y Safari devuelven el elemento BODY. - JW.

activeElement en realidad no devuelve el elemento enfocado. Cualquier elemento puede tener foco. Si un documento tiene 4 'scrolldivs', se puede desplazar por 0 o 1 de esos divs mediante las teclas de flecha. Si hace clic en uno, ese div está enfocado. Si hace clic fuera de todo, el cuerpo está enfocado. ¿Cómo saber qué scrolldiv está enfocado? jsfiddle.net/rudiedirkx/bC5ke/show (comprobar consola) - Rudie

@Rudie, @Stewart: Me basé en tu violín para crear un patio de recreo más elaborado: jsfiddle.net/mklement/72rTF. Descubrirá que el único navegador importante (a finales de 2012) que realmente puede enfocar un div es Firefox 17, y solo por tabulación lo. Los tipos de elementos que TODOS los principales navegadores devuelven a través de document.activeElement están restringidos a datos de entrada-Elementos relacionados. Si ningún elemento tiene el foco, todos los navegadores principales devuelven el body elemento - excepto IE 9, que devuelve el html elemento. - mklement0

No estoy seguro de si ayuda, pero puede hacer que un elemento como un div reciba el foco del teclado al incluir el atributo tabindex = "0" - Marco Luglio

Cualquier acceso a document.activeElement debe estar envuelto en un try catch ya que en algunas circunstancias puede generar una excepción (no solo IE9 AFAIK). Ver bugs.jquery.com/ticket/13393 y bugs.jqueryui.com/ticket/8443 - robogato

Como dijo JW, no puede 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 de HTML5 y parece ser compatible con la última versión de Chrome, Safari y Firefox al menos.

Respondido 18 Oct 11, 17:10

FF3 también. En realidad, esto es parte de la especificación HTML5 en torno a la "gestión del enfoque". - Creciente Fresco

Funciona en la versión actual de Chrome y Opera (9.62). No funciona en Safari 3.2.3 en OS X, pero funciona en Safari 4 que se lanzó ayer :) - gregarios

sigue igual para Chrome 19: S - Sebas

Solo funciona en chrome (20) / safari (5.1.3) cuando usas el teclado para tabular el elemento. Si hace clic en él, ni el selector jquery: focus ni el document.activeElement logran devolver el elemento en el que hizo clic (devolviendo el elemento undefined y el cuerpo del documento respectivamente). PD: No puedo creer que este hilo tenga 2 años y todavía hay problemas de regresión en webkit, junto con uno en el que los enlaces de omisión no funcionan, pero se está trabajando mucho para agregar css3 experimental. Creo que puedo volver a recomendar Firefox a mi familia y amigos. - Alba

Devuelve 'cuerpo' para la mayoría de los elementos. Bastante inútil. - Cornelius

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

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

$(":focus")

De: Cómo seleccionar un elemento que se centra en él con jQuery

contestado el 23 de mayo de 17 a las 13:05

Esto es bueno, pero ¿cómo lo hace jQuery? document.activeElement? Encontré esto: return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - harry pehkonen

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

El siguiente código solucionará este problema y recurrirá a querySelector dando un poco de 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 de jsperf.com.

Respondido 19 Oct 11, 14:10

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

Usted puede quiere ese comportamiento, o puede no importa (por ejemplo, dentro de un 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 de lo contrario null.

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

Para comprobar si un soluciones 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 se comprueba document.body y document.documentElement, esto se debe a que algunos navegadores devuelven uno de estos o null cuando nada está enfocado.

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


Aquí está un (pesado airquotes) versión "de una sola línea" de obtener el elemento enfocado, que es conceptualmente más complicado porque tienes que saber sobre los cortocircuitos, y ya 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 puede quitar el || null parte si no te importa conseguir false en algunos casos. (Todavía podrías conseguir null if document.activeElement is null):

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

Para comprobar 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ías arreglar la suposición del estado inicial usando la forma sin eventos, pero entonces también podrías usar eso en su lugar.

Respondido 01 Feb 18, 22:02

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

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

Respondido 06 ago 14, 20:08

Genial, sí, en mi caso, tu enfoque tenía mucho sentido. Puedo configurar mis elementos enfocables con 'tabindex = "- 1"', si ninguno de ellos tiene foco (digamos, algún texto o imagen, que no me importa) el document.querySelector (': focus') devuelve nulo. - Manfred

Vea mi respuesta para evitar usar querySelector: stackoverflow.com/a/40873560/2624876 - 1j01

Me gustó el enfoque utilizado por Joel S, pero también me encanta la simplicidad de document.activeElement. Usé jQuery y combiné los dos. Navegadores más antiguos que no son compatibles document.activeElement utilizará jQuery.data() para almacenar el valor de 'hasFocus'. Los navegadores más nuevos utilizará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);

Respondido el 08 de Septiembre de 10 a las 19:09

¿Podría ser reemplazado por el de @William Denniss? $("*:focus") ? - Pylinux

Supongo que podría. Escribí esto hace mucho tiempo y nunca tuve una razón para revisar una solución mejor ahora que ha pasado 5 años. ¡Pruébalo! Podría hacer lo mismo. ¡Tengo menos plugin en nuestro sitio! :) - Jason

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 manera puede verificar si el elemento tiene foco con el.hasFocus() siempre que startFocusTracking() se ha llamado en el elemento dado.

Respondido 22 Jul 14, 13:07

He encontrado que el siguiente fragmento es útil cuando intento determinar qué elemento tiene el foco actualmente. Copie lo siguiente en la consola de su navegador, y cada segundo imprimirá los detalles del elemento actual que tiene el foco.

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

Siéntase libre de modificar el console.log para cerrar sesión en algo diferente para ayudarlo a identificar el elemento exacto si imprimir todo el elemento no lo ayuda a identificar el elemento.

Respondido 20 Oct 17, 12:10

JQuery admite el :focus pseudoclase a partir de la actualidad. Si lo está buscando en la documentación de JQuery, consulte en "Selectores" donde le indica el Documentos CSS del W3C. 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 asumiendo que ha asignado una identificación al elemento que tiene el foco:

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

respondido 10 mar '11, 23:03

Deberías (¿siempre?) Usar this.id en lugar de $(this).attr('id'), o al menos (cuando ya tenga su objeto jQuery) $(this)[0].id. Javascript nativo en este nivel es MUCHO más rápido y más eficiente. Es posible que no se note en este caso, pero en todo el sistema notará una diferencia. - Martijn

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

Espero ayude.

Respondido el 16 de Septiembre de 17 a las 20:09

¿Mejor de qué manera? - 1j01

Abra el inspector de su navegador, haga clic en cualquier lugar de la página, más allá de este document.getSelection().focusNode.parentElement y toque Entrar. Después de eso, pasado document.activeElement y haz lo mismo. ;) - rplaurindo

Con este cuadro de comentarios enfocado, document.activeElement da el <textarea> mientras document.getSelection().focusNode da el <td> que contiene el <textarea> (y document.getSelection().focusNode.parentElement da el <tr> que contiene el <td>) - 1j01

Lo siento, mis disculpas. No lo expliqué bien. Si desea obtener un objeto que sea una instancia de Element, debes usar document.activeElement, pero si desea obtener un objeto que sea una instancia de Text, debes usar document.getSelection().focusNode. Por favor, pruébelo de nuevo. Espero haber ayudado. - rplaurindo

La pregunta es en qué elemento se está enfocando actualmente. Y el focusNode tampoco se garantiza que sea un nodo de texto. - 1j01

Existen problemas potenciales con el uso de document.activeElement. Considerar:

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

Si el usuario se centra en un div interno, document.activeElement aún hace referencia al div externo. No puede usar document.activeElement para determinar cuál de los div internos tiene el foco.

La siguiente función evita esto y devuelve el nodo enfocado:

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

Si prefiere obtener el elemento enfocado, use:

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

respondido 01 mar '15, 07:03

Eso no es realmente un problema con document.activeElement: el interior <div> los elementos en realidad no pueden recibir el enfoque, como puede ver visualmente al configurar el :focus pseudo-clase a algo visible (ejemplo: jsfiddle.net/4gasa1t2/1). De lo que estás hablando es de cuál de los <div>s contiene la selección o el símbolo de intercalación, que es un tema aparte. - Tim abajo

Leyendo otras respuestas y probándome, parece document.activeElement le dará el elemento que necesita en la mayoría de los navegadores.

Si tiene un navegador que no es compatible con document.activeElement, si tiene jQuery, debería poder completarlo en todos los eventos de enfoque con algo muy simple como esto (no probado ya que no tengo un navegador que cumpla con esos criterios a mano ):

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

Respondido 05 ago 11, 00:08

Si está usando jQuery, puede usar esto para averiguar si un elemento está activo:

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

Respondido 14 Feb 12, 19:02

Con dojo, puedes usar dijit.getFocus ()

Respondido el 13 de enero de 12 a las 11:01

Solo pongo esto aquí para dar la solución que finalmente se me ocurrió.

Creé una propiedad llamada document.activeInputArea, y usé el complemento HotKeys de jQuery para atrapar eventos de teclado para teclas de flecha, tabulación e ingresar, y creé un controlador de eventos para hacer clic en elementos de entrada.

Luego ajusté el activeInputArea cada vez que cambiaba el enfoque, por lo que podía usar esa propiedad para averiguar dónde estaba.

Sin embargo, es fácil arruinar esto, porque si tiene un error en el sistema y el enfoque no está donde cree que está, entonces es muy difícil restaurar el enfoque correcto.

contestado el 18 de mayo de 09 a las 13:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.