Làm cách nào tôi có thể ngăn phím backspace điều hướng trở lại?


275

Trên IE tôi có thể làm điều này với jQuery (cực kỳ không chuẩn, nhưng đang hoạt động)

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

Nhưng liệu có thể thực hiện theo cách hoạt động trên Firefox hoặc theo cách đa trình duyệt để nhận tiền thưởng?

Đối với hồ sơ:

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

Không lam gi cả.

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

giải quyết vấn đề, nhưng khiến cho phím backspace không thể sử dụng được trên trang, thậm chí còn tệ hơn hành vi ban đầu.

EDIT: Lý do tôi làm điều này là vì tôi không tạo ra một trang web đơn giản mà là một ứng dụng lớn. Thật khó chịu khi mất 10 phút làm việc chỉ vì bạn nhấn backspace không đúng chỗ. Tỷ lệ ngăn ngừa lỗi so với người dùng gây phiền nhiễu nên vượt quá 1000/1 bằng cách ngăn phím backspace điều hướng trở lại.

EDIT2: Tôi không cố gắng ngăn điều hướng lịch sử, chỉ là tai nạn.

EDIT3: Nhận xét @brentonstrines (được chuyển đến đây vì câu hỏi rất phổ biến): Đây là một 'sửa chữa' dài hạn, nhưng bạn có thể ném hỗ trợ của mình đằng sau lỗi Chromium để thay đổi hành vi này trong webkit


137
Bởi vì phím backspace bị quá tải. Bạn có thể không nhận thấy nó, nhưng bạn có thể sử dụng nó mọi lúc để xóa các chữ cái bạn vừa gõ vào một trường văn bản. Một số khách hàng của tôi đã gặp sự cố với điều đó khiến trang bị quay trở lại, vì vậy đây là thông tin hữu ích. Không ai ngoài những chú hề biết rằng backspace được cho là quay lại một trang. Đó là điều mà tôi chưa bao giờ biết, và đó là hành vi thù địch hoàn toàn đối với một trình duyệt. Tôi nghĩ rằng tất cả các trang nên vô hiệu hóa hành vi đó.
Breton

80
Tại sao mọi người nghĩ rằng điều này là kỳ lạ? Sử dụng backspace để điều hướng là một phím tắt thực sự ngu ngốc! có rất nhiều trường văn bản mà người dùng có thể muốn xóa văn bản khỏi - hãy tưởng tượng có một câu trả lời SO dài, chuyển sang một cửa sổ khác để kiểm tra một cái gì đó, sau đó bạn quay lại và bấm nhầm vào khu vực chỉnh sửa, nhấn backspace để xóa một từ và đột nhiên trình duyệt quay lại một trang và bạn có khả năng mất mọi thứ bạn vừa viết.
Peter Boughton

57
Tại sao tôi muốn làm điều này? Tôi không tạo một trang web mà là một ứng dụng web. Một số trường đầu vào chỉ đọc trong trường hợp chúng trông có thể chỉnh sửa được, nhưng nếu bạn nhấn backspace, bạn sẽ rời khỏi trang. Tỷ lệ của các lần nhấn backspace có ý định điều hướng trở lại so với các lần nhấn backspace cố gắng xóa một cái gì đó có lẽ ít hơn 1 / 1000.
erikkallen

42
Câu hỏi là làm thế nào để làm điều này, không phải ý kiến ​​của bạn về việc đó có phải là một ý tưởng tốt hay không. Không biết các chi tiết của dự án, ý kiến ​​của bạn là vô nghĩa. Khách hàng của tôi đã đặc biệt yêu cầu hành vi này cho một trong các dự án của tôi và một câu trả lời thực sự thay vì "Tại sao bạn lại muốn làm điều đó?" Sẽ hữu ích.
Không có

7
Đây là một lâu dài 'sửa chữa', nhưng bạn có thể ném hỗ trợ của bạn đằng sau những lỗi Chromium để thay đổi hành vi này trong webkit: code.google.com/p/chromium/issues/detail?id=144832
brentonstrine

Câu trả lời:


335

Mã này giải quyết vấn đề, ít nhất là trong IE và Firefox (chưa thử nghiệm bất kỳ vấn đề nào khác, nhưng tôi cho nó cơ hội làm việc hợp lý nếu sự cố thậm chí còn tồn tại trong các trình duyệt khác).

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

6
Phá vỡ các trường mật khẩu.
Hemlock

7
Như Hemlock đã nêu - kiểm tra d.type.toUpperCase() === 'PASSWORD'là tốt. Nếu không thì có vẻ tốt
stevendesu

17
Vì bạn đã sử dụng jQueryif( $(d).is( ":input" ) )...
Paul Alexander

23
Thật tệ khi đây phải là một danh sách trắng, thay vì có thể đưa vào danh sách đen chức năng "quay lại". Bạn có thể muốn thêm một kiểm tra d.isContentEditabletại đây.
iono

3
Tôi đã tạo một dự án NPM với phiên bản sạch của câu trả lời hiện đang được chấp nhận: github.com/slorber/backspace-disabler (nó cũng hỗ trợ nội dung và không có sự phụ thuộc)
Sebastien Lorber

62

Mã này hoạt động trên tất cả các trình duyệt và nuốt phím backspace khi không phải trên một phần tử biểu mẫu hoặc nếu phần tử biểu mẫu bị vô hiệu hóa | readOnly. Nó cũng hiệu quả, điều này rất quan trọng khi nó được thực thi trên mọi khóa được nhập vào.

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

1
Vui lòng kiểm tra ví dụ của tôi, bạn có thể muốn cập nhật mã của mình cho phù hợp.
Biff MaGriff

10
Tôi thích giải pháp này hơn giải pháp của @ erikkallen vì nó sạch hơn. Tuy nhiên, tôi muốn gửi các nút, nút radio và hộp kiểm cũng bị bỏ qua, vì vậy tôi đã thay đổi if () thành này:if(!rx.test(e.target.tagName) || $(e.target).is(':checkbox') || $(e.target).is(':radio') || $(e.target).is(':submit') || e.target.disabled || e.target.readOnly )
Matthew Clark

@thetoolman, xem nhận xét của tôi về câu trả lời của erikallen. Điều này cũng nên chiếm contentEditable.
giật

10
@MaffooClock: bạn có thể súc tích hơn với.is(':checkbox,:radio,:submit')
cdmckay

1
@cdmckay: Tôi không thể tin rằng tôi đã không viết nó theo cách đó ngay từ đầu. Cảm ơn vì đã dọn dẹp tất cả cho tất cả chúng ta :)
Matthew Clark

41

Các câu trả lời khác ở đây đã xác định rằng điều này không thể được thực hiện mà không có các yếu tố trong danh sách trắng trong đó Backspace được cho phép. Giải pháp này không lý tưởng vì danh sách trắng không đơn giản như chỉ đơn thuần là nhập văn bản và nhập văn bản / mật khẩu, nhưng nhiều lần được tìm thấy là không đầy đủ và cần phải cập nhật.

Tuy nhiên, vì mục đích ngăn chặn chức năng backspace chỉ đơn thuần là để ngăn người dùng vô tình làm mất dữ liệu, giải pháp trước khi tải là một giải pháp tốt vì cửa sổ bật lên phương thức rất đáng ngạc nhiên - cửa sổ bật lên phương thức rất tệ khi chúng được kích hoạt như một phần của quy trình làm việc tiêu chuẩn, bởi vì người dùng đã quen với việc loại bỏ chúng mà không đọc chúng, và chúng gây phiền nhiễu. Trong trường hợp này, cửa sổ bật lên phương thức sẽ chỉ xuất hiện thay thế cho một hành động hiếm gặp và đáng ngạc nhiên, và do đó được chấp nhận.

Vấn đề là một chế độ onb Beforeunload không được bật lên bất cứ khi nào người dùng điều hướng khỏi trang (chẳng hạn như khi nhấp vào liên kết hoặc gửi biểu mẫu) và chúng tôi không muốn bắt đầu danh sách trắng hoặc liệt kê các điều kiện onb Beforeunload cụ thể.

Sự kết hợp lý tưởng của sự đánh đổi cho một giải pháp tổng quát như sau: theo dõi xem liệu backspace có được nhấn hay không và chỉ bật lên phương thức onb Beforeunload nếu có. Nói cách khác:

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

Điều này đã được thử nghiệm để hoạt động trong IE7 +, FireFox, Chrome, Safari và Opera. Chỉ cần thả chức năng này vào global.js của bạn và gọi nó từ bất kỳ trang nào mà bạn không muốn người dùng vô tình làm mất dữ liệu của họ.

Lưu ý rằng một chế độ onb Beforeunload chỉ có thể được kích hoạt một lần, vì vậy nếu người dùng nhấn lại backspace, phương thức sẽ không kích hoạt lại.

Lưu ý rằng điều này sẽ không kích hoạt các sự kiện băm, tuy nhiên trong bối cảnh đó, bạn có thể sử dụng các kỹ thuật khác để ngăn người dùng vô tình làm mất dữ liệu của họ.


2
Tôi vừa đi để thêm giải pháp tương tự và thấy bài đăng này ở dưới cùng của trang LOL. Một điểm khác biệt tôi có là đặt LastUserInputWasBackspace = false trước câu trả lời "Bạn có chắc chắn ..." không, vì vậy bạn không nhận được cửa sổ bật lên nếu bạn tình cờ nhấp vào nút quay lại sau khi đã thấy cửa sổ bật lên (vì vậy nó phù hợp với không hành vi ảnh hưởng backspace).
David Russell

1
@ user2407309 Tôi đã xóa nhận xét của mình (không phải là khiếu nại) về việc firefox không hoạt động với giải pháp của bạn. Có một vấn đề với trình gỡ lỗi của tôi. Tôi xin lỗi vì đã chỉnh sửa / phá mã của bạn. Bây giờ tôi nhận ra rằng tôi đã vượt qua giới hạn của mình (chỉnh sửa) tha thứ cho tôi. Tôi thực sự xin lỗi và tôi không có ý phàn nàn về giải pháp tuyệt vời của bạn cho vấn đề này. Một lần nữa, lời xin lỗi của tôi. Mã này hoạt động tốt. Tôi tin rằng đây là câu trả lời tốt nhất và tôi khen bạn vì nó.
Charles Byrne

1
Giải pháp này hoạt động trên máy cục bộ của tôi, nhưng khi tôi chuyển nó qua, máy khách (ít nhất là một số trong số chúng) đã mất chức năng của một nửa ứng dụng. Tôi đoán một cái gì đó đang từ chối nó, nhưng tôi không biết gì.
Steve

1
@Steve, hiếm hay không, nếu có vấn đề với chức năng, thông tin đó thuộc về đây. Tôi chỉ muốn biết liệu thực sự có vấn đề.
Vladimir Kornea 6/03/2015

1
Giải pháp hay, nhưng thật không may, nếu người dùng vô tình nhấn backspace hai lần, nó vẫn điều hướng trở lại. (ít nhất là trên firefox)
Remco de Zwart

26

Một giải pháp thanh lịch / súc tích hơn:

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

1
Điều này ngắn gọn hơn rất nhiều và từ những gì tôi có thể nói cũng hoạt động tốt. Tại sao câu trả lời phổ biến nhất có tất cả những câu hỏi kiểm tra các loại đầu vào, và có vẻ phức tạp hơn? Có đáng tin cậy hơn không?
Điểm gần

1
Câu trả lời phổ biến nhất là câu trả lời đầu tiên, do đó số phiếu cao.
Darwayne

4
khi các trường chỉ đọc được tập trung xóa vẫn điều hướng trở lại trong chrome
Will D

16

Sửa đổi câu trả lời của erikkallen để giải quyết các loại đầu vào khác nhau

Tôi đã phát hiện ra rằng một người dùng dám nghĩ dám làm có thể nhấn backspace trên hộp kiểm hoặc nút radio trong một nỗ lực vô ích để xóa nó và thay vào đó họ sẽ điều hướng lùi và mất tất cả dữ liệu của họ.

Thay đổi này sẽ giải quyết vấn đề đó.

Chỉnh sửa mới để giải quyết nội dung div có thể chỉnh sửa

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

Ví dụ
Để kiểm tra làm 2 tệp.

starthere.htm - mở cái này trước để bạn có một nơi để quay lại

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

test.htm - Điều này sẽ điều hướng lùi khi nhấn phím lùi trong khi hộp kiểm hoặc gửi có tiêu điểm (đạt được bằng cách gắn thẻ). Thay thế bằng mã của tôi để sửa chữa.

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

Trình duyệt nào bạn thấy backspace nhấn trên radio | hộp kiểm | gửi -> chức năng quay lại? Tôi chưa thấy một trình duyệt làm điều này ..
thetoolman

Internet Explorer 8 và Chrome
Biff MaGriff

2
Tôi đã thử một số giải pháp khác trong chủ đề này, nhưng giải pháp này hoạt động tốt trong mọi tình huống của tôi và có mã sạch nhất, dễ hiểu nhất. Cảm ơn bạn.
Ezward

Bạn đã thử @Darwayne Tôi tò mò muốn biết tại sao cái đó lại quá ngắn và nó phức tạp hơn, nhưng cả hai dường như hoạt động giống nhau đối với tôi
Gần điểm

Điều này có hoạt động trên các liên kết? Tôi có một ứng dụng ASP.Net với nút hình ảnh để xóa một mục. Đó là điều duy nhất mà nó chưa hoạt động cho đến nay ...
Steve

8

Dựa trên các bình luận, có vẻ như bạn muốn ngăn mọi người mất thông tin trong các biểu mẫu, nếu họ nhấn backspace để xóa nhưng trường không được tập trung.

Trong trường hợp đó, bạn muốn xem xét xử lý sự kiện onunload . Stack Overflow sử dụng nó - nếu bạn cố gắng rời khỏi một trang khi bạn bắt đầu viết câu trả lời, nó sẽ hiện ra một cảnh báo.


4
xin lỗi đó là một nhận xét thô lỗ. Ý tôi là, người dùng có lẽ không muốn bị mắng mỏ khi làm điều gì đó mà họ thậm chí không biết là sai. Tại sao không chỉ âm thầm ăn chìa khóa với một onkeydown? Mục tiêu không phải là ngăn chặn hoàn toàn người dùng rời khỏi trang, mà là để bảo vệ chống lại lỗi phổ biến này. Ngoài ra, các hộp thoại bật lên không hiệu quả hoặc hữu ích. Người dùng không đọc chúng. Bạn có chắc chắn muốn rời khỏi trang? Được chứ! Không chờ đợi, tôi không muốn rời khỏi trang .. rất tiếc.
Breton

3
OK sau đó lấy nó hoặc để lại nó. Tôi nghĩ rằng bạn đang cố gắng thiết kế quá mức một vấn đề không thực sự tồn tại hoặc ít nhất là không quan trọng. Và theo kinh nghiệm của tôi, đó chỉ là những người dùng có quyền bấm "OK" trên các hộp thoại lạ mà không đọc đúng. ;)
DisgruntledGoat

3
Bạn và Breton có phải là cùng một người không? Dù sao bạn cũng tự bắn vào chân mình - bài báo nói rằng "câu trả lời mặc định là Hủy" vì vậy khi thấy hộp thoại về việc rời khỏi trang, họ sẽ nhấn "Hủy" và do đó không rời khỏi trang. Mặc dù cần lưu ý rằng các tùy chọn của Chrome trên hộp thoại đó là "Rời khỏi trang này" và "Ở lại trang này" rất rõ ràng.
DisgruntledGoat

1
Không, anh ấy không phải là tôi, nhưng tôi đã đi qua liên kết đó trước đây. Tôi nghĩ rằng các ý kiến ​​là vui nhộn. "Cái gì!? Mọi người bỏ qua các hộp thoại phương thức? Chúng ta phải tìm cách khiến chúng thậm chí còn dai dẳng và khó chịu hơn!". Thực sự giải thích rất nhiều về phần mềm microsoft.
Breton

3
@Disgruntled: Không, tôi không phải là Breton và quan điểm của bài viết không phải là "Lựa chọn mặc định là ..." mà là "người dùng không đọc gì cả."
erikkallen

7

Dừng điều hướng mã này hoạt động!

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

Nhưng để không hạn chế các trường văn bản nhưng những người khác

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

Để ngăn chặn nó cho lĩnh vực cụ thể chỉ cần sử dụng

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

Nhắc đến cái này dưới đây!

Ngăn BACKSPACE điều hướng trở lại với jQuery (Giống như Trang chủ của Google)


7

Hầu hết các câu trả lời là trong jquery. Bạn có thể làm điều này một cách hoàn hảo trong Javascript thuần túy, đơn giản và không cần thư viện. Bài viết này là một điểm khởi đầu tốt cho tôi nhưng vì keyIdentifier không được dùng nữa, tôi muốn mã này an toàn hơn nên tôi đã thêm || e.keyCode == 8 vào câu lệnh if. Ngoài ra, mã không hoạt động tốt trên Firefox nên tôi đã thêm return false; và bây giờ nó hoạt động hoàn toàn tốt. Đây là:

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

Mã này hoạt động tuyệt vời bởi vì,

  1. Nó là trong javascript thuần túy (không cần thư viện).
  2. Không chỉ kiểm tra phím được nhấn, nó còn xác nhận xem hành động đó có thực sự là hành động "quay lại" của trình duyệt hay không.
  3. Cùng với cách trên, người dùng có thể nhập và xóa văn bản khỏi các hộp văn bản đầu vào trên trang web mà không gặp bất kỳ vấn đề nào trong khi vẫn ngăn chặn hành động của nút quay lại.
  4. Nó ngắn, sạch sẽ, nhanh chóng và đi thẳng vào vấn đề.

Bạn có thể thêm console.log (e); cho mục đích thử nghiệm của bạn và nhấn F12 bằng chrome, hãy chuyển đến tab "console" và nhấn "backspace" trên trang và nhìn vào bên trong để xem giá trị nào được trả về, sau đó bạn có thể nhắm mục tiêu tất cả các tham số đó để tăng cường hơn nữa mã ở trên để phù hợp với nhu cầu của bạn.


6

Kết hợp các giải pháp được đưa ra bởi "thetoolman" && "Biff MaGriff"

mã sau dường như hoạt động chính xác trong 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();
    });
}); 

Thêm IMAGE cũng có thể hữu ích.
mrswadge

tôi giải quyết cái này
Corentin

5

Không chắc chắn tại sao không ai chỉ trả lời điều này - có vẻ như là một câu hỏi kỹ thuật hoàn toàn hợp lý để hỏi liệu điều đó có khả thi hay không.

Không, tôi không nghĩ có một cách trình duyệt chéo để tắt nút backspace. Tôi biết mặc dù nó không được bật trong FF ngày nay.


3
Trừ đi 1 vì không trả lời câu hỏi thực tế và lãng phí thời gian
Andrew

3

Giải pháp này tương tự như các giải pháp khác đã được đăng, nhưng nó sử dụng danh sách trắng đơn giản giúp dễ dàng tùy chỉnh để cho phép backspace trong các thành phần được chỉ định chỉ bằng cách đặt bộ chọn trong hàm .is ().

Tôi sử dụng nó trong hình thức này để ngăn chặn backspace trên các trang điều hướng trở lại:

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

2
Khi người dùng sử dụng nội dung, điều này sẽ làm cho nó bị vô hiệu hóa. Vì vậy, bạn có thể muốn thêm nội dung có thể = true trong danh sách trắng
Miguel

3

Để giải thích một chút về câu trả lời xuất sắc của @ erikkallen , đây là một chức năng cho phép tất cả các loại đầu vào dựa trên bàn phím, bao gồm cả các loại được giới thiệu trong 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();
    }
});

Cảm ơn, tôi đang sử dụng câu trả lời này! Bạn đã tìm thấy bất kỳ vấn đề với các giải pháp này cho đến nay?
Điểm gần

1
Tôi khuyên bạn nên di chuyển các khai báo INPUTTYPES, TEXTRE ra khỏi hàm để chúng không được tính toán lại trên mỗi sự kiện keydown.
thetoolman

3

JavaScript - Cách jQuery:

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

Javascript - cách bản địa, phù hợp với tôi:

<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 Đã ổn đối với trường hợp sử dụng của tôi, từ lâu rồi. Xin vui lòng, đóng góp bằng cách cải thiện / thay đổi câu trả lời của tôi. Cám ơn!
Vladimir Djuricic

3

Tôi đã có một thời gian khó khăn để tìm một câu trả lời không JQUERY. Cảm ơn Stas đã đưa tôi vào đường đua.

Trình duyệt Chrome: Nếu bạn không cần hỗ trợ trình duyệt chéo, bạn chỉ có thể sử dụng danh sách đen, thay vì danh sách trắng. Phiên bản JS thuần này hoạt động trong Chrome, nhưng không phải trong IE. Không chắc chắn về FF.

Trong Chrome (câu 36, giữa năm 2014), các phím bấm không nằm trên yếu tố đầu vào hoặc nội dung có thể được nhắm mục tiêu <BODY>. Điều này làm cho nó có thể sử dụng một danh sách đen, mà tôi thích vào danh sách trắng. IE sử dụng mục tiêu nhấp chuột cuối cùng - vì vậy nó có thể là div hoặc bất cứ thứ gì khác. Điều đó làm cho điều này trở nên vô dụng trong 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();
        }
    }
}  

Trình duyệt chéo: Đối với javascript thuần túy, tôi thấy câu trả lời của Stas là tốt nhất. Thêm một kiểm tra điều kiện nữa cho nội dung có thể làm cho nó hoạt động đối với tôi *:

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

* Lưu ý rằng IE [chỉnh sửa: và Spartan / TechPreview] có "tính năng" làm cho các thành phần liên quan đến bảng không thể được chỉnh sửa . Nếu bạn nhấp vào một trong số đó và nhấn phím lùi, nó sẽ điều hướng trở lại. Nếu bạn không có <td>s có thể chỉnh sửa , đây không phải là vấn đề.


2

Tôi đã gặp một số vấn đề với giải pháp được chấp nhận và plugin Chọn2.js; Tôi không thể xóa các ký tự trong hộp có thể chỉnh sửa vì hành động xóa đang bị ngăn chặn. Đây là giải pháp của tôi:

//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 tạo Span với thuộc tính "contentEditable" được đặt thành true cho hộp tổ hợp có thể chỉnh sửa trong đó. Tôi đã thêm mã vào tài khoản cho tagName và thuộc tính khác nhau. Điều này giải quyết tất cả các vấn đề của tôi.

Chỉnh sửa: Nếu bạn không sử dụng plugin Combo2 cho jquery, thì giải pháp này có thể không cần thiết cho bạn và giải pháp được chấp nhận có thể tốt hơn.


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
Bạn không nên sử dụng return false. e.preventDefault được khuyến nghị. Ngoài ra, bạn đang dừng việc truyền bá sự kiện cho mọi khóa và không chỉ là khoảng lùi. Cuối cùng, keyCode 13 được nhập và câu hỏi là về việc ngăn điều hướng ngược bằng backspace, nhưng điều này sẽ ngăn enter gửi biểu mẫu hoặc thực hiện các hành động khác.
Không có

1

Mã này giải quyết vấn đề trong tất cả các trình duyệt:

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
Tôi thấy mã này không hoạt động như mong đợi do d.tagname được DIVhoặc TD.
Biff MaGriff

Mã từ Haseeb Akhtar hoạt động hoàn hảo trong Chrome và Firefox, nhưng thật bất ngờ !! không có trong IE6-9 có gợi ý nào không?
Martin Andersen

1

Cách đơn giản nhất để ngăn điều hướng khi nhấn backspace

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

Ngăn chặn điều hướng khi nhấn backspcae, đồng thời cho phép backspace với tất cả các điều khiển đầu vào
Mohammed Irfan Mayan

Và đừng bỏ lỡ dòng đầu tiên .. $ (tài liệu) .keydown (function () {
Mohammed Irfan Maya

3
điều này sẽ vô hiệu hóa nút bấm bên trong textareas và đầu vào
gật đầu

1

Sử dụng bộ công cụ Dojo 1.7, công cụ này hoạt động trong 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()});
});

1

Bạn đã thử giải pháp rất đơn giản chỉ cần thêm thuộc tính sau vào trường văn bản chỉ đọc của bạn:

onkeydown = "trả về sai;"

Điều này sẽ giữ cho trình duyệt không quay trở lại trong lịch sử khi nhấn phím Backspace trong trường văn bản chỉ đọc. Có thể tôi đang thiếu ý định thực sự của bạn, nhưng có vẻ như đây sẽ là giải pháp đơn giản nhất cho vấn đề của bạn.


1

Một giải pháp gọn gàng hơn -

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

Thay phiên, bạn chỉ có thể kiểm tra nếu

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

1

Phiên bản javascript thuần, hoạt động trong tất cả các trình duyệt:

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

Tất nhiên, bạn có thể sử dụng "INPUT, TEXTAREA" và sử dụng "if (! Regex.test (yếu tố))". Việc đầu tiên làm việc tốt cho tôi.


1

Hiệu suất?

Tôi đã lo lắng về hiệu suất và thực hiện một câu đố: http://jsfiddle.net/felvhage/k2rT6/9/embedded/result/

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

Tôi đã phân tích các phương pháp hứa hẹn nhất tôi tìm thấy trong chủ đề này. Hóa ra, tất cả chúng đều rất nhanh và hầu hết có thể không gây ra vấn đề gì về "sự chậm chạp" khi gõ. Phương pháp chậm nhất tôi đã xem là khoảng 125 ms cho 10.000 cuộc gọi trong IE8. Đó là 0,0125ms mỗi Đột quỵ.

Tôi thấy các phương thức được đăng bởi Codenepal và Robin Maben là nhanh nhất ~ 0,001ms (IE8) nhưng hãy cẩn thận với các ngữ nghĩa khác nhau.

Có lẽ đây là một sự giải thoát cho ai đó giới thiệu loại chức năng này cho mã của mình.


1

Câu trả lời erikkallen đã sửa đổi:

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

1
Câu trả lời hoàn hảo. Giải pháp mà tôi nhận được từ những người khác đã không hoạt động trong firefox, nhưng giải pháp này hoàn toàn hiệu quả trong cả ba (Firefox, IE và crome) mà không gặp vấn đề gì. Cảm ơn Prozi.
Nikhil Dinesh

1

Giải pháp này hoạt động rất tốt khi thử nghiệm.

Tôi đã thêm một số mã để xử lý một số trường đầu vào không được gắn thẻ đầu vào và để tích hợp trong ứng dụng Oracle PL / SQL tạo biểu mẫu đầu vào cho công việc của tôi.

Theo quan điểm của tôi":

 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

Tôi đã tạo một dự án NPM với phiên bản sạch của hiện đang được chấp nhận (của erikkallen)

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

Về cơ bản, nó sử dụng các nguyên tắc tương tự nhưng:

  • Không phụ thuộc
  • Hỗ trợ cho nội dung
  • Cơ sở mã dễ đọc / duy trì hơn
  • Sẽ được hỗ trợ vì nó sẽ được sử dụng trong sản xuất bởi công ty của tôi
  • Giấy phép MIT

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

1

Dưới đây là bài viết lại của tôi về câu trả lời được bình chọn hàng đầu. Tôi đã cố kiểm tra Element.value! == không xác định (vì một số phần tử như có thể không có thuộc tính html nhưng có thể có thuộc tính giá trị javascript ở đâu đó trên chuỗi nguyên mẫu), tuy nhiên điều đó không hoạt động tốt và có nhiều trường hợp cạnh. Dường như không có cách nào tốt để chứng minh điều này trong tương lai, vì vậy một danh sách trắng dường như là lựa chọn tốt nhất.

Điều này đăng ký phần tử ở cuối giai đoạn bong bóng sự kiện, vì vậy nếu bạn muốn xử lý Backspace theo bất kỳ cách tùy chỉnh nào, bạn có thể làm như vậy trong các trình xử lý khác.

Điều này cũng kiểm tra ví dụ HTMLTextAreE bổ sung vì về mặt lý thuyết người ta có thể có một thành phần web kế thừa từ đó.

Điều này không kiểm tra nội dung Chỉnh sửa (kết hợp với các câu trả lời khác).

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

0

Sơ đồ trang web: Vô hiệu hóa trở lại cho Javascript

event.stopPropagation()event.preventDefault()không làm gì trong IE. Tôi đã phải gửi trả lại event.keyCode == 11(tôi chỉ chọn một cái gì đó) thay vì chỉ nói "if not = 8, run the event"để làm cho nó hoạt động, mặc dù. event.returnValue = falsecũng hoạt động.


0

Một phương pháp khác sử dụng 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>

Xin lưu ý rằng điều này không hoạt động nếu các điều khiển (hộp văn bản) đã được thêm động.
CodeNepal

0

Tôi đã sử dụng mã này trong mã của tôi một thời gian rồi. Tôi viết bài kiểm tra trực tuyến cho sinh viên và gặp vấn đề khi sinh viên đang nhấn backspace trong bài kiểm tra của họ và nó sẽ đưa họ trở lại màn hình đăng nhập. Bực bội! Nó hoạt động trên FF chắc chắn.

document.onkeypress = Backspace;
function Backspace(event) {
    if (event.keyCode == 8) {
        if (document.activeElement.tagName == "INPUT") {
            return true;
        } else {
            return false;
        }
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.