Pergunta

Esta questão já tem uma resposta aqui:

Eu gostaria de algum código Javascript para ser executado quando o mouse deixa a janela do navegador. Eu só preciso apoiar Safari (WebKit).

Eu tentei colocar um manipulador mouseout na janela. Esse manipulador é chamado de forma confiável quando o mouse deixa a janela do navegador. Mas por causa da borbulhando também é chamado quando o mouse se move entre elementos no documento. Eu não consigo descobrir como determinar quando o mouse tem realmente deixou a janela e quando só se moveu entre os elementos.

Quando as folhas do rato da janela, exatamente é gerado um evento, e as aparece elemento de destino a ser o elemento o rato foi realmente acabou. Assim, verificando para ver se o elemento de destino é a janela ou documento não funciona. E envolvendo toda a página em um contendo div invisível não quer trabalhar: se o div é invisível, então o rato nunca será sobre ele, por isso não muda nada.

(A mesma coisa acontece se eu colocar o manipulador de documento ou document.body, exceto que surpreendentemente document.body não recebe eventos mouseover / mouseout quando o mouse entra ou sai uma parte vazia da janela, como o vazio espaço vertical criado por absolutamente posicionar um elemento com base:.. 0 Para que o espaço, documento ea janela vai ter mouseover / eventos mouseout com o alvo sendo , mas document.body não)

Algumas idéias que eu tive:

  • Em cada evento mouseout, obter a posição real do mouse e ver se ele é de fato sobre a janela. Mas eu não sei se isso é realmente possível e parece que seria complicado para eliminar todas as condições de corrida.
  • Também registrar um manipulador de mouseover e detectar casos em que mouseout não é precedido por (ou seguido logo por a) um mouseover. Mas isso exigiria um temporizador.

Nós usamos prototype.js tão idealmente eu gostaria de expressar a solução em termos de Event.observe de protótipo, mas eu posso descobrir isso parte.

Obrigado por todas as sugestões!

Foi útil?

Solução

RESUMO: Isto pode ser feito de forma limpa, verificando a propriedade relatedTarget durante o evento mouseout. Se relatedTarget não é uma criança de documento, em seguida, o rato acabado de sair da janela. É fácil de fazer sozinho, mas se você não quer, algumas bibliotecas (Mootools, futuro Prototype ..) já cozido em termos de funcionalidade, e outros (protótipo atual) têm extensões disponíveis. No IE, você poderia passar a usar mouseleave, que é uma versão não-borbulhante de mouseout.

Detalhes:

IE tem eventos chamados mouseenter e mouseleave que são versões não borbulhando de mouseover e mouseout. Outros navegadores não, mas se o fizessem, estabelecendo um ouvinte mouseleave na janela ou documento faria o truque.

Um senhor chamado Ken Snyder vem para o resgate:

Em um mouseover, a relatedTarget referências de propriedade do nó de qual o ponteiro veio. Em um mouseout, as referências de propriedade relatedTarget o nó ao qual o ponteiro went.On qualquer caso, o escopo é o nó que o evento é attached.When o relatedTarget é um não filho do currentTarget, um evento mouseover é equivalente a um evento mouseenter e uma evento mouseout é equivalente a um evento mouseleave.

- http://kendsnyder.com/archives/6-MouseEnter- e-MouseLeave.html

Isto torna possível implementar mouseenter e mouseleave em outros navegadores. Na verdade, Ken fornece mesmo código Prototype a fazê-lo: http://kendsnyder.com/sandbox/enterleave /MouseEnterLeave.js

Duroth destacou em comentários que MooTools já inclui algo semelhante. (Graças Duroth.) Parece que o lançamento Prototype próximo (1.6.2) pode incluir essa funcionalidade, mas eu não consigo encontrar nada definido.

Outras dicas

Usando apenas javascript, nenhum protótipo ou jQuery etc.

<html>
<head>
<script type="text/javascript">
  var mouseX = 0;
  var mouseY = 0;
  var counter = 0;
var mouseIsIn = true;
function wireEvent() {
window.addEventListener("mouseout",
    function(e){
        mouseX = e.pageX;
        mouseY = e.pageY;
        if ((mouseY >= 0 && mouseY <= window.innerHeight)
        && (mouseX >= 0 && mouseX <= window.innerWidth))
            return;
        //do something for mouse out
        counter++;
        mouseIsIn = false;
        document.getElementById('in_out').innerHTML='out' + counter;
    },
    false);
window.addEventListener("mouseover",
    function(e){
        if(mouseIsIn)
            return;
        //do something for mouse over
        counter++;
        mouseIsIn = true;
        document.getElementById('in_out').innerHTML='in' + counter;
    },
    false);
}
</script> 
</head>
<body onload="wireEvent();">
<div id="in_out">&nbsp;</div>
<div style="width:300px; height: 200px; background: red;">Dummy element</div>
</body>
</html>

UPDATE:
verificação adicional para a posição do mouse sobre mouseout desencadeada quando se deslocam in / out elementos dentro do corpo. Se é dentro da janela, evento mouseout não é acionado.
Também introduziu uma bandeira para o estado atual do mouse 'em' ou 'out' usando mouseIsIn. Se é true, mouseover não será desencadeada também.

Talvez você pode definir um ouvinte para mouseover e mouseout document, body ou algum outro elemento que envolve todo o documento, e usar isso (salvando que isso aconteceu) como um gatilho para determinar se ele é um mouseout válido na janela?

Na falta deste, a sua primeira ideia (sobre check posição) deve funcionar muito bem. Qualquer evento passa ao longo do X / Y o evento ocorreu. Se é nada mais do que a altura / largura da janela, você deixou a janela real. Se é algo negativo, você deixou a janela. E, possivelmente, se é exatamente a altura / largura ou exatamente top: 0 ou esquerda:. 0, então você deixou a janela

Quando o mouse sai de qualquer elemento, incluindo a janela, o objeto de janela irá disparar um evento mouseout e passar o objeto event junto com ele.

Um dos itens do objeto de evento é chamado toElement, que é um ponteiro para o elemento o rato acabado de entrar quando deixou o antigo. Mas quando as folhas do rato a janela, não existe tal toElement assim que este item torna-se null.

Ao testar se ou não este item é null em um evento mouseout, você pode dizer se o mouse esquerda da janela. Aqui está o código:

window.onmouseout=function(event){ 
  if(event.toElement===null) console.log('the mouse left the window'); 
}

Seu problema vem de eventos mouseout sendo gerados para elementos dentro da janela, que, em seguida, borbulhar, conforme descrito na eventos W3C especificação . Você pode verificar qual elemento o evento foi realmente demitido em:

function mouseoutFunction(event) {
  event = event || window.event;
  var sender = event.srcElement || event.target;
}

Aqui está a minha solução baseada em um temporizador. O temporizador aqui é basicamente usado para dar uma chance para outros manipuladores de eventos (especificamente, onmouseover) para executar antes de decidir que o mosue está fora da janela. O tempo limite de 1 ms (na verdade em torno de 33ms, existe uma resolução mínima temporizador) dá um pouco de tempo para o mouseover ocorrer se ainda não tem.

var inWin=0;
window.onmouseout = function(e)
{
   inWin--;
   setTimeout(checkIfOut, 1);
}
window.onmouseover = function(e)
{
   inWin++;
}

function checkIfOut()
{
   if(!inWin)
   {
     //Yay! Mouse is out of the window (probably)
   }
}

Você pode usar onmouseout evento em uma janela em vez

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top