Lorsqu'un événement de "flou" se produit, comment puis-je savoir quel élément est concentré * sur *?

StackOverflow https://stackoverflow.com/questions/121499

  •  02-07-2019
  •  | 
  •  

Question

Supposons que j'attache une fonction blur à une zone de saisie HTML comme celle-ci:

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

Existe-t-il un moyen d'obtenir l'ID de l'élément qui a provoqué le déclenchement de l'événement blur (l'élément sur lequel vous avez cliqué) à l'intérieur de la fonction? Comment?

Par exemple, supposons que j'ai une étendue comme celle-ci:

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

Si je clique sur l'étendue juste après que l'élément d'entrée ait le focus, l'élément d'entrée perdra son focus. Comment la fonction sait-elle que c'est sur mySpan que vous avez cliqué?

PS: si l'événement onclick de la plage se produisait avant l'événement onblur de l'élément d'entrée, mon problème serait résolu car je pouvais définir une valeur d'état indiquant qu'un élément spécifique avait été cliqué.

PPS: Ce problème a pour origine le fait que je souhaite déclencher un contrôle AJAX autocompleter en externe (à partir d'un élément cliquable) pour afficher ses suggestions, sans que celles-ci ne disparaissent immédiatement à cause de l'événement blur . l'élément d'entrée. Je souhaite donc vérifier dans la fonction blur si un élément spécifique a été cliqué et, le cas échéant, ignorer l'événement de flou.

Était-ce utile?

La solution

Hmm ... Dans Firefox, vous pouvez utiliser explicitOriginalTarget pour extraire l'élément sur lequel l'utilisateur a 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 récemment ciblé 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 ne fonctionne pas pour les changements de focus causés par la tabulation à travers les champs avec le clavier, et ne fonctionne pas du tout dans Chrome ou Safari. Le gros problème lié à l’utilisation de activeElement (sauf dans IE) est qu’il n’est pas mis à jour de manière cohérente avant après que l'événement blur a été traité et n'a aucune valeur valide pendant le traitement! Cela peut être atténué par une variation sur la technique utilisée par Michiel :

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), en précisant que Chrome ne met pas l'accent sur les boutons sur lesquels cliquez sur (plutôt que sur les onglets).

Autres conseils

Réponse de 2015 : selon Événements d'interface utilisateur , vous pouvez utiliser propriété relatedTarget :

  

Utilisé pour identifier un EventTarget secondaire en rapport avec un focus   événement, en fonction du type d’événement.

Pour les flous ,

  

relatedTarget : cible d'événement recevant le focus.

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

Remarque Firefox ne supportera pas relatedTarget avant la version 48 ( bug 962251 , MDN ).

Je l'ai finalement résolu avec un dépassement de délai sur l'événement onblur (grâce aux conseils d'un ami autre que 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.

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

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

Les instances de type FocusEvent ont l'attribut relatedTarget . Toutefois, jusqu'à la version 47 du fichier FF, cet attribut renvoie null, et 48 fonctionne déjà.

Vous pouvez voir plus de ici .

J'essaie également de faire en sorte qu'Autocompleter ignore le flou si un élément spécifique a cliqué et a une solution opérationnelle, 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 encapsule la méthode onBlur par défaut d'Autocompleter et vérifie si les paramètres ignoreBlurEventElement sont définis. s'il est défini, il vérifie à chaque fois si l'élément cliqué est ignoreBlurEventElement ou non. Si c'est le cas, Autocompleter n'appelle pas OnBlur, sinon il appelle onBlur. Le seul problème avec cela est que cela ne fonctionne que dans Firefox car la propriété explicitOriginalTarget est spécifique à Mozilla. Maintenant, j'essaie de trouver un moyen différent d'utiliser explicitOriginalTarget. La solution que vous avez mentionnée vous oblige à ajouter manuellement le comportement onclick à l'élément. Si je ne parviens pas à résoudre le problème explicitOriginalTarget, je suppose que je suivrai votre solution.

Pouvez-vous inverser ce que vous vérifiez et quand? Si vous vous rappelez ce qui était flou en dernier:

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

puis dans le onClick de votre extension, 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 contient les objets cliqués et l’objet flou. OnBlur a déjà eu lieu, il ne fera donc pas disparaître les suggestions.

Utilisez quelque chose comme ceci:

var myVar = null;

Et ensuite dans votre fonction:

myVar = fldID;

Et ensuite:

setTimeout(setFocus,1000)

Et ensuite:

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 cela ne fonctionne pas avec firefox!

Comme indiqué dans la réponse , vous pouvez vérifier la valeur de document.activeElement . document est une variable globale, vous n'avez donc pas besoin de 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 peut être un nœud parent (par exemple, un nœud de corps car il se trouve dans une phase de commutation temporaire d'une cible à une autre), de sorte qu'il n'est pas utilisable pour votre portée
  • ev.explicitOriginalTarget n'est pas toujours valorisé

Le meilleur moyen consiste donc à utiliser l'événement onclick on body pour comprendre indirectement que votre nœud (event.target) est flou

.

Modifier: Une façon simple de le faire serait de créer une variable qui garde la trace de chaque élément qui vous tient à cœur. Donc, si vous vous souciez de la perte de focus de 'myInput', définissez une variable sur focus.

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

Réponse originale: Vous pouvez passer "this" à la fonction.

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

Je suggère d'utiliser des variables globales blurfrom et blurto. Ensuite, configurez tous les éléments qui vous intéressent pour attribuer leur position dans le DOM à la variable blurfrom lorsqu’ils perdent la mise au point. En outre, configurez-les pour que le focus soit défini sur la variable blurto sur leur position dans le DOM. Vous pouvez ensuite utiliser une autre fonction pour analyser les données de flou et de blurto.

N'oubliez pas que la solution avec explicitOriginalTarget ne fonctionne pas pour les sauts entre entrées de 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">

Je jouais avec cette même fonctionnalité et découvrais que FF, IE, Chrome et Opera avaient la possibilité de fournir l’élément source d’un événement. Je n’ai pas testé Safari, mais j’imagine qu’il 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 timeout pour coder javascript, donc je le ferais à l'inverse de 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

Cela ressemble à "explicitOriginalTarget" pour FF.

Antoine et J

J'ai écrit à la solution alternative comment rendre tout élément focalisable et "blurable". / p>

Cela consiste à transformer un élément en contentEditable , à le masquer visuellement et à désactiver le mode d'édition lui-même:

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

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

DEMO

Remarque: testé sous Chrome, Firefox et Safari (OS X). Pas sûr de IE.

Related: Je recherchais une solution pour VueJs, donc pour ceux qui sont intéressés / curieux comment implémenter une telle fonctionnalité à l'aide de la directive Vue Focusable, veuillez jetez un coup d'œil .

Fonctionne dans Google Chrome v66.x, Mozilla v59.x et Microsoft Edge ... Solution avec jQuery.

  

Je teste dans Internet Explorer 9 et n'est pas pris en charge.

$("#YourElement").blur(function(e){
     var InputTarget =  $(e.relatedTarget).attr("id"); // GET ID Element
     console.log(InputTarget);
     if(target == "YourId") { // If you want validate or make a action to specfic element
          ... // your code
     }
});

Commentez votre test dans d'autres versions d'Internet Explorer.

Je ne vois que des hacks dans les réponses, mais il existe en fait une solution intégrée très facile à utiliser: En gros, vous pouvez capturer l’élément de focus comme ceci:

const focusedElement = document.activeElement

https://developer.mozilla.org/en -US / docs / Web / API / DocumentOrShadowRoot / activeElement

De cette façon:

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

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

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

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


Je pense que c'est facilement possible via jQuery en passant la référence du champ à l'origine de 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)"/>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top