Quando si verifica un evento di "sfocatura", come posso sapere quale elemento attivo è passato da * a *?

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

  •  02-07-2019
  •  | 
  •  

Domanda

Supponiamo di allegare una funzione 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'attivazione dell'evento blur (l'elemento su cui è stato fatto clic) all'interno della funzione? Come?

Ad esempio, supponiamo che io abbia una durata come questa:

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

Se clicco sull'intervallo subito dopo l'attivazione dell'elemento di input, l'elemento di input perderà il focus. Come fa la funzione a sapere che è stato selezionato mySpan ?

PS: se l'evento onclick dell'intervallo si verificasse prima dell'evento onblur dell'elemento di input, il mio problema sarebbe risolto, perché potrei impostare un valore di stato che indica che è stato fatto clic su un elemento specifico.

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

È stato utile?

Soluzione

Hmm ... In Firefox, puoi usare esplicativoOriginalTarget per estrarre l'elemento su cui hai fatto clic. Mi aspettavo che toElement facesse lo stesso per IE, ma non sembra funzionare ... Tuttavia, puoi estrarre l'elemento appena focalizzato dal 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" />

Avvertenza: questa tecnica non funziona per i cambiamenti di focus causati da tabulazione attraverso i campi con la tastiera e non funziona affatto in Chrome o Safari. Il grosso problema con l'utilizzo di activeElement (tranne in IE) è che non viene costantemente aggiornato fino a quando dopo l'evento blur è stato elaborato e potrebbe non hanno alcun valore valido durante l'elaborazione! Questo può essere mitigato con una variazione su la tecnica che Michiel ha finito per usare :

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

Questo dovrebbe funzionare nella maggior parte dei browser moderni (testato in Chrome, IE e Firefox), con l'avvertenza che Chrome non si concentra sui pulsanti cliccati (rispetto a quelli a schede).

Altri suggerimenti

Risposta 2015 : secondo Eventi UI , puoi utilizzare la proprietà relatedTarget dell'evento:

  

Utilizzato per identificare un EventTarget secondario in relazione a un focus   evento, a seconda del tipo di evento.

Per gli eventi blur ,

  

RelatedTarget : target evento ricevendo focus.

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

Alla fine l'ho risolto con un timeout sull'evento onblur (grazie al consiglio di un amico che non è StackOverflow):

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

Funziona sia in FF che IE.

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

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

Le istanze di tipo FocusEvent hanno l'attributo relatedTarget , tuttavia, fino alla versione 47 dell'FF, in particolare, questo attributo restituisce null, poiché 48 funziona già.

Puoi vedere di più qui .

Sto anche cercando di fare in modo che Autocompleter ignori la sfocatura se un elemento specifico ha fatto clic e ha una soluzione funzionante, ma solo per Firefox a causa di esplicitoOriginalTarget

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 racchiude il metodo onBlur predefinito di Autocompleter e verifica se i parametri ignoreBlurEventElement sono impostati. se è impostato, controlla ogni volta per vedere se l'elemento cliccato è ignoreBlurEventElement o no. In tal caso, il completamento automatico non si chiama onBlur, altrimenti chiama onBlur. L'unico problema è che funziona solo in Firefox perché la proprietà esplicativaOriginalTarget è specifica di Mozilla. Ora sto cercando di trovare un modo diverso rispetto all'uso di esplicativo originale. La soluzione che hai citato richiede di aggiungere manualmente il comportamento onclick all'elemento. Se non riesco a risolvere il problema esplicativo dell'originale, credo che seguirò la tua soluzione.

Puoi invertire ciò che stai controllando e quando? Cioè se ricordi ciò che è stato sfocato per ultimo:

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

e quindi in onClick per il tuo intervallo, chiama la funzione () con entrambi gli oggetti:

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

La tua funzione potrebbe quindi decidere se attivare o meno il controllo Ajax.AutoCompleter. La funzione ha l'oggetto cliccato e l'oggetto sfocato. OnBlur è già successo, quindi non farà sparire i suggerimenti.

Usa qualcosa del genere:

var myVar = null;

E poi all'interno della 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>

penso che non sia possibile, con IE puoi provare a usare window.event.toElement , ma non funziona con firefox!

Come indicato in questa risposta , puoi controllare il valore di document.activeElement . document è una variabile globale, quindi non devi fare alcun incantesimo per usarlo nel tuo gestore onBlur:

function myOnBlur(e) {
  if(document.activeElement ===
       document.getElementById('elementToCheckForFocus')) {
    // Focus went where we expected!
    // ...
  }
}
  • document.activeElement potrebbe essere un nodo padre (ad esempio nodo del corpo perché è in una fase temporanea che passa da una destinazione a un'altra), quindi non è utilizzabile per il tuo ambito
  • ev.explicitOriginalTarget non viene sempre valutato

Quindi il modo migliore è usare onclick on body event per capire indirettamente che il tuo nodo (event.target) è su blur

Modifica Un modo bizzarro per farlo sarebbe quello di creare una variabile che tenga traccia del focus per ogni elemento a cui tieni. Quindi, se ti interessa che "myInput" abbia perso la concentrazione, imposta una variabile su di essa.

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

Risposta originale: Puoi passare "this" alla funzione.

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

Suggerisco di usare le variabili globali blurfrom e blurto. Quindi, configura tutti gli elementi che ti interessano per assegnare la loro posizione nel DOM alla sfocatura variabile quando perdono il focus. Inoltre, configurali in modo tale da ottenere lo stato attivo che imposta la variabile blurto sulla loro posizione nel DOM. Quindi, è possibile utilizzare un'altra funzione del tutto per analizzare la sfocatura e la sfocatura nei dati.

tieni presente che la soluzione con esplicitoOriginalTarget non funziona per i salti da input di testo a input di 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">

Ho giocato con questa stessa funzione e ho scoperto che FF, IE, Chrome e Opera hanno la capacità di fornire l'elemento sorgente di un evento. Non ho testato Safari ma credo che potrebbe avere qualcosa di simile.

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

Non mi piace usare il timeout durante la codifica di JavaScript, quindi lo farei nel modo opposto di Michiel Borkent. (Non ho provato il codice dietro ma dovresti avere l'idea).

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

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

Puoi correggere IE con:

 event.currentTarget.firstChild.ownerDocument.activeElement

Sembra " esplicativoOriginalTarget " per FF.

Antoine e J

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

Si basa sulla creazione di un elemento come contentEditable e nascondendolo visivamente e disabilitando la modalità di modifica stessa:

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

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

DEMO

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


Correlato: stavo cercando una soluzione per VueJs, quindi per coloro che erano interessati / curiosi su come implementare tale funzionalità usando la direttiva Vue Focusable, per favore dai un'occhiata .

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

  

Ho testato in Internet Explorer 9 e non 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.

Nelle risposte vedo solo hack, ma in realtà esiste una soluzione integrata molto facile da usare: Fondamentalmente puoi catturare l'elemento focus in questo modo:

const focusedElement = document.activeElement

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

In questo modo:

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

O se si collega l'ascoltatore tramite JavaScript (jQuery in questo esempio):

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

Modifica : scusa. Ho letto male la domanda.


Penso che sia facilmente possibile tramite jquery passando il riferimento del campo che causa l'evento onblur in "questo".
Ad esempio

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

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

Grazie
Monika

Potresti farlo in questo modo:

<script type="text/javascript">
function myFunction(thisElement) 
{
    document.getElementByName(thisElement)[0];
}
</script>
<input type="text" name="txtInput1" onBlur="myFunction(this.name)"/>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top