javascript - perder - Evite disparar el evento de desenfoque si alguno de sus hijos recibe atención
perder el foco javascript (2)
Tengo un div en una página que muestra información sobre una categoría en particular (Imagen, Nombre, etc.).
Cuando hago clic en la imagen de edición, coloca la categoría en modo de edición, lo que me permite actualizar el nombre. Como puede ver en la imagen a continuación, muestra que "Soup" se encuentra actualmente en modo de edición, los otros están en modo de vista normal. Todo esto funciona como se espera con los botones cancelar / guardar haciendo todo bien. (Traté de agregar una imagen pero no me dejó, necesito más amor)
Sin embargo, una vez en el modo de edición, si hago clic en cualquier otro lugar de la página (fuera del div), el resultado esperado sería que la categoría de sopa vuelva al modo de visualización. Después de un evento de disparo de algún tipo, esto también debería permitirme preguntar si querían guardar los cambios.
Entonces, lo que decidí hacer fue crear un evento borroso en el div principal de "sopas". Esto funciona como se esperaba si hago clic en cualquier parte de la página, sin embargo, si hago clic en el elemento interno de div, también provoca que se desencadene el desenfoque de los padres, lo que provoca que la categoría regrese al modo de visualización.
Entonces, ¿hay alguna manera de evitar que el div principal active el evento blur si alguno de sus hijos recibe focus?
<div tabindex="-1" onblur="alert(''outer'')">
<input type="text" value="Soup" />
</div>
Simplemente escribí el código sin un compilador, por lo que no estoy seguro de si eso funciona, pero con eso espero que entiendas la idea.
Estoy usando Knockout.js para actualizar la GUI sobre la marcha, pero eso no debería afectar esta respuesta. No lo hubiera pensado.
He tenido que enfrentar este problema antes. No estoy seguro de si es la mejor solución, pero es lo que terminé usando.
Debido a que el evento de clic se dispara después del desenfoque, no existe una forma (confiable para navegadores cruzados) de saber qué elemento está ganando enfoque.
Mousedown, sin embargo, se dispara antes del desenfoque. Esto significa que puede establecer un indicador en el mousedown de los elementos secundarios e interrogar ese indicador en la imagen borrosa de su elemento primario.
Ejemplo de trabajo: http://jsfiddle.net/L5Cts/
Tenga en cuenta que también tendrá que manejar el keydown
(y verificar la tabulación / pestañas de cambio) si también desea capturar desenfoques causados por el teclado.
No creo que haya ninguna garantía de que el mousedown
ocurra antes de los eventos de foco en todos los navegadores, así que una mejor manera de manejar esto podría ser usar evt.relatedTarget
. Para el evento focusin
, la propiedad eventTarget
es una referencia al elemento que actualmente está perdiendo el foco. Puedes verificar si ese elemento es un descendiente del padre, y si no es así, sabes que el foco está ingresando al padre desde el exterior. Para el evento de focusout
, relatedTarget
es una referencia al elemento que actualmente está recibiendo focus. Use la misma lógica para determinar si el foco está saliendo completamente del elemento primario:
const parent = document.getElementById(''parent'');
parent.addEventListener(''focusin'', e => {
const enteringParent = !parent.contains(e.relatedTarget);
if (enteringParent) {
// do things in response to focus on any child of the parent or the parent itself
}
});
parent.addEventListener(''focusout'', e => {
const leavingParent = !parent.contains(e.relatedTarget);
if (leavingParent) {
// do things in response to fully leaving the parent element and all of its children
}
});