243 votes

Lorsqu'un événement " flou " se produit, comment puis-je savoir quel élément a été touché par le focus ?

Supposons que j'attache un blur à un champ 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 causé le problème ? blur à déclencher (l'élément qui a été cliqué) dans la fonction ? Comment ?

Par exemple, supposons que j'ai un span comme celui-ci :

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

Si je clique sur le span juste après que l'élément de saisie ait le focus, l'élément de saisie perdra son focus. Comment la fonction sait-elle qu'elle a été mySpan qui a été cliqué ?

PS : Si l'événement onclick du span se produisait avant l'événement onblur de l'élément de saisie, mon problème serait résolu, car je pourrais définir une valeur d'état indiquant qu'un élément spécifique a été cliqué.

PPS : Le fond du problème est que je veux déclencher un contrôle AJAX autocompleter de manière externe (à partir d'un élément cliquable) pour afficher ses suggestions, sans que les suggestions disparaissent immédiatement à cause de l'attribut blur sur l'élément d'entrée. Je veux donc vérifier dans le blur si un élément spécifique a été cliqué et, dans ce cas, ignore l'événement de flou.

1 votes

C'est une question intéressante dont j'aimerais connaître le raisonnement - c'est-à-dire pourquoi faites-vous cela ? Quel est le contexte ?

0 votes

Rahul et roosteronacid, j'ai mis à jour la question en réaction à vos commentaires (le PPS).

1 votes

Comme cette information est un peu ancienne, voyez ici pour une réponse plus récente : stackoverflow.com/questions/7096120/

96voto

Shog9 Points 82052

Hmm... Dans Firefox, vous pouvez utiliser explicitOriginalTarget pour tirer l'élément sur lequel on a cliqué. Je m'attendais à ce que toElement de faire la même chose 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" />

Attention : Cette technique permet no pour les changements de focalisation causés par tabulation à travers les champs avec le clavier, et ne fonctionne pas du tout dans Chrome ou Safari. Le gros problème de l'utilisation de activeElement (sauf dans IE) est qu'il n'est pas systématiquement mis à jour jusqu'à ce que après le site blur a été traité, et peut n'avoir aucune valeur valide pendant le traitement ! Ce problème peut être atténué par une variante de l'option 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é dans Chrome, IE et Firefox), à condition que Chrome ne mette pas l'accent sur les boutons qui sont a cliqué sur (par opposition à "onglet").

1 votes

Cela fait longtemps que je cherche quelque chose comme explicitOriginalTarget. Comment l'avez-vous découvert ?

3 votes

J'ai examiné l'objet de l'événement dans FireBug. Pour info, la propriété est spécifique à Mozilla, et documentée sur MDC : developer.mozilla.org/fr/DOM/event.explicitOriginalTarget

0 votes

Vous m'avez sauvé la vie ! Aujourd'hui, je me suis battu avec ce problème pendant des heures jusqu'à ce que je trouve cette astuce :) Merci, Joshua !

21voto

Michiel Borkent Points 11503

J'ai fini par résoudre le problème avec un timeout 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 aussi bien dans FF que dans IE.

12 votes

Est-ce que cela est considéré comme une mauvaise pratique dans le monde du javascript ?

1 votes

C'est un vieux poste mais j'ai la même question. Quoi qu'il en soit, c'est la seule chose qui semble faire le travail dans tous les navigateurs.

0 votes

Cette réponse m'a beaucoup aidé en résolvant un autre problème... Merci Michael !

17voto

user308436 Points 97

Il est possible d'utiliser l'événement mousedown du document au lieu du blur :

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

2voto

bmb Points 2995

Pouvez-vous inverser ce que vous vérifiez et quand ? Si vous vous souvenez de ce qui a été flouté en dernier :

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

et ensuite dans le onClick de votre span, appelez function() 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 a déjà eu lieu, donc il ne fera pas disparaître les suggestions.

2voto

matte Points 591

J'essaie également de faire en sorte que l'Autocompleter ignore le flou si un élément spécifique est cliqué et j'ai une solution qui fonctionne, mais uniquement pour Firefox en raison de 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);
                }
            }
        }
    );

Ce code enveloppe la méthode onBlur par défaut de l'Autocompleter et vérifie si le paramètre ignoreBlurEventElement est défini. S'il est défini, il vérifie à chaque fois si l'élément cliqué est ignoreBlurEventElement ou non. Si c'est le cas, l'autocompleteur n'appelle pas onBlur, sinon il appelle onBlur. Le seul problème avec cette méthode est qu'elle ne fonctionne qu'avec Firefox car la propriété explicitOriginalTarget est spécifique à Mozilla. J'essaie maintenant de trouver un autre moyen que d'utiliser explicitOriginalTarget. La solution que vous avez mentionnée nécessite d'ajouter manuellement le comportement onclick à l'élément. Si je ne parviens pas à résoudre le problème de explicitOriginalTarget, je pense que je suivrai votre solution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X