ChatGPT解决这个技术问题 Extra ChatGPT

如何防止退格键向后导航?

在 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 bug to change this behavior in webkit

因为退格键过载。您可能没有注意到它,但您可能一直使用它来擦除您刚刚在文本字段中输入的字母。我的一些客户遇到了导致页面返回的问题,所以这是有用的信息。除了你们这些小丑之外,没有人知道退格应该返回一页。这是我从来不知道的事情,对于浏览器来说,这是完全的敌对行为。我认为所有页面都应该禁用这种行为。
为什么人们会觉得这很奇怪?使用退格键导航是一个非常愚蠢的快捷方式!有很多文本字段,用户可能想要从中删除文本 - 想象一下,有一个很长的 SO 答案,切换到另一个窗口检查某些内容,然后您返回并错误单击编辑区域,按退格键删除一个单词,然后突然,浏览器返回一个页面,您可能会丢失刚刚编写的所有内容。
我为什么要这样做?我不是在创建一个网站,而是一个 Web 应用程序。某些输入字段是只读的,在这种情况下它们看起来是可编辑的,但如果您按退格键,则会离开页面。打算向后导航的退格键与试图擦除某些内容的退格键的比率可能远小于 1 / 1000。
问题是如何做到这一点,而不是你对它是否是一个好主意的看法。在不了解项目细节的情况下,您的意见毫无意义。我的客户已经特别要求我的一个项目的这种行为和一个真正的答案,而不是“你为什么要这样做?”会有帮助的。
这是一个长期的“修复”,但您可以支持 Chromium 错误以更改 webkit 中的这种行为:code.google.com/p/chromium/issues/detail?id=144832

J
Jorge Fuentes González

这段代码解决了这个问题,至少在 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;
        }
    }
});

仅添加了对文本输入的检查,如果您专注于按钮,则退格正在工作。
正如 Hemlock 所说 - 检查 d.type.toUpperCase() === 'PASSWORD' 以及。否则看起来不错
由于您已经在使用 jQuery if( $(d).is( ":input" ) )...
很糟糕,这必须是一个白名单,而不是能够将“后退”功能列入黑名单。您可能想在此处添加对 d.isContentEditable 的检查。
我使用当前接受的答案的干净版本创建了一个 NPM 项目:github.com/slorber/backspace-disabler(它还支持 contenteditables 并且没有依赖项)
t
thetoolman

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

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

请测试我的示例,您可能希望相应地更新您的代码。
我更喜欢 @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 )
@thetoolman,请参阅我对 erikallen 回答的评论。这也应考虑 contentEditable
@MaffooClock:您可以使用 .is(':checkbox,:radio,:submit') 更简洁
@cdmckay:我不敢相信我一开始没有那样写。感谢您为我们所有人清理它:)
V
Vladimir Kornea

这里的其他答案已经确定,如果没有将允许 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 事件上触发,但是在这种情况下,您可以使用其他技术来防止用户意外丢失他们的数据。


我刚刚添加了相同的解决方案,并在页面底部看到了这篇文章 LOL。我的一个区别是在 return "Are you sure..." 语句之前设置 lastUserInputWasBackspace = false ,因此如果您在看到弹出窗口后碰巧单击后退按钮,则不会收到弹出窗口(因此它与非一致退格影响的行为)。
@user2407309 我已经删除了关于 Firefox 无法使用您的解决方案的评论(不是投诉)。我的调试器有问题。对于编辑/破坏您的代码,我深表歉意。我现在意识到我越界了(编辑)原谅我。我真的很抱歉,我无意抱怨你对这个问题的精彩解决方案。再次,我很抱歉。这段代码运行良好。我相信这是最好的答案,我赞扬你。
这个解决方案在我的本地机器上工作,但是当我把它移过来时,客户端(至少其中一些)失去了一半应用程序的功能。我猜有些东西在拒绝它,但我不知道是什么。
@Steve,无论是否罕见,如果功能有问题,该信息属于这里。我只是想知道是否真的有问题。
不错的解决方案,但不幸的是,如果用户不小心按了两次退格键,它仍然会向后导航。 (至少在火狐上)
D
Darwayne

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

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

这要简洁得多,据我所知也可以。为什么最受欢迎的答案会检查所有输入类型,而且看起来更复杂?它更可靠吗?
最受欢迎的答案是第一个回答问题的人,因此获得了高票。
当只读字段聚焦时,删除仍会在 chrome 中导航
B
Biff MaGriff

修改 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>

您看到哪个浏览器在 radio|checkbox|submit -> back 功能上按退格键?我还没有看到浏览器这样做..
Internet Explorer 8 和 Chrome
我在这个线程中尝试了许多其他解决方案,但这个解决方案在我的所有情况下都运行良好,并且拥有最干净、最容易理解的代码。谢谢你。
你试过@Darwayne吗?我很想知道为什么那个这么短而且这个更复杂,但两者对我来说似乎都一样
这对链接有效吗?我有一个带有图像按钮的 ASP.Net 应用程序来删除项目。这是迄今为止唯一没有奏效的事情......
D
DisgruntledGoat

根据评论,您似乎希望阻止人们在表单中丢失信息,如果他们按退格键删除但该字段没有聚焦。

在这种情况下,您需要查看 onunload 事件处理程序。 Stack Overflow 使用它 - 如果您在开始编写答案时尝试离开页面,它会弹出警告。


抱歉,这是一个粗鲁的评论。我的意思是,用户可能不想因为做了他们甚至不知道是错误的事情而受到指责。为什么不用 onkeydown 默默地吃掉钥匙?目标不是完全阻止用户离开页面,而是防止这种常见错误。此外,弹出式对话不是很有效或有用。用户不阅读它们。您确定要离开该页面吗?好的!别等了,我不想离开页面..哎呀太晚了。
好的,然后接受或离开。我认为您正在尝试过度设计一个实际上并不存在或至少不重要的问题。根据我的经验,只有高级用户会在不熟悉的对话框上单击“确定”而没有正确阅读它们。 ;)
你和布列塔尼是同一个人吗?无论如何,你有点自责 - 文章说“默认答案是取消”,所以当看到有关离开页面的对话框时,他们会按“取消”,因此不会离开页面。尽管应该注意的是,Chrome 在该对话框上的选项是“离开此页面”和“留在此页面上”,它们非常清晰。
不,他不是我,但我以前遇到过那个链接。我觉得评论很搞笑。 “什么!?人们忽略了模式对话框?我们必须找到一种方法让它们更加持久和烦人!”。真的解释了很多关于微软软件的东西。
@Disgruntled:不,我不是布列塔尼人,文章的重点不是“默认选择是……”,而是“用户什么都不读”。
T
Tarik

大多数答案都在 jquery 中。您可以在纯 Javascript 中完美地做到这一点,简单且不需要库。 This 文章对我来说是一个很好的起点,但由于 keyIdentifier 已被弃用,我希望此代码更安全,因此我添加了 ||e.keyCode==8到 if 语句。此外,代码在 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>

这段代码很好用,因为,

它是纯javascript(不需要库)。它不仅检查按下的键,还确认该操作是否真的是浏览器“返回”操作。与上述一起,用户可以在网页上的输入文本框中键入和删除文本,而不会出现任何问题,同时仍然阻止返回按钮动作。它简短、干净、快速且直截了当。

您可以添加 console.log(e);出于您的测试目的,并在 chrome 中按 F12,转到“控制台”选项卡并在页面上按“退格键”并查看其内部以查看返回的值,然后您可以定位所有这些参数以进一步增强代码以上,以满足您的需求。


C
Community

停止导航此代码有效!

$(document).on("keydown", function (event) {        
   if (event.keyCode === 8) {
      event.preventDefault();
    }
  });

但是为了不限制文本字段而限制其他

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

为了防止它用于特定领域,只需使用

$('#myOtherField').on("keydown", function (event) {
  if (event.keyCode === 8 || event.which === 8) { 
   event.preventDefault(); 
  } 
});

参考下面这个!

Prevent BACKSPACE from navigating back with jQuery (Like Google's Homepage)


C
CodeNepal

结合“thetoolman”&&“Biff MaGriff”给出的解决方案

以下代码似乎在 IE 8/Mozilla/Chrome 中正常工作

$(function () {
    var rx = /INPUT|TEXTAREA/i;
    var rxT = /RADIO|CHECKBOX|SUBMIT/i;

    $(document).bind("keydown keypress", function (e) {
        var preventKeyPress;
        if (e.keyCode == 8) {
            var d = e.srcElement || e.target;
            if (rx.test(e.target.tagName)) {
                var preventPressBasedOnType = false;
                if (d.attributes["type"]) {
                    preventPressBasedOnType = rxT.test(d.attributes["type"].value);
                }
                preventKeyPress = d.readOnly || d.disabled || preventPressBasedOnType;
            } else {preventKeyPress = true;}
        } else { preventKeyPress = false; }

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

添加 IMAGE 也可能有用。
我选择了这个。
b
brabster

不知道为什么没有人回答这个问题——这似乎是一个完全合理的技术问题,可以问这是否可能。

不,我认为没有跨浏览器的方式来禁用退格按钮。我知道这些天在 FF 中默认没有启用它。


没有回答实际问题和浪费时间的减 1
J
Josiah

我很难找到非 JQUERY 的答案。感谢 Stas 让我走上正轨。

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

在 Chrome(2014 年年中,第 36 版)中,不在 input 或 contenteditable 元素上的按键似乎针对 <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 [edit: 和 Spartan/TechPreview] 有一个“功能”,即 table-related elements uneditable。如果您单击其中一个然后按退格键,它将导航回来。如果您没有可编辑的 <td>,这不是问题。


N
None

此解决方案与已发布的其他解决方案类似,但它使用简单的白名单,只需在 .is() 函数中设置选择器,即可轻松自定义以允许指定元素中的退格。

我以这种形式使用它来防止页面上的退格键向后导航:

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

当用户使用 contenteditable 时,这将使其禁用。所以你可能想在白名单中添加 contenteditable=true
C
Community

为了稍微详细说明 @erikkallen 的 excellent answer,这里有一个函数允许所有基于键盘的输入类型,包括 those introduced in 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();
    }
});

谢谢,我正在使用这个答案!到目前为止,您是否发现此解决方案有任何问题?
我建议将 INPUTTYPES、TEXTRE 声明移出函数,这样它们就不会在每个 keydown 事件上重新计算。
V
Vladimir Djuricic

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很久以前我的用例没问题。请随时通过改进/更改我的答案来做出贡献。谢谢!
P
PrinceTyke

我对接受的解决方案和 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,对于其中的可编辑组合框,该属性设置为 true。我添加了代码来说明 spans tagName 和不同的属性。这解决了我所有的问题。

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


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

你不应该使用 return false。推荐使用 e.preventDefault。此外,您正在停止传播每个键的事件,而不仅仅是退格键。最后,keyCode 13 是 enter,问题是关于防止使用退格键进行后退导航,但这会阻止 enter 提交表单或执行其他操作。
T
Tim Cooper

此代码解决了所有浏览器中的问题:

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

  }

由于 d.tagname 为 DIVTD,我发现此代码无法按预期工作。
Haseeb Akhtar 的代码在 Chrome 和 Firefox 中完美运行,但令人惊讶!不在 IE6-9 有什么建议吗?
L
Luke Woodward

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

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

防止在按下退格键时导航,同时在所有输入控件中允许退格键
不要错过第一行..$(document).keydown(function () {
这将禁用 textareas 和输入中的后退按钮
C
Chris V

使用 Dojo 工具包 1.7,这适用于 IE 8:

require(["dojo/on", "dojo/keys", "dojo/domReady!"],
function(on, keys) {
    on(document.body,"keydown",function(evt){if(evt.keyCode == keys.BACKSPACE)evt.preventDefault()});
});

B
B-Dog

您是否尝试过将以下属性添加到只读文本字段的非常简单的解决方案:

onkeydown="返回假;"

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


R
Robin Maben

一个更整洁的解决方案 -

$(document).on('keydown', function (e) {
    var key = e == null ? event.keyCode : e.keyCode;
    if(key == 8 && $(document.activeElement.is(':not(:input)')))   //select, textarea
      e.preventDefault();
});

或者,您只能检查是否

$(document.activeElement).is('body')

S
Stanislav Parkhomenko

纯 javascript 版本,适用于所有浏览器:

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 (regex.test(elements)) {
      event.preventDefault ? event.preventDefault() : event.returnValue = false;
    }
  }
}

当然你可以使用“INPUT, TEXTAREA”然后使用“if (!regex.test(elements))”。第一个对我来说很好。


B
BenMorel

表现?

我担心性能并做了一个小提琴:http://jsfiddle.net/felvhage/k2rT6/9/embedded/result/

var stresstest = function(e, method, index){...

我已经分析了我在这个线程中找到的最有前途的方法。事实证明,它们都非常快,并且很可能不会在打字时造成“迟缓”问题。我看到的最慢的方法是在 IE8 中进行 10.000 次调用大约需要 125 毫秒。即每笔划 0.0125 毫秒。

我发现 Codenepal 和 Robin Maben 发布的方法最快 ~ 0.001ms (IE8),但要注意不同的语义。

也许这对于将这种功能引入他的代码的人来说是一种解脱。


J
Jacek Pietal

修改后的 erikkallen 答案:

$(document).unbind('keydown').bind('keydown', function (event) {

    var doPrevent = false, elem;

    if (event.keyCode === 8) {
        elem = event.srcElement || event.target;
        if( $(elem).is(':input') ) {
            doPrevent = elem.readOnly || elem.disabled;
        } else {
            doPrevent = true;
        }
    }

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

完美的答案。我从其他人那里得到的解决方案在 Firefox 中不起作用,但是这个解决方案在所有三个(Firefox、IE 和 crom)中都可以正常工作,没有任何问题。谢谢普罗齐。
L
Luis Cuellar

该解决方案在测试时效果很好。

我确实添加了一些代码来处理一些没有用输入标记的输入字段,并集成到为我的工作生成输入表单的 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";
      }                              
   }

S
Sebastien Lorber

我创建了一个 NPM 项目,它具有当前接受的(erikkallen 的)的干净版本

https://github.com/slorber/backspace-disabler

它使用基本相同的原理,但是:

无依赖

支持内容可编辑

更具可读性/可维护性的代码库

将得到支持,因为它将被我的公司用于生产

麻省理工学院执照

var Backspace = 8;

// See http://stackoverflow.com/questions/12949590/how-to-detach-event-in-ie-6-7-8-9-using-javascript
function addHandler(element, type, handler) {
    if (element.addEventListener) {
        element.addEventListener(type, handler, false);
    } else if (element.attachEvent) {
        element.attachEvent("on" + type, handler);
    } else {
        element["on" + type] = handler;
    }
}
function removeHandler(element, type, handler) {
    if (element.removeEventListener) {
        element.removeEventListener(type, handler, false);
    } else if (element.detachEvent) {
        element.detachEvent("on" + type, handler);
    } else {
        element["on" + type] = null;
    }
}




// Test wether or not the given node is an active contenteditable,
// or is inside an active contenteditable
function isInActiveContentEditable(node) {
    while (node) {
        if ( node.getAttribute && node.getAttribute("contenteditable") === "true" ) {
            return true;
        }
        node = node.parentNode;
    }
    return false;
}



var ValidInputTypes = ['TEXT','PASSWORD','FILE','EMAIL','SEARCH','DATE'];

function isActiveFormItem(node) {
    var tagName = node.tagName.toUpperCase();
    var isInput = ( tagName === "INPUT" && ValidInputTypes.indexOf(node.type.toUpperCase()) >= 0 );
    var isTextarea = ( tagName === "TEXTAREA" );
    if ( isInput || isTextarea ) {
        var isDisabled = node.readOnly || node.disabled;
        return !isDisabled;
    }
    else if ( isInActiveContentEditable(node) ) {
        return true;
    }
    else {
        return false;
    }
}


// See http://stackoverflow.com/questions/1495219/how-can-i-prevent-the-backspace-key-from-navigating-back
function disabler(event) {
    if (event.keyCode === Backspace) {
        var node = event.srcElement || event.target;
        // We don't want to disable the ability to delete content in form inputs and contenteditables
        if ( isActiveFormItem(node) ) {
            // Do nothing
        }
        // But in any other cases we prevent the default behavior that triggers a browser backward navigation
        else {
            event.preventDefault();
        }
    }
}


/**
 * By default the browser issues a back nav when the focus is not on a form input / textarea
 * But users often press back without focus, and they loose all their form data :(
 *
 * Use this if you want the backspace to never trigger a browser back
 */
exports.disable = function(el) {
    addHandler(el || document,"keydown",disabler);
};

/**
 * Reenable the browser backs
 */
exports.enable = function(el) {
    removeHandler(el || document,"keydown",disabler);
};

n
ninjagecko

这是我对最高投票答案的重写。我尝试检查 element.value!==undefined (因为某些元素可能没有 html 属性,但可能在原型链的某处具有 javascript value 属性),但是效果不佳并且有很多边缘情况。似乎没有一个很好的方法来证明这一点,所以白名单似乎是最好的选择。

这会在事件冒泡阶段结束时注册元素,因此如果您想以任何自定义方式处理 Backspace,您可以在其他处理程序中执行此操作。

这也会检查 instanceof HTMLTextAreElement,因为理论上可以有一个继承自它的 Web 组件。

这不会检查 contentEditable (与其他答案结合)。

https://jsfiddle.net/af2cfjc5/15/

var _INPUTTYPE_WHITELIST = ['text', 'password', 'search', 'email', 'number', 'date'];

function backspaceWouldBeOkay(elem) {
    // returns true if backspace is captured by the element
    var isFrozen = elem.readOnly || elem.disabled;
    if (isFrozen) // a frozen field has no default which would shadow the shitty one
        return false;
    else {
        var tagName = elem.tagName.toLowerCase();
        if (elem instanceof HTMLTextAreaElement) // allow textareas
            return true;
        if (tagName=='input') { // allow only whitelisted input types
            var inputType = elem.type.toLowerCase();
            if (_INPUTTYPE_WHITELIST.includes(inputType))
                return true;
        }   
        return false; // everything else is bad
    }
}

document.body.addEventListener('keydown', ev => {
    if (ev.keyCode==8 && !backspaceWouldBeOkay(ev.target)) {
        //console.log('preventing backspace navigation');
        ev.preventDefault();
    }
}, true); // end of event bubble phase

J
John Conde

Sitepoint: Disable back for Javascript

event.stopPropagation()event.preventDefault() 在 IE 中什么都不做。不过,我不得不发送 return event.keyCode == 11(我刚刚选择了一些东西)而不是仅仅说 "if not = 8, run the event" 才能让它工作。 event.returnValue = false 也有效。


C
CodeNepal

使用jquery的另一种方法

    <script type="text/javascript">

    //set this variable according to the need within the page
    var BACKSPACE_NAV_DISABLED = true;

    function fnPreventBackspace(event){if (BACKSPACE_NAV_DISABLED && event.keyCode == 8) {return false;}}
    function fnPreventBackspacePropagation(event){if(BACKSPACE_NAV_DISABLED && event.keyCode == 8){event.stopPropagation();}return true;}

    $(document).ready(function(){ 
        if(BACKSPACE_NAV_DISABLED){
            //for IE use keydown, for Mozilla keypress  
            //as described in scr: http://www.codeproject.com/KB/scripting/PreventDropdownBackSpace.aspx
            $(document).keypress(fnPreventBackspace);
            $(document).keydown(fnPreventBackspace);

            //Allow Backspace is the following controls 
            var jCtrl = null;
            jCtrl = $('input[type="text"]');
            jCtrl.keypress(fnPreventBackspacePropagation);
            jCtrl.keydown(fnPreventBackspacePropagation);

            jCtrl = $('input[type="password"]');
            jCtrl.keypress(fnPreventBackspacePropagation);
            jCtrl.keydown(fnPreventBackspacePropagation);

            jCtrl = $('textarea');
            jCtrl.keypress(fnPreventBackspacePropagation);
            jCtrl.keydown(fnPreventBackspacePropagation);

            //disable backspace for readonly and disabled
            jCtrl = $('input[type="text"][readonly="readonly"]')
            jCtrl.keypress(fnPreventBackspace);
            jCtrl.keydown(fnPreventBackspace);

            jCtrl = $('input[type="text"][disabled="disabled"]')
            jCtrl.keypress(fnPreventBackspace);
            jCtrl.keydown(fnPreventBackspace);
        }
    }); 

    </script>

请注意,如果控件(文本框)已被动态添加,这将不起作用。
T
Tan

我已经在我的代码中使用它一段时间了。我为学生编写了在线测试,当学生在测试期间按退格键时遇到了问题,这会让他们回到登录屏幕。令人沮丧!它肯定适用于FF。

document.onkeypress = Backspace;
function Backspace(event) {
    if (event.keyCode == 8) {
        if (document.activeElement.tagName == "INPUT") {
            return true;
        } else {
            return false;
        }
    }
}