Domanda

In un'app Web a cui sto lavorando, sto catturando su Prima dello scaricamento per chiedere all'utente se veramente vuole uscire.

Ora, se decide di restare, ci sono un certo numero di cose che mi piacerebbe fare. Quello che sto cercando di capire è che ha davvero scelto di restare.

Posso ovviamente dichiarare un SetTimeout per " x " secondi, e se ciò si attiva, significa che l'utente è ancora lì (perché non siamo stati scaricati). Il problema è che l'utente può impiegare qualsiasi momento per decidere se rimanere o meno ...

Prima speravo che mentre la finestra di dialogo fosse visualizzata, le chiamate SetTimeout non si attivassero, quindi avrei potuto impostare un timeout per un breve periodo e si sarebbe attivato solo se l'utente avesse scelto di rimanere. Tuttavia, i timeout eseguono vengono attivati ??mentre viene visualizzata la finestra di dialogo, quindi non funziona.

Un'altra idea che ho provato è catturare mouseMoves nella finestra / documento. Mentre viene mostrata la finestra di dialogo, mouseMoves in effetti non si attiva, ad eccezione di una strana eccezione che si applica davvero al mio caso, quindi non funzionerà neanche.

Qualcuno può pensare ad un altro modo per farlo?

Grazie!


(Nel caso tu sia curioso, il motivo per cui catturare mouseMove non funziona è che ho un IFrame nella mia pagina, contenente un sito da un altro dominio. Se al momento dello scarico della pagina, lo stato attivo è all'interno del IFrame, mentre la finestra di dialogo mostra, quindi ottengo l'evento MouseMove che attiva ONCE quando il mouse si sposta dall'interno dell'IFrame verso l'esterno (almeno in Firefox). Probabilmente è un bug, ma è molto probabile che accada nel nostro caso, quindi non posso usare questo metodo).

È stato utile?

Soluzione

Quello che ho finito per fare è stato agganciare l'evento click per il mio documento e una volta ricevuto un clic ho considerato che l'utente era rimasto.

Non è una buona soluzione, nella maggior parte dei casi (se sei un DiggBar) avrai molti falsi negativi (le persone rimarranno e non lo saprai mai), ma nel nostro caso ha perfettamente senso, perché le persone interagiscono pesantemente con il nostro sito, non solo con i siti incorniciati.

Essenzialmente, il mio codice fa questo ...

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

Altri suggerimenti

Ho cercato questa domanda online negli ultimi giorni e la risposta, invariabilmente, è "no". non puoi dire con certezza che un utente è rimasto o è uscito (a parte il fatto che la tua app smette di funzionare se l'utente lascia). Odio " no " risposte. Mi è venuta in mente la seguente utility.

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

})();

Quindi, una chiamata come

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

verrà chiamata all'interno del gestore per vedere se deve essere attivata o meno. In tal caso, il prefire viene eseguito prima che il popup venga mostrato all'utente (potresti voler mettere in pausa un video) e la richiamata avverrà SOLO se l'utente rimane.

La mia logica era di avviare un setTimeout nel corpo del gestore eventi. SetTimeout non verrà eseguito fino a quando l'utente non preme uno dei pulsanti. Dopo averlo fatto, si accende immediatamente. SetTimeout in questo caso non chiama il callback, ma una funzione proxy che esegue un altro timeout per il callback con un ritardo di 20 ms. Se l'utente rimane sulla pagina, viene eseguita la richiamata. In caso contrario, un altro gestore è collegato a onunload che cancella il timeout che chiamerà il callback, assicurando che il callback non venga mai chiamato. Ho avuto solo la possibilità di controllarlo su Firefox, IE e Chrome, ma ha funzionato finora in tutti e tre senza problemi.

Spero che questo aiuti le persone frustrate come lo ero dal brevetto "no". dato universalmente a questa domanda. Questo codice potrebbe non essere perfetto, ma penso che sia sulla strada giusta.

Questo è il massimo successo per questo tipo di domanda, e so che il caso specifico (di 8 anni fa) non poteva usare questa soluzione perché era in un iFrame, ma probabilmente tutti i futuri arrivati ??saranno più aiutati dalla risposta in basso rispetto a quelle sopra:

Puoi facilmente dire se sono rimasti con un ascoltatore di eventi del corpo, penso che mousemove e keydown combinati dovrebbero essere sufficienti.

Per sapere se se ne sono andati, avrai bisogno di alcune cose sul lato server.

Tutto sommato, sarà simile a questo (dovrai compilare tu stesso le chiamate ajax al server):

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

Sul lato server, dovrai usare qualcosa di brutto, un timer. Effettua una serie di tentativi di partenza e rimuovili come richiesto in permanenza o dopo un minuto circa come congedo confermato. Non riesco a immaginare nessun caso in cui sapere se l'utente lasciato è più sensibile al tempo di qualche minuto, ma se ne hai uno, ti preghiamo di commentare perché mi piacerebbe pensarci.

Perché non usare semplicemente il metodo di StackOverflow, in cui si ottiene una finestra popup che consente di fare la scelta:

  

Sei sicuro di voler uscire da questa pagina?

     

Hai iniziato a scrivere o modificare un post.

     

Premi OK per continuare o Annulla per rimanere nella pagina corrente

Quindi non importa quanto tempo impiegano. Se fanno clic su un pulsante, se ne vanno. Se fanno clic sull'altro, rimangono.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top