Atrasar o evento de foco do jquery?

93

Eu gostaria de atrasar um evento de foco em jquery. Estou lendo um arquivo quando o usuário passa o mouse sobre um link ou rótulo. Não quero que esse evento ocorra imediatamente, caso o usuário esteja apenas movendo o mouse pela tela. Existe uma maneira de atrasar o disparo do evento?

Obrigado.

Código de exemplo:

$(function() {
    $('#container a').hover(function() {
        $('<div id="fileinfo" />').load('ReadTextFileX.aspx',
            {filename:'file.txt'},
            function() {
                $(this).appendTo('#info');
            }
         );
    },
        function() { $('#info').remove(); }
    });
});

ATUALIZAÇÃO: (14/01/09) Após adicionar o plugin HoverIntent, o código acima foi alterado para o seguinte para implementá-lo. Muito simples de implementar.

$(function() {
    hiConfig = {
        sensitivity: 3, // number = sensitivity threshold (must be 1 or higher)
        interval: 200, // number = milliseconds for onMouseOver polling interval
        timeout: 200, // number = milliseconds delay before onMouseOut
        over: function() {
            $('<div id="fileinfo" />').load('ReadTextFileX.aspx', {filename:'file.txt'},
                function() {
                   $(this).appendTo('#info');
                }
             );
        }, // function = onMouseOver callback (REQUIRED)
        out: function() { $('#info').remove();  } // function = onMouseOut callback (REQUIRED)
    }
    $('#container a').hoverIntent(hiConfig)
}
Brettski
fonte
1
Obrigado por fornecer o uso do hoverIntent
JavaKungFu

Respostas:

91

Use o plugin hoverIntent para jquery: http://cherne.net/brian/resources/jquery.hoverIntent.html

É absolutamente perfeito para o que você descreve e eu o usei em quase todos os projetos que exigiam a ativação do mouse sobre os menus, etc ...

Há uma pegadinha nessa abordagem, algumas interfaces são desprovidas de um estado de 'pairar', por exemplo. navegadores móveis como o safari no iphone. Você pode estar escondendo uma parte importante da interface ou navegação sem nenhuma maneira de abri-la em tal dispositivo. Você pode contornar isso com CSS específico do dispositivo.

Roborourke
fonte
Ou este plugin também funciona como um charme github.com/john-terenzio/jQuery-Hover-Delay
mica
50

Você precisa verificar um cronômetro ao pairar. Se ele não existir (ou seja, este é o primeiro foco), crie-o. Se ele existir (ou seja, este não é o primeiro foco), elimine-o e reinicie-o. Defina a carga útil do cronômetro para o seu código.

$(function() {
    var timer;

    $('#container a').hover(function() {
        if(timer) {
            clearTimeout(timer);
            timer = null
        }
        timer = setTimeout(function() {
            $('<div id="fileinfo" />').load('ReadTextFileX.aspx',
                {filename:'file.txt'},
                function() {
                    $(this).appendTo('#info');
                }
            );
        }, 500)
    },
    // mouse out
    });
});

Aposto que jQuery tem uma função que encerra tudo isso para você.

Edit : Ah sim, plugin jQuery para o resgate

Crescent Fresh
fonte
9
Obrigado de qualquer maneira por uma solução sem plug-in!
Jrgns
4
Eu adicionei um clearTimeout (timer); temporizador = nulo; no lado do mouseout, mas funcionou perfeitamente e evitou YAP (mais um plugin)
Andiih
@Andiih Boa chamada, e obrigado por me apresentar à sigla "YAP".
Jon
você provavelmente quer dizer debounce ()
Vitim.us
11

Concordo totalmente que o hoverIntent é a melhor solução, mas se você for um infeliz que trabalha em um site com um processo longo e demorado de aprovação de plug-ins jQuery, aqui está uma solução rápida e suja que funcionou bem para mim:

$('li.contracted').hover(function () {
    var expanding = $(this);
    var timer = window.setTimeout(function () {
        expanding.data('timerid', null);

            ... do stuff

    }, 300);
    //store ID of newly created timer in DOM object
    expanding.data('timerid', timer);
}, function () {
    var timerid = $(this).data('timerid');
    if (timerid != null) {
        //mouse out, didn't timeout. Kill previously started timer
        window.clearTimeout(timerid);
    }
});

Este é apenas para expandir um <li> se o mouse estiver nele por mais de 300 ms.

Matthew Millman
fonte
Obrigado, achei isso mais útil do que as outras respostas.
Ray
6

Você poderia usar uma chamada setTimeout () com um clearTimeout () no evento mouseout.

Dan Monego
fonte
1

Em 2016, a solução da Crescent Fresh não funcionou conforme o esperado para mim, então eu descobri o seguinte:

$(selector).hover(function() {
    hovered = true;
    setTimeout(function() {
        if(hovered) {
            //do stuff
        }
    }, 300); //you can pass references as 3rd, 4th etc. arguments after the delay

}, function() {
    hovered = false;
});
a teia
fonte
-2

Minha solução é fácil. Atrasar o menu aberto se o usuário mantiver o mouseenter em obj acima de 300 ms:

var sleep = 0;
$('#category li').mouseenter(function() {
    sleep = 1;
    $('#category li').mouseleave(function() {
        sleep = 0;
    });
    var ob = $(this);
    setTimeout(function() {                         
        if(sleep) {
            // [...] Example:
            $('#'+ob.attr('rel')).show();
        }
    }, 300);
});
onekamil
fonte