Pergunta

Em uma aplicação web que estou trabalhando, estou capturando onBeforeUnload para perguntar ao usuário se ele realmente quer sair.

Agora, se ele decidir ficar, há uma série de coisas que eu gostaria de fazer. O que eu estou tentando descobrir é que ele realmente escolheu para estadia.

I pode, naturalmente, declarar uma SetTimeout para "x" segundos, e se isso incêndios, então isso significaria que o usuário ainda está lá (porque não se descarregada). O problema é que o usuário pode tomar qualquer tempo para decidir se quer permanecer ou não ...

Eu estava em primeiro lugar na esperança de que, enquanto o diálogo estava mostrando, chamadas SetTimeOut não iria fogo, para que eu pudesse definir um tempo limite para um curto período de tempo e só tinha fogo se o usuário escolheu para ficar. No entanto, o tempo limite do fogo enquanto o diálogo é mostrada, de modo que não funciona.

Outra idéia que eu tentei é capturar mouseMoves na janela / documento. Enquanto o diálogo é mostrada, mouseMoves fato não fogo, exceto por uma exceção estranha que realmente se aplica ao meu caso, para que não quer trabalhar.

Alguém pode pensar em outra maneira de fazer isso?

Obrigado!


(No caso de você estiver curioso, a razão capturar mouseMove não funciona é que eu tenho um IFrame na minha página, que contém um site de outro domínio. Se no momento da descarga da página, o foco está dentro do IFrame, enquanto os shows de diálogo, então eu recebo o evento MouseMove disparando uma vez quando o mouse se move de dentro do iframe para o exterior (pelo menos no Firefox). isso é provavelmente um bug, mas ainda assim, é muito provável que vai acontecer na nossa caso, por isso não posso usar este método).

Foi útil?

Solução

O que eu acabei fazendo foi ligar para o evento clique para o meu documento, e uma vez eu recebi um clique eu considerava o usuário tinha ficado.

Não é uma boa solução, na maioria dos casos (se você é um DiggBar) você terá lotes de falsos negativos (as pessoas vão ter ficado e você nunca saberá), mas no nosso caso, faz todo o sentido, porque as pessoas interagem fortemente com o nosso site, não só com os sites emolduradas.

esentially, meu código faz isso ...

function OnBeforeUnload() {
    Event.observe(document, "click", UserStayed);
    if (IConsiderTheIFrameMightBeTryingToPopOut) {
        return "The site is trying to escape. Do you want to stay?";
    }
}

function UserStayed() {
Event.stopObserving(document, "click", UserStayed);
    // New we know the user is still with us for sure.
}

Outras dicas

Eu estive pesquisando esta pergunta on-line para os últimos dias e a resposta, invariavelmente, é "não" você não pode dizer, com certeza, que um usuário permaneceu ou à esquerda (que não seja o fato de que seus quits app funcionar se as folhas de usuários). Eu odeio "não" como resposta. Eu vim com o seguinte utilitário.

var OnBeforeUnload = (function(){
    var
    FDUM = new Function,
    AFFIRM = function(){ return true; };

    var _reg = function(msg,opts){
        opts = opts || {};
        var
            pid = null,
            pre = typeof opts.prefire == 'function' ? opts.prefire : FDUM,
            callback = typeof opts.callback == 'function' ? opts.callback : FDUM,
            condition = typeof opts.condition == 'function' ? opts.condition : AFFIRM;

        window.onbeforeunload = function(){
            return condition() ? (pre(),setTimeout(function(){ pid = setTimeout(callback,20); },1),msg) : void 0; 
        }

        window.onunload = function(){ clearTimeout(pid); };

    }

    var _unreg = function(){ window.onbeforeunload = null;  }

    return {
        register : _reg,
        unregister : _unreg
    };

})();

Assim, uma chamada como

OnBeforeUnload.register('Hello!',{ 
    condition:function_that_returns_true_to_fire_event_false_to_ignore,
    prefire:function_to_call_on_page_exit_attempt, 
    callback:function_to_call_if_user_stays
});

condição será chamado dentro do manipulador para ver se ele deve ativar ou não. Se assim for, prefire é executado antes da pop-up é mostrado para o usuário (você pode querer pausar um vídeo) e de retorno de chamada ocorrerá somente se a estadias de usuários.

A minha lógica foi iniciar um setTimeout no corpo do manipulador de eventos. O setTimeout não será executado até que o usuário pressionar um dos botões. Após o fazem, é acionado imediatamente. O setTimeout, neste caso, não chama o retorno de chamada, mas uma função de proxy que executa outro tempo de espera para a chamada de retorno com um atraso de 20ms. Se as estadias do usuário na página, o callback executa. Se não, então outro manipulador está anexado a onunload que limpa o tempo limite que irá chamar o callback, garantindo que o retorno nunca é chamado. Eu só tive a oportunidade de verificá-lo no Firefox, IE e Chrome, mas ele tem trabalhado até agora em todos os três sem um soluço.

Espero que isso ajude as pessoas tão frustrado quanto eu era pela patente "não" dado universalmente a esta pergunta. Este código pode não ser perfeito, mas eu acho que é no caminho certo.

Este é o top hit para este tipo de pergunta, e eu conheço o caso específico (a partir de 8 anos atrás) não poderia usar esta solução porque estava em um iFrame, mas quaisquer comers futuras provavelmente será mais ajudado pela resposta abaixo do que os acima:

Você pode facilmente dizer se eles fiquei com um ouvinte de eventos corpo, acho mousemove e keydown combinado deve ser suficiente.

Para dizer se eles à esquerda, você vai precisar de algumas coisas do lado do servidor.

Ao todo, ele vai ser algo como isto (Você terá que preencher as chamadas AJAX para o servidor você mesmo):

window.addEventListener("beforeunload", function(event){
    //tell your server they are attempting to leave
    var tryLeaveID = serverLogAttempToLeave();

    //an element with giant letters and warning text, because you can no longer set text on the alert box
    var unsavedWarning = document.getElementById("unsavedChangesWarning");
    unsavedWarning.style.display = "block";

    var onStay = function() {
        //if they stay, tell your server so
        serverRevokeAttemptToLeave(tryLeaveID);
        unsavedWarning.style.display = "none";
        document.body.removeEventListener("mousemove", onStay);
        document.body.removeEventListener("keydown", onStay);
    }

    document.body.addEventListener("mousemove", onStay);
    document.body.addEventListener("keydown", onStay);


    var dialogText =  "undisplayed text";
    event.returnValue = dialogText;
    return dialogText;
});

No lado do servidor, você vai ter que usar algo feio, um temporizador. Faça uma pilha de tentativas de deixar, e removê-los ou como solicitado em permanência, ou depois de um minuto ou assim como uma licença confirmada. Eu não posso imaginar qualquer caso em saber se o usuário esquerda é mais sensível ao tempo do que alguns minutos, mas se você tiver um, por favor comentário porque eu gostaria de pensar sobre isso.

Por que não usar o método que StackOverflow faz, onde você obtém uma caixa de pop-up que permite que você faça a escolha:

Você tem certeza que quer sair desta página?

Você iniciou escrever ou editar um post.

Pressione OK para continuar ou Cancelar para permanecer na página atual

Então, não importa quanto tempo demora. Se clicar em um botão, eles deixam. Se eles clique no outro, eles ficam.

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