如何防止按下退格键后返回上一页?

290

在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,通过禁止退格键导航回去来防止这种情况。
编辑2:我并不想阻止历史记录导航,只是想要防止意外发生。
编辑3:@brentonstrines评论(将其移到此处,因为问题如此流行):这是一个长期的“修复”方法,但您可以支持Chromium bug以更改webkit中的此行为

142
由于退格键功能过载,你可能没有注意到,但你可能经常使用它来删除刚刚在文本框中键入的字母。我的一些客户因为这个问题而感到困扰,导致页面返回,所以这是有用的信息。除了你们这些小丑之外,没人知道退格键应该返回上一页。这是我从未知道的事情,对于浏览器来说,这是完全敌对的行为。我认为所有页面都应该禁用这种行为。 - Breton
83
为什么人们认为这很奇怪?使用退格键进行导航是一个非常愚蠢的快捷方式!有很多文本字段用户可能想要删除文本——想象一下有一个很长的stackoverflow答案,在切换到另一个窗口查看东西后,你回来时误点了编辑区域,按下退格键删除一个单词,突然浏览器返回上一页,你可能会丢失你刚刚写的所有内容。 - Peter Boughton
59
为什么我想这样做呢?我不是在创建一个网站而是一个网络应用程序。一些输入字段是只读的,看起来像可编辑的,但如果您按退格键,您将离开该页面。想要导航回去的退格键次数与试图删除某些内容的退格键次数的比率可能远小于1/1000。 - erikkallen
43
问题是如何做到这一点,而不是你对此是否是个好主意的看法。如果不知道该项目的详细信息,你的意见是没有意义的。我的客户特别要求在我的一个项目中实现这种行为,一个真正的答案而不是“你为什么要这样做?”会更有帮助。 - None
7
这是一个长期的“修复”计划,但你可以支持Chromium bug来更改webkit中的这种行为:http://code.google.com/p/chromium/issues/detail?id=144832 - brentonstrine
显示剩余13条评论
33个回答

4

我很难找到一个非JQUERY的答案。感谢Stas让我找到了方向。

Chrome: 如果不需要跨浏览器支持,可以使用黑名单而不是白名单。这个纯JS版本在Chrome中有效,但在IE中无效。不确定FF是否有效。

在Chrome(版本36,2014年中期)中,不在输入或可编辑元素上的按键似乎会定位到<BODY>。这使得使用黑名单成为可能,我更喜欢使用黑名单而不是白名单。IE使用最后一个点击目标-因此它可能是一个div或其他任何东西。这使得在IE中这个无用。

window.onkeydown = function(event) {
    if (event.keyCode == 8) {
    //alert(event.target.tagName); //if you want to see how chrome handles keypresses not on an editable element
        if (event.target.tagName == 'BODY') {
            //alert("Prevented Navigation");
            event.preventDefault();
        }
    }
}  

跨浏览器:对于纯JavaScript,我发现Stas的答案是最好的。增加一个条件检查contenteditable使其对我起作用*:

document.onkeydown = function(e) {stopDefaultBackspaceBehaviour(e);}
document.onkeypress = function(e) {stopDefaultBackspaceBehaviour(e);}

function stopDefaultBackspaceBehaviour(event) {
    var event = event || window.event;
    if (event.keyCode == 8) {
        var elements = "HTML, BODY, TABLE, TBODY, TR, TD, DIV";
        var d = event.srcElement || event.target;
        var regex = new RegExp(d.tagName.toUpperCase());
        if (d.contentEditable != 'true') { //it's not REALLY true, checking the boolean value (!== true) always passes, so we can use != 'true' rather than !== true/
            if (regex.test(elements)) {
                event.preventDefault ? event.preventDefault() : event.returnValue = false;
            }
        }
    }
}

请注意,IE浏览器(包括Spartan/TechPreview)有一个“特性”,会使与表格相关的元素无法编辑。如果你点击其中一个元素然后按下退格键,它将会导航回上一页。如果你没有可编辑的<td>,这不是问题。

3
这个解决方案与其他已发布的方案相似,但它使用了一个简单的白名单,使其易于定制,只需在.is()函数中设置选择器即可允许在指定元素中使用退格键。
我使用它来防止在页面上使用退格键导航回去:
$(document).on("keydown", function (e) {
    if (e.which === 8 && !$(e.target).is("input:not([readonly]), textarea")) {
        e.preventDefault();
    }
});

2
当用户使用contenteditable时,这会使其变为禁用状态。因此,您可能需要将contenteditable=true添加到白名单中。 - Miguel

3

稍微详细解释一下@erikkallen的优秀回答,这里有一个函数,可以支持所有基于键盘的输入类型,包括HTML5中引入的那些类型

$(document).unbind('keydown').bind('keydown', function (event) {
    var doPrevent = false;
    var INPUTTYPES = [
        "text", "password", "file", "date", "datetime", "datetime-local",
        "month", "week", "time", "email", "number", "range", "search", "tel",
        "url"];
    var TEXTRE = new RegExp("^" + INPUTTYPES.join("|") + "$", "i");
    if (event.keyCode === 8) {
        var d = event.srcElement || event.target;
        if ((d.tagName.toUpperCase() === 'INPUT' && d.type.match(TEXTRE)) ||
             d.tagName.toUpperCase() === 'TEXTAREA') {
            doPrevent = d.readOnly || d.disabled;
        } else {
            doPrevent = true;
        }
    }
    if (doPrevent) {
        event.preventDefault();
    }
});

谢谢,我正在使用这个答案!你到目前为止发现了任何问题吗? - Nearpoint
1
我建议将INPUTTYPES、TEXTRE的声明从函数中移出,这样它们就不会在每次键按下事件上重新计算。 - thetoolman

3

JavaScript - jQuery 的方式:

$(document).on("keydown", function (e) {
    if (e.which === 8 && !$(e.target).is("input, textarea")) {
        e.preventDefault();
    }
});

Javascript - 本地方式,适合我使用:

<script type="text/javascript">

//on backspace down + optional callback
function onBackspace(e, callback){
    var key;
    if(typeof e.keyIdentifier !== "undefined"){
        key = e.keyIdentifier;

    }else if(typeof e.keyCode !== "undefined"){
        key = e.keyCode;
    }
    if (key === 'U+0008' || 
        key === 'Backspace' || 
        key === 8) {
                    if(typeof callback === "function"){
                callback();
            }
            return true;
        }
    return false;
}

//event listener
window.addEventListener('keydown', function (e) {

    switch(e.target.tagName.toLowerCase()){
        case "input":
        case "textarea":
        break;
        case "body":
            onBackspace(e,function(){
                e.preventDefault();
            });

        break;
    }
}, true);
</script>

@MichaelPotter,对于我的使用情况来说还可以,但是请随意通过改进/修改我的答案来做出贡献。谢谢! - Vladimir Djuricic

2

我在使用Select2.js插件的时候遇到了一些问题,无法删除可编辑框中的字符,因为删除操作被阻止了。以下是我的解决方案:

//Prevent backwards navigation when trying to delete disabled text.
$(document).unbind('keydown').bind('keydown', function (event) {

    if (event.keyCode === 8) {

        var doPrevent = false,
            d = event.srcElement || event.target,
            tagName = d.tagName.toUpperCase(),
            type = (d.type ? d.type.toUpperCase() : ""),
            isEditable = d.contentEditable,
            isReadOnly = d.readOnly,
            isDisabled = d.disabled;

        if (( tagName === 'INPUT' && (type === 'TEXT' || type === 'PASSWORD'))
            || tagName === 'PASSWORD'
            || tagName === 'TEXTAREA') {
            doPrevent =  isReadOnly || isDisabled;
        }
        else if(tagName === 'SPAN'){
            doPrevent = !isEditable;
        }
        else {
            doPrevent = true;
        }
    }

    if (doPrevent) {
        event.preventDefault();
    }
});

Select2会创建一个带有"contentEditable"属性的Span,用于在可编辑的组合框中。我添加了代码以考虑span标记和不同属性。这解决了我所有的问题。

编辑:如果您没有使用jquery的Select2组合框插件,则可能不需要此解决方案,而接受的解决方案可能更好。


1

防止按下退格键导航的最简单方法

$(document).keydown(function () {
    if (event.keyCode == 8) {
        if (event.target.nodeName == 'BODY') {
            event.preventDefault();
        }
    }
});

防止按下退格键时导航,同时允许在所有输入控件中使用退格键。 - Mohammed Irfan Mayan
$(document).keydown(function () { 不要错过第一行.. - Mohammed Irfan Mayan
3
这将禁用文本区域和输入框中的返回按钮。 - nodrog

1
    document.onkeydown = function (e) {    
        e.stopPropagation();
        if ((e.keyCode==8  ||  e.keyCode==13) &&
            (e.target.tagName != "TEXTAREA") && 
            (e.target.tagName != "INPUT")) { 
            return false;
        }
    };

2
不应使用 return false。推荐使用 e.preventDefault。另外,您正在阻止每个键的事件传播,而不仅仅是回退键。最后,keyCode 13 是“回车”,该问题涉及防止使用回退键进行后退导航,但这将防止回车提交表单或执行其他操作。 - None

1

这个解决方案在测试时表现非常好。

我添加了一些代码来处理一些未标记为input的输入字段,并将其集成到一个生成我的工作输入表单的Oracle PL/SQL应用程序中。

我的看法:

 if (typeof window.event != ''undefined'')
    document.onkeydown = function() {
    //////////// IE //////////////
    var src = event.srcElement;
    var tag = src.tagName.toUpperCase();
    if (event.srcElement.tagName.toUpperCase() != "INPUT"
        && event.srcElement.tagName.toUpperCase() != "TEXTAREA"
        || src.readOnly || src.disabled 
        )
        return (event.keyCode != 8);
    if(src.type) {
       var type = ("" + src.type).toUpperCase();
       return type != "CHECKBOX" && type != "RADIO" && type != "BUTTON";
       }
   }
else
   document.onkeypress = function(e) {
   //////////// FireFox 
   var src = e.target;
   var tag = src.tagName.toUpperCase();
   if ( src.nodeName.toUpperCase() != "INPUT" && tag != "TEXTAREA"
      || src.readOnly || src.disabled )
      return (e.keyCode != 8);
    if(src.type) {
      var type = ("" + src.type).toUpperCase();
      return type != "CHECKBOX" && type != "RADIO" && type != "BUTTON";
      }                              
   }

1

这段代码可以在所有浏览器中解决问题:

onKeydown:function(e)
{
    if (e.keyCode == 8) 
    {
      var d = e.srcElement || e.target;
      if (!((d.tagName.toUpperCase() == 'BODY') || (d.tagName.toUpperCase() == 'HTML'))) 
      {
         doPrevent = false;
      }
       else
      {
         doPrevent = true;
      }
    }
    else
    {
       doPrevent = false;
    }
      if (doPrevent)
      {
         e.preventDefault();
       }

  }

1
我发现这段代码由于d.tagname是DIVTD而无法按预期工作。 - Biff MaGriff
Haseeb Akhtar的代码在Chrome和Firefox中完美运行,但是意外地在IE6-9上不行。有什么建议吗? - Martin Andersen

1

您是否尝试过只需将以下属性添加到您的只读文本字段中:

onkeydown="return false;"

这将防止浏览器在只读文本字段中按下退格键时返回历史记录。也许我没有理解您的真正意图,但似乎这是解决您问题最简单的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接