ウェブサイト検索

javascript - バックスペースキーが前のページに戻るのを防ぐにはどうすればよいですか?


IEでは、これを(非常に標準外だが動作する)jQueryで行うことができます

if ($.browser.msie)
    $(document).keydown(function(e) { if (e.keyCode == 8) window.event.keyCode = 0;});

しかし、Firefoxで動作する方法や、ボーナスとしてクロスブラウザーでの方法で行うことは可能でしょうか?

記録のために:

$(document).keydown(function(e) { if (e.keyCode == 8) e.stopPropagation(); });

何もしない。

$(document).keydown(function(e) { if (e.keyCode == 8) e.preventDefault(); });

問題を解決しますが、ページ上でバックスペースキーが使用できなくなり、元の動作よりもさらに悪くなります。

編集: 私がこれを行う理由は、単純なウェブページを作っているのではなく、大規模なアプリケーションを作っているからです。間違った場所でバックスペースを押しただけで10分間の作業が失われるのは非常にイライラします。ミスを防ぐこととユーザーを煩わせることの比率は、バックスペースキーが戻る操作を行わないようにすることで、1000対1をはるかに超えるべきです。

EDIT2: 私は履歴の移動を防ごうとしているわけではなく、ただの事故を防ごうとしているだけです。

EDIT3: @brentonstrines のコメント(この質問が非常に人気があるため、こちらに移動しました):これは長期的な「修正」ですが、Chromium のバグのサポートをして、webkit でこの挙動を変更することもできます

回答 #1

このコードは少なくともIEとFirefoxでは問題を解決します(他のブラウザではテストしていませんが、仮に他のブラウザでも問題が存在するなら、動作する可能性は十分にあると思います)。

// Prevent the backspace key from navigating back.
$(document).unbind('keydown').bind('keydown', function (event) {
    if (event.keyCode === 8) {
        var doPrevent = true;
        var types = ["text", "password", "file", "search", "email", "number", "date", "color", "datetime", "datetime-local", "month", "range", "search", "tel", "time", "url", "week"];
        var d = $(event.srcElement || event.target);
        var disabled = d.prop("readonly") || d.prop("disabled");
        if (!disabled) {
            if (d[0].isContentEditable) {
                doPrevent = false;
            } else if (d.is("input")) {
                var type = d.attr("type");
                if (type) {
                    type = type.toLowerCase();
                }
                if (types.indexOf(type) > -1) {
                    doPrevent = false;
                }
            } else if (d.is("textarea")) {
                doPrevent = false;
            }
        }
        if (doPrevent) {
            event.preventDefault();
            return false;
        }
    }
});

回答 #2

このコードはすべてのブラウザで動作し、フォーム要素上にない場合やフォーム要素が無効または読み取り専用の場合にバックスペースキーを無効にします。また、処理効率も良く、入力されるすべてのキーで実行される場合でも重要です。

$(function(){
    /*
     * this swallows backspace keys on any non-input element.
     * stops backspace -> back
     */
    var rx = /INPUT|SELECT|TEXTAREA/i;

    $(document).bind("keydown keypress", function(e){
        if( e.which == 8 ){ // 8 == backspace
            if(!rx.test(e.target.tagName) || e.target.disabled || e.target.readOnly ){
                e.preventDefault();
            }
        }
    });
});

回答 #3

ここでの他の回答では、Backspaceが許可されている要素をホワイトリストに登録しない限り、これは実行できないと述べられています。この解決策は理想的ではありません。なぜなら、ホワイトリストは単にテキストエリアやテキスト/パスワード入力だけではなく、繰り返し不完全で更新が必要になることがあるからです。

しかし、バックスペース機能を抑制する目的がユーザーが誤ってデータを失うのを防ぐことだけであるため、beforeunload の解決策は良いものです。なぜなら、モーダルポップアップは驚きがあるからです――モーダルポップアップは標準的なワークフローの一部としてトリガーされると悪影響があります。ユーザーはそれを読まずに閉じることに慣れてしまい、煩わしくなるためです。この場合、モーダルポップアップは稀で驚くべき操作の代替としてのみ表示されるため、許容されます。

問題は、ユーザーがページから離れるたびに(リンクをクリックしたりフォームを送信したりする場合など)onbeforeunload モーダルが表示されてはいけないということであり、特定の onbeforeunload 条件をホワイトリストまたはブラックリスト化し始めたくないということです。

一般化されたソリューションのための理想的なトレードオフの組み合わせは次の通りです:バックスペースが押されたかどうかを追跡し、それが押された場合にのみ onbeforeunload モーダルを表示します。言い換えれば:

function confirmBackspaceNavigations () {
    // http://stackoverflow.com/a/22949859/2407309
    var backspaceIsPressed = false
    $(document).keydown(function(event){
        if (event.which == 8) {
            backspaceIsPressed = true
        }
    })
    $(document).keyup(function(event){
        if (event.which == 8) {
            backspaceIsPressed = false
        }
    })
    $(window).on('beforeunload', function(){
        if (backspaceIsPressed) {
            backspaceIsPressed = false
            return "Are you sure you want to leave this page?"
        }
    })
} // confirmBackspaceNavigations

これは IE7 以降、Firefox、Chrome、Safari、および Opera で動作することがテストされています。この関数を global.js に追加し、ユーザーがデータを誤って失わないようにしたいページから呼び出すだけです。

編集: onbeforeunload モーダルは一度しかトリガーされないことに注意してください。したがって、ユーザーが再度バックスペースを押しても、モーダルは再度表示されません。

追記: これは hashchange イベントでは発火しませんが、その場合でもユーザーが誤ってデータを失わないようにするために、他の手法を使用することができます。

回答 #4

よりエレガントで簡潔な解決策:

$(document).on('keydown',function(e){
  var $target = $(e.target||e.srcElement);
  if(e.keyCode == 8 && !$target.is('input,[contenteditable="true"],textarea'))
  {
    e.preventDefault();
  }
})

回答 #5

異なる入力タイプに対応するための erikkallen の回答の修正

私は、積極的なユーザーがチェックボックスやラジオボタンでバックスペースキーを押してそれを消そうとするかもしれないことに気づきましたが、代わりに前のページに戻ってしまい、すべてのデータを失うことになるでしょう。

この変更でその問題に対処できるはずです。

コンテンツ編集可能なdivに対応する新しい編集

    //Prevents backspace except in the case of textareas and text inputs to prevent user navigation.
    $(document).keydown(function (e) {
        var preventKeyPress;
        if (e.keyCode == 8) {
            var d = e.srcElement || e.target;
            switch (d.tagName.toUpperCase()) {
                case 'TEXTAREA':
                    preventKeyPress = d.readOnly || d.disabled;
                    break;
                case 'INPUT':
                    preventKeyPress = d.readOnly || d.disabled ||
                        (d.attributes["type"] && $.inArray(d.attributes["type"].value.toLowerCase(), ["radio", "checkbox", "submit", "button"]) >= 0);
                    break;
                case 'DIV':
                    preventKeyPress = d.readOnly || d.disabled || !(d.attributes["contentEditable"] && d.attributes["contentEditable"].value == "true");
                    break;
                default:
                    preventKeyPress = true;
                    break;
            }
        }
        else
            preventKeyPress = false;

        if (preventKeyPress)
            e.preventDefault();
    });

例
テストのために2つのファイルを作成します。

starthere.htm - まずこれを開いて、戻る場所を確保してください

<a href="./test.htm">Navigate to here to test</a>

test.htm - チェックボックスや送信ボタンにフォーカスがある状態でバックスペースを押すと後ろに移動します(タブで移動して実現)。修正するには、自分のコードと置き換えてください。

<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

    $(document).keydown(function(e) {
        var doPrevent;
        if (e.keyCode == 8) {
            var d = e.srcElement || e.target;
            if (d.tagName.toUpperCase() == 'INPUT' || d.tagName.toUpperCase() == 'TEXTAREA') {
                doPrevent = d.readOnly || d.disabled;
            }
            else
                doPrevent = true;
        }
        else
            doPrevent = false;

        if (doPrevent)
            e.preventDefault();
    });
</script>
</head>
<body>
<input type="text" />
<input type="radio" />
<input type="checkbox" />
<input type="submit" />
</body>
</html>

回答 #6

ほとんどの回答はjQueryで書かれています。これを純粋なJavaScriptで完璧に行うことができ、シンプルでライブラリは必要ありません。この記事は私にとって良い出発点でしたが、keyIdentifierが非推奨になっているため、このコードをより安全にしたくて、if文に||e.keyCode==8を追加しました。また、コードがFirefoxでうまく動作しなかったので、return false;を追加し、今では完全にうまく動作します。こちらです:

<script type="text/javascript">
window.addEventListener('keydown',function(e){if(e.keyIdentifier=='U+0008'||e.keyIdentifier=='Backspace'||e.keyCode==8){if(e.target==document.body){e.preventDefault();return false;}}},true);
</script>

このコードはうまく動作します、なぜなら、

  1. これは純粋なJavaScriptで書かれています(ライブラリは不要です)。
  2. それは押されたキーを確認するだけでなく、その動作が本当にブラウザの「戻る」操作であるかどうかも確認します。
  3. 上記と同様に、ユーザーは戻るボタンの動作を防ぎつつ、ウェブページの入力テキストボックスにテキストを入力したり削除したりすることが問題なくできます。
  4. それは短く、清潔で、速く、そして要点を押さえています。

テスト目的で console.log(e); を追加して、Chrome で F12 を押し、「コンソール」タブに移動し、ページ上で「Backspace」を押して中身を確認すると、返される値を見ることができます。その後、上記のコードをさらに自分のニーズに合わせるために、これらすべてのパラメータをターゲットにすることができます。

関連記事