Lorsque l'onblor se produit, comment puis-je savoir quel élément est allé * à *?

Supposons que j'attache une fonction onblur à une boîte de saisie html comme ceci:

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

Existe-t-il un moyen d'obtenir l'ID de l'élément qui a provoqué l'incendie de l'événement Onblur (l'élément qui a été cliqué) à l'intérieur de la fonction? Comment?

Par exemple, supposons que j'ai une portée comme ceci:

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

Si je clique sur la portée juste après que l'élément d'entrée a la mise au point, l'élément d'entrée perdra son attention. Comment la fonction sait-elle que c'était mySpan qui a été cliqué?

PS: Si l'événement onclick de l'intervalle se produirait avant l'événement onblor de l'élément d'entrée, mon problème serait résolu, car je pourrais définir une certaine valeur d'état indiquant qu'un élément spécifique avait été cliqué.

PPS: l'arrière-plan de ce problème est que je souhaite déclencher un contrôle Ajax.AutoCompleter à l'extérieur (à partir d'un élément cliquable) pour montrer ses suggestions, sans que les suggestions disparaissent immédiatement en raison de l'événement Onblur sur l'élément de saisie. Je souhaite donc vérifier la fonction OnBlur si un élément spécifique a été cliqué, et si oui, ignorez l'événement flou.

Hmm … Dans Firefox, vous pouvez utiliser explicitOriginalTarget pour extraire l'élément sur lequel vous avez cliqué. Je m'attendais à ce que toElement fasse de même pour IE, mais cela ne semble pas fonctionner … Cependant, vous pouvez extraire l'élément nouvellement focalisé du document:

 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" /> 

Mise en garde: cette technique ne fonctionne pas pour les changements de focus causés par le tabulation à travers les champs avec le clavier, et ne fonctionne pas du tout dans Chrome ou Safari. Le gros problème lors de l'utilisation d' activeElement (sauf dans IE) est qu'il n'est pas toujours mis à jour jusqu'à ce que l'événement de blur ait été traité et que vous ne disposez d'aucune valeur valide pendant le traitement! Cela peut être atténué par une variation de la technique que Michiel a fini par utiliser :

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

Cela devrait fonctionner dans la plupart des navigateurs modernes (testés dans Chrome, IE et Firefox), avec la garantie que Chrome ne met pas l'accent sur les boutons qui sont cliqués (par rapport à l'onglet).

Réponse de 2015 : selon les événements de l'interface utilisateur , vous pouvez utiliser la propriété de l'événement relatedTarget :

Utilisé pour identifier une EventTarget secondaire liée à un événement Focus, selon le type d'événement.

Pour les événements blur ,

relatedTarget : cible d'événement cible de réception.

Exemple:

 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 /> 

Il est possible d'utiliser mousedown event of document au lieu de flou:

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

Je l'ai résolu finalement avec un délai d'attente sur l'événement Onblur (grâce aux conseils d'un ami qui n'est pas StackOverflow):

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

Fonctionne à la fois dans FF et IE.

J'essaie également de faire en sorte que Autocompleter ignore le flou si un élément spécifique a cliqué et a une solution de travail, mais pour Firefox uniquement en raison de l'explication de la base de données Oracle

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

Ce code enveloppe la méthode OnBlur par défaut sur Autocompleter et vérifie si les paramètres ignoreBlurEventElement sont définis. Si elle est définie, elle vérifie chaque fois que l'élément cliqué ignoreBlurEventElement ou non. Si c'est le cas, Autocompleter ne calcule pas sur l'écran, sinon il appelle onBlur. Le seul problème avec cela est que cela ne fonctionne que dans Firefox, car la propriété expliquéOriginalTarget est spécifique à Mozilla. Maintenant, j'essaie de trouver un moyen différent de l'utilisation de l'application expliciteGrancelle. La solution que vous avez mentionnée nécessite que vous ajoutez le comportement onclick manuellement à l'élément. Si je ne parviens pas à résoudre le problème explicite de Oracle, je suppose que je vais suivre votre solution.

Pouvez-vous renverser ce que vous vérifiez et quand? C'est si vous vous souvenez de ce qui s'est passé en flèche:

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

Puis, dans le clic sur votre intervalle, appelez la fonction () avec les deux objets:

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

Votre fonction pourrait alors décider de déclencher ou non le contrôle Ajax.AutoCompleter. La fonction a l'objet cliqué et l'objet flou. Le OnBlur est déjà arrivé, de sorte que les suggestions ne disparaîtront pas.

Utilisez quelque chose comme ceci:

 var myVar = null; 

Et puis, dans votre fonction:

 myVar = fldID; 

Et alors:

 setTimeout(setFocus,1000) 

Et alors:

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

Code 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> 

Je pense que ce n'est pas possible, avec IE, vous pouvez essayer d'utiliser window.event.toElement , mais ça ne fonctionne pas avec Firefox!

Comme indiqué dans cette réponse , vous pouvez vérifier la valeur de document.activeElement . document est une variable globale, donc vous n'avez pas à faire de magie pour l'utiliser dans votre gestionnaire onBlur:

 function myOnBlur(e) { if(document.activeElement === document.getElementById('elementToCheckForFocus')) { // Focus went where we expected! // ... } } 
  • Document.activeElement pourrait être un noeud parent (par exemple nœud du corps car il se trouve dans une transition de phase temporaire d'une cible à l'autre), donc il n'est pas utilisable pour votre portée
  • Ev.explicitOriginalTarget n'est pas toujours évalué

Donc, la meilleure façon est d'utiliser onclick sur l'événement du corps pour comprendre indirectement votre noeud (event.target) est en flou

Edit: Une façon hacky de le faire serait de créer une variable qui surveille l'accent pour chaque élément qui vous préoccupe. Donc, si vous craignez que 'myInput' ait perdu le focus, définissez une variable sur la mise au point.

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

Réponse d'origine: vous pouvez passer «ceci» à la fonction.

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

Je suggère d'utiliser les variables globales blurfrom et blurto. Ensuite, configurez tous les éléments que vous souhaitez affecter leur position dans le DOM à la variable blurfrom lorsqu'ils perdent leur attention. En outre, configurez-les de manière à ce que la mise au point définisse le flou variable à leur position dans le DOM. Ensuite, vous pouvez utiliser une autre fonction pour analyser les données blurfrom et blurto.

Gardez à l'esprit que la solution avec expliciteBrançaisTarget ne fonctionne pas pour les sauts d'entrée texte-entrée-texte.

Essayez de remplacer les boutons par les entrées de texte suivantes et vous verrez la différence:

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

J'ai joué avec cette même fonctionnalité et j'ai découvert que FF, IE, Chrome et Opera ont la capacité de fournir l'élément source d'un événement. Je n'ai pas testé Safari, mais je pense que cela pourrait avoir quelque chose de similaire.

 $('#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; } //... }); 

Je n'aime pas utiliser le délai d'attente lors du codage de javascript, donc je le ferais de manière opposée à Michiel Borkent. (N'a pas essayé le code derrière mais vous devriez avoir l'idée).

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

Dans la tête, quelque chose comme ça

 <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> 

Vous pouvez réparer IE avec:

  event.currentTarget.firstChild.ownerDocument.activeElement 

Il ressemble à "explicitOriginalTarget" pour FF.

Antoine et J

Les instances FocusEvent possèdent l'attribut relatedTarget , mais jusqu'à la version 47 du FF, spécifiquement, cet attribut est null renvoyé, à partir de 48 déjà fonctionne.

J'ai écrit une solution alternative pour rendre tout élément focalisable et "flamboyant".

Il est basé sur la création d'un élément comme contentEditable et le cache visuellement et désactive le mode d'édition lui-même:

 el.addEventListener("keydown", function(e) { e.preventDefault(); e.stopPropagation(); }); el.addEventListener("blur", cbBlur); el.contentEditable = true; 

DEMO

Note: Testé sur Chrome, Firefox et Safari (OS X). Pas sûr de l'IE.


En ce qui concerne: je cherchais une solution pour VueJs, alors pour ceux qui s'intéressent / curieux de mettre en œuvre une telle fonctionnalité à l'aide de la directive Vue Focusable, regardez .

  • Document.activeElement pourrait être un noeud parent, donc il est utilisable pour votre portée
  • Ev.explicitOriginalTarget n'est pas toujours évalué

Donc, la meilleure façon est d'utiliser l'événement onclick pour comprendre indirectement que votre nœud est en flou ou non

Par ici:

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

Ou si vous attachez l'auditeur via JavaScript (jQuery dans cet exemple):

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

Modifier : désolé. J'ai mal interprété la question.

Je pense qu'il est facilement possible via jquery en passant la référence du champ provoquant l'événement Onblur dans "this".
Par exemple

 <input type="text" id="text1" onblur="showMessageOnOnblur(this)"> function showMessageOnOnblur(field){ alert($(field).attr("id")); } 

Merci
Monika

Vous pourriez le faire comme ceci:

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