2008-09-23 12 views
133

Supongamos que hay que adjuntar una función blur a un cuadro de entrada HTML así:Cuando se produce un evento de 'desenfoque', ¿cómo puedo saber qué elemento de enfoque fue * a *?

<input id="myInput" onblur="function() { ... }"></input> 

¿Hay una manera de obtener el ID del elemento que causó el evento blur al fuego (el elemento que se ha hecho clic) en el interior del ¿función? ¿Cómo?

Por ejemplo, supongamos que tengo un lapso de esta manera:

<span id="mySpan">Hello World</span> 

Si hago clic en el lapso inmediatamente después del elemento de entrada tiene el foco, el elemento de entrada perderá su enfoque. ¿Cómo sabe la función que se hizo clic en mySpan?

PD: Si el evento onclick del span ocurriera antes del evento onblur del elemento de entrada mi problema estaría resuelto, porque podría establecer algún valor de estado que indique que se hizo clic en un elemento específico.

PPS: El fondo de este problema es que deseo activar un control autocompletador AJAX externamente (desde un elemento seleccionable) para mostrar sus sugerencias, sin que las sugerencias desaparezcan inmediatamente debido al evento blur en el elemento de entrada. Por lo tanto, quiero verificar la función blur si se ha hecho clic en un elemento específico y, de ser así, ignorar el evento de desenfoque.

+0

esta es una pregunta interesante que me he aquí ve a ver el razonamiento detrás, es decir, ¿por qué estás haciendo esto? ¿Cuál es el contexto? – Rahul

+0

Rahul y roosteronacid, actualicé la pregunta como una reacción a sus comentarios (el PPS). –

+1

Como esta información es un poco antigua, consulte aquí para obtener una respuesta más reciente: http://stackoverflow.com/questions/7096120/how-to-determine-where-focus-went –

Respuesta

71

Hmm ... En Firefox, puede usar explicitOriginalTarget para tirar del elemento sobre el que se hizo clic. Yo esperaba toElement a hacer lo mismo para IE, pero no parece funcionar ... Sin embargo, se puede tirar el elemento de centrado recientemente en el documento:

function showBlur(ev) 
{ 
    var target = ev.explicitOriginalTarget||document.activeElement; 
    document.getElementById("focused").value = 
     target ? target.id||target.tagName||target : ''; 
} 

... 

<button id="btn1" onblur="showBlur(event)">Button 1</button> 
<button id="btn2" onblur="showBlur(event)">Button 2</button> 
<button id="btn3" onblur="showBlur(event)">Button 3</button> 
<input id="focused" type="text" disabled="disabled" /> 

Advertencia: Esta técnica Hace no funciona para cambios de foco causados ​​por tabulando a través de campos con el teclado, y no funciona en absoluto en Chrome o Safari.El gran problema con el uso de activeElement (excepto en IE) es que no se actualiza constantemente hasta después de el evento blur ha sido procesado, y puede no tener ningún valor válido durante el procesamiento. Esto se puede mitigar con una variación de the technique Michiel ended up using:

function showBlur(ev) 
{ 
    // Use timeout to delay examination of activeElement until after blur/focus 
    // events have been processed. 
    setTimeout(function() 
    { 
    var target = document.activeElement; 
    document.getElementById("focused").value = 
     target ? target.id||target.tagName||target : ''; 
    }, 1); 
} 

Esto debería funcionar en la mayoría de los navegadores modernos (probado en Chrome, IE y Firefox), con la advertencia de que Chrome no se pone el foco en los botones que están hecho clic (frente a pestañas).

+1

He estado buscando algo así como explicitOriginalTarget durante mucho tiempo. ¿Cómo lo descubriste? – Kev

+3

Examinado el objeto de evento en FireBug. FWIW, la propiedad es específica de Mozilla y está documentada en MDC: http://developer.mozilla.org/en/DOM/event.explicitOriginalTarget – Shog9

+0

Buena respuesta. Muy útil. –

0

Editar: Una manera muy divertida de hacerlo sería crear una variable que haga un seguimiento del enfoque para cada elemento que te interese. Por lo tanto, si le importa que 'myInput' pierda el foco, establezca una variable en el foco.

<script type="text/javascript"> 
    var lastFocusedElement; 
</script> 
<input id="myInput" onFocus="lastFocusedElement=this;" /> 

respuesta original: Puede pasar 'esto' a la función.

<input id="myInput" onblur="function(this){ 
    var theId = this.id; // will be 'myInput' 
}" /> 
+0

esto no responde la pregunta, con suerte lo hizo más claro con el ejemplo adicional –

-2

esta manera:

<script type="text/javascript"> 
    function yourFunction(element) { 
     alert(element); 
    } 
</script> 
<input id="myinput" onblur="yourFunction(this)"> 

O si adjunta al oyente a través de JavaScript (jQuery en este ejemplo):

var input = $('#myinput').blur(function() { 
    alert(this); 
}); 

Editar: lo siento. Leí mal la pregunta.

+2

Si es consciente de que esta no es la respuesta a la pregunta y la ha leído mal, actualicela o elimínela. –

1

Creo que no es posible, con IE puede intentar usar window.event.toElement, pero no funciona con Firefox.

+0

No funciona con Chrome o Safari. Tal vez no funcionará con las nuevas versiones de IE que son más compatibles con los estándares. – robocat

2

¿Puede revertir lo que está revisando y cuándo? Esto es, si recordaba lo que estaba borrosa última:

<input id="myInput" onblur="lastBlurred=this;"></input> 

y luego en el onClick para su palmo, la función de llamada() con dos objetos:

<span id="mySpan" onClick="function(lastBlurred, this);">Hello World</span> 

Su función podría entonces decidir si se debe o no activa el control Ajax.AutoCompleter. La función tiene el objeto cliquete y el objeto borroso. El onBlur ya ha sucedido, por lo que no hará desaparecer las sugerencias.

0

Sugiero usar variables globales blurfrom y blurto. Luego, configure todos los elementos que le interesan para asignar su posición en el DOM a la variable borrosa de cuando pierden el foco. Además, configúrelos de modo que obtener foco establezca la variable blurto en su posición en el DOM. Entonces, podría usar otra función completamente para analizar el desenfoque y los datos blurto.

+0

Es casi la solución, pero en el controlador de eventos onblur ya necesitaba saber en qué elemento se había hecho clic, por lo que un tiempo de espera en el onblur lo hizo por mí. –

16

Lo resuelto finalmente con un tiempo de espera en el evento onBlur (gracias a los consejos de un amigo que no es stackoverflow):

<input id="myInput" onblur="setTimeout(function() {alert(clickSrc);},200);"></input> 
<span onclick="clickSrc='mySpan';" id="mySpan">Hello World</span> 

funciona tanto en FF y el IE.

+8

¿Esto se considera una mala práctica en el mundo javascript por cierto? –

+0

publicación anterior pero tengo la misma pregunta. sin embargo, es lo único que parece hacer el trabajo cruzado. – joshs

+0

esta respuesta me ayudó una TONELADA resolviendo algún otro problema ... ¡Gracias Michael! – Alex

2

También estoy tratando de hacer Autocompleter ignorar borrosa si un elemento específico hizo clic y tener una solución de trabajo, pero sólo para Firefox debido a explicitOriginalTarget

Autocompleter.Base.prototype.onBlur = Autocompleter.Base.prototype.onBlur.wrap( 
     function(origfunc, ev) { 
      if ($(this.options.ignoreBlurEventElement)) { 
       var newTargetElement = (ev.explicitOriginalTarget.nodeType == 3 ? ev.explicitOriginalTarget.parentNode : ev.explicitOriginalTarget); 
       if (!newTargetElement.descendantOf($(this.options.ignoreBlurEventElement))) { 
        return origfunc(ev); 
       } 
      } 
     } 
    ); 

Este código envuelve método predeterminado onBlur de Autocompleter y comprueba si ignoreBlurEventElement parámetros está configurado. si está configurado, comprueba cada vez para ver si el elemento cliqueado es ignoreBlurEventElement o no. Si es así, Autocompleter no llama a Blur, de lo contrario llama a Blur. El único problema con esto es que solo funciona en Firefox porque la propiedad explicitOriginalTarget es específica de Mozilla. Ahora estoy tratando de encontrar una forma diferente de usar explicitOriginalTarget. La solución que ha mencionado requiere que agregue el comportamiento onclick manualmente al elemento. Si no puedo resolver el problema de explicitoOriginalTarget, supongo que seguiré tu solución.

0

tenga en cuenta que la solución con explicitOriginalTarget no funciona para los saltos de entrada de texto a entrada de texto.

de tratar de reemplazar los botones con el siguiente texto insumos y verá la diferencia:

<input id="btn1" onblur="showBlur(event)" value="text1"> 
<input id="btn2" onblur="showBlur(event)" value="text2"> 
<input id="btn3" onblur="showBlur(event)" value="text3"> 
16

Es posible utilizar evento MouseDown del documento en lugar de desenfoque:

$(document).mousedown(function(){ 
    if ($(event.target).attr("id") == "mySpan") { 
    // some process 
    } 
}); 
+0

¡listo! Funciona bien. – Jide

+24

Pero no funciona para la tecla de tabulación –

0

tengo estado jugando con esta misma característica y descubrí que FF, IE, Chrome y Opera tienen la capacidad de proporcionar el elemento de origen de un evento. No probé Safari, pero creo que podría tener algo similar.

$('#Form').keyup(function (e) { 
    var ctrl = null; 
    if (e.originalEvent.explicitOriginalTarget) { // FF 
     ctrl = e.originalEvent.explicitOriginalTarget; 
    } 
    else if (e.originalEvent.srcElement) { // IE, Chrome and Opera 
     ctrl = e.originalEvent.srcElement; 
    } 
    //... 
}); 
+0

esto funciona bien ¿por qué downvoting? solo elimina originalEvent! –

1

usar algo como esto:

var myVar = null; 

Y a continuación, dentro de su función:

myVar = fldID; 

Y luego:

setTimeout(setFocus,1000) 

Y luego:

function setFocus(){ document.getElementById(fldID).focus(); } 

código final:

<html> 
<head> 
    <script type="text/javascript"> 
     function somefunction(){ 
      var myVar = null; 

      myVar = document.getElementById('myInput'); 

      if(myVar.value=='') 
       setTimeout(setFocusOnJobTitle,1000); 
      else 
       myVar.value='Success'; 
     } 
     function setFocusOnJobTitle(){ 
      document.getElementById('myInput').focus(); 
     } 
    </script> 
</head> 
<body> 
<label id="jobTitleId" for="myInput">Job Title</label> 
<input id="myInput" onblur="somefunction();"></input> 
</body> 
</html> 
0

no me gusta el uso de tiempo de espera cuando se codifica Javascript por lo que lo haría el camino opuesto de Michiel Borkent. (No probé el código, pero debería entenderse).

<input id="myInput" onblur="blured = this.id;"></input> 
<span onfocus = "sortOfCallback(this.id)" id="mySpan">Hello World</span> 

En la cabeza algo así

<head> 
    <script type="text/javascript"> 
     function sortOfCallback(id){ 
      bluredElement = document.getElementById(blured); 
      // Do whatever you want on the blured element with the id of the focus element 


     } 

    </script> 
</head> 
-2


Creo que es fácilmente posible a través de jQuery pasando la referencia del campo haciendo que el evento onBlur en "este".
Por ej.

<input type="text" id="text1" onblur="showMessageOnOnblur(this)"> 

function showMessageOnOnblur(field){ 
    alert($(field).attr("id")); 
} 

Gracias
Monika

-2

Se podría hacer de esta manera:

<script type="text/javascript"> 
function myFunction(thisElement) 
{ 
    document.getElementByName(thisElement)[0]; 
} 
</script> 
<input type="text" name="txtInput1" onBlur="myFunction(this.name)"/> 
37

2015 respuesta: según UI Events, puede utilizar la propiedad relatedTarget del evento:

Se utiliza para identificar un evento secundario EventTarget relacionado con un evento Focus , según el tipo de evento.

Para blur eventos,

relatedTarget: event target recibir el foco.

Ejemplo:

function blurListener(event) { 
 
    event.target.className = 'blurred'; 
 
    if(event.relatedTarget) 
 
    event.relatedTarget.className = 'focused'; 
 
} 
 
[].forEach.call(document.querySelectorAll('input'), function(el) { 
 
    el.addEventListener('blur', blurListener, false); 
 
});
.blurred { background: orange } 
 
.focused { background: lime }
<p>Blurred elements will become orange.</p> 
 
<p>Focused elements should become lime.</p> 
 
<input /><input /><input />

Nota Firefox no apoyará relatedTarget hasta la versión 48 (bug 962251, MDN).

+0

Firefox no tiene soporte, pero hay un ticket: https://bugzilla.mozilla.org/show_bug.cgi?id=687787 – sandstrom

+3

Ahora lo tiene. Ver [aquí] (https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/relatedTarget). – rplaurindo

+0

encanta la comunidad web, ahora todo es mucho más fácil^_^ – am05mhz

0

Usted puede arreglar con IE:

event.currentTarget.firstChild.ownerDocument.activeElement 

Parece que "explicitOriginalTarget" para FF.

Antoine y J

1

Como se señaló en this answer, se puede comprobar el valor de document.activeElement. document es una variable global, por lo que no tiene que hacer ninguna magia para utilizarlo en su onBlur manejador:

function myOnBlur(e) { 
    if(document.activeElement === 
     document.getElementById('elementToCheckForFocus')) { 
    // Focus went where we expected! 
    // ... 
    } 
} 
1

Los FocusEvent casos tiene relatedTarget atributo, sin embargo, hasta la versión 47 de la FF, en concreto, este atributo devuelto nulo, de 48 ya funciona.

0

Escribí alternative solution cómo hacer que cualquier elemento sea enfocable y "blurable".

Se basa en la fabricación de un elemento tan contentEditable y ocultar visualmente y deshabilitar el modo de edición en sí:

el.addEventListener("keydown", function(e) { 
    e.preventDefault(); 
    e.stopPropagation(); 
}); 

el.addEventListener("blur", cbBlur); 
el.contentEditable = true; 

DEMO

Nota: Probado en Chrome, Firefox y Safari (OS X). No estoy seguro acerca de IE.


relacionadas: yo estaba buscando una solución para VueJs, así que para aquellos que interesados ​​/ curioso cómo implementar esta funcionalidad usando Vue Directiva enfocable, por favor take a look.

1
  • document.activeElement podría ser un nodo padre (por ejemplo nodo cuerpo, ya que está en una fase temporal de conmutación de un objetivo a otro), por lo que no es utilizable para su alcance
  • ev.explicitOriginalTarget no es siempre valorado

Así que la mejor manera es utilizar onclick en el evento cuerpo para la comprensión indirectamente el nodo (event.target) está en la falta de definición

0
  • document.activeElement podría ser una matriz n ode, por lo que es útil para su alcance
  • ev.explicitOriginalTarget no siempre se valora

Así que la mejor forma de hacerlo es utilizar el evento onclick para entender indirectamente que el nodo está en la falta de definición o no

Cuestiones relacionadas