9

私が取り組んでいる Web アプリでは、onBeforeUnload をキャプチャして、ユーザーが本当に終了したいかどうかを尋ねています。

今、もし彼が残ることに決めたら、やりたいことがたくさんあります。私が理解しようとしているのは、彼が実際に留まることを選んだということです。

もちろん、"x" 秒間 SetTimeout を宣言することもできます。それが発生した場合は、ユーザーがまだそこにいることを意味します (アンロードされていないため)。問題は、ユーザーが滞在するかどうかを決定するのにいつでも時間がかかることです...

ダイアログが表示されている間は SetTimeout 呼び出しが発生しないことを最初に期待していたので、タイムアウトを短時間設定して、ユーザーが留まることを選択した場合にのみ発生するようにしました。ただし、ダイアログが表示されている間にタイムアウト発生するため、機能しません。

私が試した別のアイデアは、ウィンドウ/ドキュメントで mouseMoves をキャプチャすることです。ダイアログが表示されている間、私の場合に実際に適用される1つの奇妙な例外を除いて、mouseMovesは実際には起動しないため、それも機能しません。

誰でもこれを行う他の方法を考えることができますか?

ありがとう!


(ご参考までに、mouseMove のキャプチャが機能しない理由は、別のドメインのサイトを含む IFrame がページにあるためです。ページのアンロード時にフォーカスが IFrame 内にある場合、ダイアログが表示されると、マウスが IFrame の内側から外側に移動すると (少なくとも Firefox では)、MouseMove イベントが 1 回発生します。この方法は使えません)。

4

4 に答える 4

6

最終的に私がやったのは、ドキュメントのクリック イベントにフックすることでした。クリックを受け取ると、ユーザーは滞在したと見なされました。

これは良い解決策ではありません。ほとんどの場合 (DiggBar の場合)、多くの偽陰性が発生します (人々が留まり、それを知ることはありません)。フレーム化されたサイトだけでなく、私たちのサイトにも深く関わっています。

基本的に、私のコードはこれを行います...

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.
}
于 2009-06-18T15:13:29.733 に答える
4

私は過去数日間この質問をオンラインで調査してきましたが、答えは常に「いいえ」であり、ユーザーが留まったか離れたかを確実に判断することはできません (ユーザーが離れた場合にアプリが動作しなくなるという事実を除いて) )。私は「いいえ」という答えが嫌いです。次のユーティリティを思いつきました。

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

})();

したがって、次のような呼び出し

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

condition がハンドラ内で呼び出され、アクティブ化する必要があるかどうかが確認されます。その場合、ポップアップがユーザーに表示される前に prefire が実行され (ビデオを一時停止したい場合があります)、ユーザーが留まっている場合にのみコールバックが発生します。

私のロジックは、イベント ハンドラーの本体で setTimeout を開始することでした。setTimeout は、ユーザーがいずれかのボタンを押すまで実行されません。彼らがした後、それはすぐに発砲します。この場合の setTimeout はコールバックを呼び出しませんが、20 ミリ秒の遅延でコールバックの別のタイムアウトを実行するプロキシ関数です。ユーザーがページに留まると、コールバックが実行されます。そうでない場合は、コールバックを呼び出すタイムアウトをクリアする別のハンドラが onunload にアタッチされ、コールバックが呼び出されないようにします。私は Firefox、IE、および Chrome でのみ確認する機会がありましたが、これまでのところ 3 つすべてで問題なく動作しています。

これが、この質問に普遍的に与えられた特許「いいえ」に私が不満を抱いていたのと同じくらい人々を助けることを願っています. このコードは完璧ではないかもしれませんが、正しい方向に進んでいると思います。

于 2013-03-06T06:17:35.003 に答える
-7

StackOverflow が行う方法を使用しないのはなぜですか。選択を可能にするポップアップ ボックスが表示されます。

このページから移動してもよろしいですか?

投稿の作成または編集を開始しました。

[OK] をクリックして続行するか、[キャンセル] をクリックして現在のページにとどまります

その後、どれだけ時間がかかるかは問題ではありません。1 つのボタンをクリックすると、離れます。もう一方をクリックすると、残ります。

于 2009-05-05T17:55:01.070 に答える