[javascript] Quando si verifica un evento "sfocato", come posso scoprire quale elemento è stato attivato per la messa a fuoco * su *?



Answers

Risposta 2015 : in base agli eventi dell'interfaccia utente , è possibile utilizzare la proprietà relatedTarget dell'evento:

Utilizzato per identificare un EventTarget secondario relativo a un evento Focus, in base al tipo di evento.

Per gli eventi blur ,

relatedTarget : destinazione dell'evento che riceve attenzione.

Esempio:

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 non supporterà relatedTarget fino alla versione 48 ( bug 962251 , MDN ).

Question

Supponiamo che allega una funzione di blur a una casella di input HTML come questa:

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

C'è un modo per ottenere l'ID dell'elemento che ha causato l'evento di blur (l'elemento su cui è stato fatto clic) all'interno della funzione? Come?

Ad esempio, supponiamo di avere un'estensione del genere:

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

Se faccio clic sullo span subito dopo l'attivazione dell'elemento di input, l'elemento di input perderà il focus. Come fa la funzione a sapere che è stato fatto clic su mySpan ?

PS: se l'evento onclick dello span dovesse verificarsi prima dell'evento onblur dell'elemento input, il mio problema sarebbe risolto, perché potrei impostare un valore di stato che indica che un elemento specifico è stato cliccato.

PPS: lo sfondo di questo problema è che voglio attivare un controllo del completamento automatico AJAX esternamente (da un elemento cliccabile) per mostrare i suoi suggerimenti, senza che i suggerimenti scompaiano immediatamente a causa dell'evento blur sull'elemento di input. Quindi voglio controllare la funzione blur se è stato fatto clic su un elemento specifico e, in tal caso, ignorare l'evento sfocatura.




Come indicato in questa risposta , è possibile verificare il valore di document.activeElement . document è una variabile globale, quindi non devi fare magie per usarlo nel tuo gestore onBlur:

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



tieni presente che la soluzione con explicitOriginalTarget non funziona per i salti di input testo-input-testo.

prova a sostituire i pulsanti con i seguenti input di testo e vedrai la differenza:

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



Modifica: un modo hacky per farlo sarebbe quello di creare una variabile che tenga traccia di messa a fuoco per ogni elemento che ti interessa. Quindi, se ti interessa che "myInput" abbia perso la messa a fuoco, imposta una variabile su di essa.

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

Risposta originale: puoi passare "questo" alla funzione.

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



È possibile utilizzare l'evento Mousedown del documento anziché la sfocatura:

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



Usa qualcosa del genere:

var myVar = null;

E poi dentro la tua funzione:

myVar = fldID;

E poi:

setTimeout(setFocus,1000)

E poi:

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

Codice finale:

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



Sto anche cercando di far sì che l'autocompletatore ignori la sfocatura se un elemento specifico ha fatto clic e ha una soluzione funzionante, ma solo per Firefox a causa di 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);
                }
            }
        }
    );

Questo codice avvolge il metodo onBlur predefinito di Autocompleter e controlla se sono impostati i parametri ignoreBlurEventElement. se è impostato, controlla ogni volta per vedere se l'elemento cliccato ignoraBlurEventElement o no. Se lo è, l'autocompletatore non esegue onlurl, altrimenti chiama onBlur. L'unico problema è che funziona solo in Firefox perché la proprietà explicitOriginalTarget è specifica per Mozilla. Ora sto cercando di trovare un modo diverso rispetto a usare explicitOriginalTarget. La soluzione che hai menzionato richiede di aggiungere manualmente il comportamento onclick all'elemento. Se non riesco a risolvere il problema di UnknownOriginalTarget, suppongo che seguirò la tua soluzione.





Penso che sia facilmente possibile tramite jquery passando il riferimento del campo che causa l'evento onblur in "this".
Per es

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

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

Grazie
Monika




Funziona su Google Chrome v66.x, Mozilla v59.x e Microsoft Edge ... Soluzione con jQuery.

Eseguo il test in Internet Explorer 9 e non sono supportato.

$("#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
     }
});

Commenta il tuo test in altre versioni di Internet Explorer.




Ho scritto una soluzione alternativa su come rendere qualsiasi elemento focalizzabile e "sfuocato".

Si basa sul rendere un elemento come contentEditable e nasconderlo visivamente e disabilitare la modalità di modifica stessa:

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

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

DEMO

Nota: testato in Chrome, Firefox e Safari (OS X). Non sono sicuro di IE.

Correlati: Stavo cercando una soluzione per VueJs, quindi per coloro che sono interessati / curiosi su come implementare tale funzionalità usando la direttiva Vue Focusable, per favore date un'occhiata .




Non mi piace usare il timeout durante la codifica di javascript, quindi farei il contrario di Michiel Borkent. (Non ho provato il codice ma dovresti avere l'idea).

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

In testa qualcosa del genere

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





Links