Quando um evento de 'borrão' ocorre, como posso descobrir qual o foco elemento fui * a *?

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

  •  02-07-2019
  •  | 
  •  

Pergunta

Suponha que eu anexar uma função blur para uma caixa de entrada HTML como esta:

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

Existe uma maneira de obter o ID do elemento que causou o evento blur ao fogo (o elemento que foi clicado) dentro da função? Como?

Por exemplo, suponha que eu tenho um período como este:

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

Se eu clique no período logo após o elemento de entrada tem o foco, o elemento de entrada vai perder seu foco. Como funciona o saber que era mySpan que foi clicado?

PS:. Se o evento onclick do intervalo ocorreria antes do evento onblur do elemento de entrada meu problema seria resolvido, porque eu poderia definir algum valor de status indicando um elemento específico foi clicado

PPS: O fundo deste problema é que eu quero acionar um controle AJAX autocompleter externamente (a partir de um elemento clicável) para mostrar as suas sugestões, sem as sugestões que desaparecem imediatamente porque do evento blur no elemento de entrada. Então, eu quero verificar na função blur se um elemento específico foi clicado, e se assim for, ignorar o evento borrão.

Foi útil?

Solução

Hmm ... No Firefox, você pode usar explicitOriginalTarget para puxar o elemento que foi clicado. Eu esperava toElement a fazer o mesmo para o IE, mas ele não aparece para trabalhar ... No entanto, você pode puxar o elemento recém-focalizada do 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" />

Aviso: Esta técnica faz não trabalho para foco mudanças causadas pela tabulação através de campos com o teclado, e não funciona em tudo em Chrome ou Safari. O grande problema com o uso de activeElement (exceto no IE) é que ele não é consistentemente atualizado até após o evento blur foi processado e pode não ter valor válido durante todo o processamento! Isto pode ser mitigado com uma variação de a técnica Michiel acabou usando :

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

Isso deve funcionar na maioria dos navegadores modernos (testado no Chrome, IE e Firefox), com a ressalva de que o Chrome não se concentram em botões que são clicado (vs. com guias para).

Outras dicas

2015 resposta : de acordo com UI Eventos , você pode usar relatedTarget propriedade do evento:

Usado para identificar um secundário EventTarget relacionada com um Focus evento, dependendo do tipo de evento.

Para blur eventos,

relatedTarget : receber foco.

Exemplo:

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 não vai apoiar relatedTarget até a versão 48 ( bug 962251 , MDN ).

Eu resolvi que, eventualmente, com um tempo limite sobre o evento onblur (graças aos conselhos de um amigo que não é StackOverflow):

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

Funciona tanto em FF e IE.

É possível usar o evento mousedown do documento em vez de borrão:

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

As instâncias tipo FocusEvent têm atributo relatedTarget, no entanto, até a versão 47 da FF, especificamente, este atributo retorna nulo, de 48 já funciona.

Você pode ver mais aqui .

Eu também estou tentando fazer Autocompleter ignorar borrar se um elemento específico clicado e ter uma solução de trabalho, mas somente para Firefox devido a 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);
                }
            }
        }
    );

Este código envolve método onBlur padrão de Autocompleter e verifica se os parâmetros ignoreBlurEventElement está definido. se estiver definido, ele verifica toda vez para ver se o elemento clicado é ignoreBlurEventElement ou não. Se for, Autocompleter não cal onBlur, senão ele chama onBlur. O único problema com isso é que ele só funciona no Firefox explicitOriginalTarget propriedade é Mozilla específico. Agora eu estou tentando encontrar uma maneira diferente de usar explicitOriginalTarget. A solução que você mencionou exige que você adicione comportamento onclick manualmente para o elemento. Se eu não posso conseguir resolver questão explicitOriginalTarget, eu acho que vai seguir a sua solução.

Você pode reverter o que você está verificando e quando? Isto é, se você lembre o que era turva passado:

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

e depois no onClick para o seu espaço, função de chamada () com dois objetos:

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

A sua função poderia então decidir se deve ou não acionar o controle Ajax.AutoCompleter. A função tem o objeto clicado e o objeto turva. O onBlur já aconteceu para que ele não vai fazer as sugestões desaparecer.

Use algo como isto:

var myVar = null;

E, em seguida, dentro de sua função:

myVar = fldID;

E, em seguida:

setTimeout(setFocus,1000)

E, em seguida:

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

código 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>

eu acho que ele não está possibe, com o IE, você pode tentar usar window.event.toElement, mas dos não funciona com o Firefox!

Como observado no esta resposta , você pode verificar o valor de document.activeElement. document é uma variável global, para que você não tem que fazer nenhuma mágica para usá-lo em sua onBlur manipulador:

function myOnBlur(e) {
  if(document.activeElement ===
       document.getElementById('elementToCheckForFocus')) {
    // Focus went where we expected!
    // ...
  }
}
  • document.activeElement poderia ser um nó pai (por exemplo nó corpo porque ela está numa fase de comutação temporário a partir de um alvo para outro), de modo que não é utilizável para o seu escopo
  • ev.explicitOriginalTarget nem sempre é valorizado

Portanto, a melhor maneira é usar onclick no evento corpo para a compreensão indiretamente seu nó (event.target) está no borrão

Editar: Uma maneira hacky para fazer isso seria criar uma variável que mantém o controle de foco para cada elemento que se preocupam. Então, se você se importa que o foco perdido 'myInput', definir uma variável para ele em foco.

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

Resposta Original: Você pode passar 'isto' para a função.

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

Eu sugiro usar variáveis ??globais blurfrom e blurto. Em seguida, configure todos os elementos que lhe interessam para atribuir a sua posição no DOM para a variável blurfrom quando perder o foco. Além disso, configure-os para que obtenha foco define a variável blurto a sua posição no DOM. Então, você poderia usar outra função completamente para analisar o blurfrom e dados blurto.

ter em mente, que a solução com explicitOriginalTarget não funciona para texto-input-to-text-input saltos.

tentar substituir os botões com o seguinte texto-entradas e você vai ver a diferença:

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

Eu tenho jogado com este mesmo recurso e descobri que FF, IE, Chrome e Opera têm a capacidade de fornecer o elemento de origem de um evento. Eu não testei Safari, mas meu palpite é que poderia ter algo similar.

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

Eu não gosto de usar tempo limite quando a codificação javascript para que eu iria fazê-lo da maneira oposta de Michiel Borkent. (Não tente o código por trás, mas você deve ter a idéia).

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

Na algo cabeça como que

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

Você pode corrigir IE com:

 event.currentTarget.firstChild.ownerDocument.activeElement

Parece que "explicitOriginalTarget" para FF.

Antoine E J

Eu escrevi um alternativa solução como fazer qualquer elemento focusable e "blurable".

É baseado em tornando um elemento como contentEditable e esconder visualmente e desativando o modo de edição própria:

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

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

DEMONSTRA

Nota: Testado no Chrome, Firefox e Safari (OS X). Não tenho certeza IE.


relacionadas: Eu estava procurando uma solução para VueJs, então para aqueles que interessados ??/ curioso como implementar essa funcionalidade usando directiva Vue Focusable, por favor dar uma olhada .

Obras em v66.x Google Chrome, Mozilla v59.x e Microsoft Edge ... Solução com jQuery.

I teste no Internet Explorer 9 e não é suportado.

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

Ties seu teste em versões outros Internet Explorer.

Eu vejo apenas hacks nas respostas, mas não há realmente uma solução embutida muito fácil de usar: Basicamente, você pode capturar o elemento foco como esta:

const focusedElement = document.activeElement

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

Desta forma:

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

Ou se você anexar o ouvinte através de JavaScript (jQuery, neste exemplo):

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

Editar : sorry. Eu descaracterizou a pergunta.


Eu acho que é facilmente possível via jQuery passando a referência do campo fazendo com que o evento onblur em "isto".
Por exemplo.

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

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

Graças
Monika

Você poderia fazê-lo como este:

<script type="text/javascript">
function myFunction(thisElement) 
{
    document.getElementByName(thisElement)[0];
}
</script>
<input type="text" name="txtInput1" onBlur="myFunction(this.name)"/>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top