如何防止退格键返回?

IT技术 javascript jquery internet-explorer firefox cross-browser
2021-01-12 07:42:35

在 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 中的这种行为

6个回答

这段代码解决了这个问题,至少在 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;
        }
    }
});
仅添加了对文本输入的检查,如果您专注于退格键正在工作的按钮。
2021-03-23 07:42:35
糟糕的是,这必须是白名单,而不是能够将“后退”功能列入黑名单。您可能想d.isContentEditable在此处添加检查
2021-03-25 07:42:35
正如 Hemlock 所说 - 也检查一下d.type.toUpperCase() === 'PASSWORD'否则看起来不错
2021-03-30 07:42:35
因为你已经在使用 jQuery if( $(d).is( ":input" ) )...
2021-04-09 07:42:35
我使用当前接受的答案的干净版本创建了一个 NPM 项目:github.com/slorber/backspace-disabler(它还支持 contenteditables 并且没有依赖项)
2021-04-11 07:42:35

此代码适用于所有浏览器,并在不在表单元素上时吞下退格键,或者如果表单元素被禁用|只读。它也很有效,这在对输入的每个键执行时很重要。

$(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();
            }
        }
    });
});
请测试我的示例,您可能希望相应地更新您的代码。
2021-03-18 07:42:35
我更喜欢这个而不是@erikkallen 的解决方案,因为它更干净。但是,我希望提交按钮、单选按钮和复选框也被忽略,因此我将 if() 更改为:if(!rx.test(e.target.tagName) || $(e.target).is(':checkbox') || $(e.target).is(':radio') || $(e.target).is(':submit') || e.target.disabled || e.target.readOnly )
2021-03-24 07:42:35
@thetoolman,请参阅我对 erikallen 回答的评论。这也应该说明contentEditable
2021-03-27 07:42:35
@cdmckay:我不敢相信我一开始就没有那样写。感谢您为我们所有人清理它:)
2021-04-04 07:42:35
@MaffooClock:你可以更简洁 .is(':checkbox,:radio,:submit')
2021-04-06 07:42:35

这里的其他答案已经确定,如果不将允许 Backspace 的元素列入白名单,就无法做到这一点。这种解决方案并不理想,因为白名单并不像仅仅输入 textareas 和 text/password 那样简单,而是反复发现不完整,需要更新。

然而,由于抑制退格功能的目的仅仅是为了防止用户意外丢失数据,所以 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 事件上触发,但是在这种情况下,您可以使用其他技术来防止用户意外丢失数据。

我刚刚添加了相同的解决方案,并在页面 LOL 底部看到了这篇文章。我的一个区别是在 return “Are you sure...退格影响的行为)。
2021-03-14 07:42:35
不错的解决方案,但不幸的是,如果用户不小心按了两次退格键,它仍然会导航回去。(至少在 Firefox 上)
2021-03-23 07:42:35
@Steve,无论是否罕见,如果该功能有问题,该信息就属于这里。我只想知道是不是真的有问题。
2021-03-24 07:42:35
@user2407309 我已经删除了我关于 Firefox 无法使用您的解决方案的评论(不是投诉)。我的调试器有问题。我很抱歉编辑/破坏您的代码。我现在意识到我越界(编辑)原谅我。我真的很抱歉,我对你对这个问题的绝妙解决方案没有任何抱怨。再次道歉。这段代码运行良好。我相信这是最好的答案,我为此向您表示赞赏。
2021-04-09 07:42:35
这个解决方案在我的本地机器上工作,但是当我移动它时,客户端(至少其中一些)失去了一半应用程序的功能。我想有什么东西在拒绝它,但我不知道是什么。
2021-04-10 07:42:35

更优雅/简洁的解决方案:

$(document).on('keydown',function(e){
  var $target = $(e.target||e.srcElement);
  if(e.keyCode == 8 && !$target.is('input,[contenteditable="true"],textarea'))
  {
    e.preventDefault();
  }
})
这更简洁,据我所知也同样有效。为什么最受欢迎的答案对所有这些输入类型进行检查,而且看起来更复杂?它更可靠吗?
2021-03-30 07:42:35
当只读字段聚焦时,删除仍会在 chrome 中导航回来
2021-04-08 07:42:35
最受欢迎的答案是第一个回答问题的人,因此票数很高。
2021-04-12 07:42:35

修改 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();
    });

示例
测试 make 2 个文件。

starthere.htm - 首先打开它,这样你就有一个可以返回的地方

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

test.htm - 当复选框或提交具有焦点(通过 Tab 键实现)时按下退格键,这将向后导航。替换为我的代码来修复。

<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>
你有没有试过@Darwayne 我很想知道为什么那个这么短而且这个更复杂,但两者对我来说似乎都是一样的
2021-03-18 07:42:35
您在什么浏览器上看到了无线电|复选框|提交 -> 后退功能上的退格键?我还没有看到浏览器这样做..
2021-03-23 07:42:35
Internet Explorer 8 和 Chrome
2021-03-25 07:42:35
这对链接有效吗?我有一个带有图像按钮的 ASP.Net 应用程序来删除一个项目。这是迄今为止唯一没有奏效的事情......
2021-04-10 07:42:35
我在这个线程中尝试了许多其他解决方案,但是这个解决方案在我的所有情况下都运行良好,并且拥有最干净、最容易理解的代码。谢谢你。
2021-04-12 07:42:35