Bagaimana saya bisa mencegah tombol backspace dari menavigasi kembali?


275

Pada IE saya bisa melakukan ini dengan jQuery (sangat tidak standar, tetapi berfungsi)

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

Tetapi apakah mungkin dilakukan dengan cara yang berfungsi pada Firefox, atau dengan cara lintas-browser untuk mendapatkan bonus?

Untuk catatan:

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

tidak melakukan apa-apa.

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

memecahkan masalah, tetapi membuat kunci ruang mundur tidak dapat digunakan pada halaman, yang bahkan lebih buruk daripada perilaku asli.

EDIT: Alasan saya melakukan ini adalah karena saya tidak membuat halaman web sederhana tetapi aplikasi besar. Sangat menyebalkan kehilangan 10 menit kerja hanya karena Anda menekan backspace di tempat yang salah. Rasio mencegah kesalahan vs pengguna yang mengganggu harus jauh di atas 1000/1 dengan mencegah backspace key dari menavigasi kembali.

EDIT2: Saya tidak berusaha mencegah navigasi riwayat, hanya kecelakaan.

EDIT3: komentar @brentonstrines (pindah ke sini karena pertanyaannya sangat populer): Ini adalah 'perbaikan' jangka panjang, tetapi Anda dapat membuang dukungan Anda di balik bug Chromium untuk mengubah perilaku ini di webkit


137
Karena tombol backspace kelebihan beban. Anda mungkin tidak memperhatikannya, tetapi Anda mungkin menggunakannya sepanjang waktu untuk menghapus huruf yang baru saja Anda ketikkan dalam bidang teks. Beberapa pelanggan saya mengalami masalah dengan hal itu yang menyebabkan halaman kembali, jadi ini adalah informasi yang berguna. Tidak seorang pun kecuali Anda, badut yang tahu bahwa backspace seharusnya mengembalikan satu halaman. Itu adalah sesuatu yang tidak pernah saya ketahui, dan ini merupakan perilaku bermusuhan yang dimiliki browser. Saya pikir semua halaman harus menonaktifkan perilaku itu.
Breton

80
Mengapa orang berpikir ini aneh? Menggunakan backspace untuk navigasi adalah jalan pintas yang sangat bodoh! ada begitu banyak bidang teks yang pengguna mungkin ingin menghapus teks - bayangkan memiliki jawaban SO yang panjang, beralih ke jendela lain untuk memeriksa sesuatu, dan kemudian Anda kembali dan salah klik area edit, tekan backspace untuk menghapus kata dan tiba-tiba browser kembali ke halaman dan Anda berpotensi kehilangan semua yang baru saja Anda tulis.
Peter Boughton

57
Kenapa saya ingin melakukan ini? Saya tidak membuat situs web tetapi aplikasi web. Beberapa kolom input hanya-baca dalam hal ini mereka terlihat dapat diedit, tetapi jika Anda menekan backspace Anda meninggalkan halaman. Rasio penekanan backspace yang berniat untuk bernavigasi kembali vs tekanan backspace yang mencoba menghapus sesuatu mungkin jauh lebih kecil dari 1/1000.
erikkallen

42
Pertanyaannya adalah bagaimana melakukan ini, bukan pendapat Anda tentang apakah itu ide yang bagus atau tidak. Tanpa mengetahui detail proyek, pendapat Anda tidak ada artinya. Klien saya secara khusus meminta perilaku ini untuk salah satu proyek saya dan jawaban yang sebenarnya daripada "Mengapa Anda ingin melakukan itu?" akan sangat membantu.
Tidak ada

7
Ini adalah 'perbaikan' jangka panjang, tetapi Anda dapat memberikan dukungan di belakang bug Chromium untuk mengubah perilaku ini di webkit: code.google.com/p/chromium/issues/detail?id=144832
brentonstrine

Jawaban:


335

Kode ini memecahkan masalah, setidaknya di IE dan Firefox (belum menguji yang lain, tapi saya memberikan kesempatan yang masuk akal untuk bekerja jika masalahnya bahkan ada di browser lain).

// 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
Hancurkan bidang kata sandi.
Hemlock

7
Seperti yang dinyatakan Hemlock - periksa d.type.toUpperCase() === 'PASSWORD'juga. Jika tidak, terlihat bagus
stevendesu

17
Karena Anda sudah menggunakan jQueryif( $(d).is( ":input" ) )...
Paul Alexander

23
Ini menyebalkan bahwa ini harus menjadi daftar putih, daripada bisa daftar hitam fungsi "kembali". Anda mungkin ingin menambahkan cek d.isContentEditabledi sini.
iono

3
Saya membuat proyek NPM dengan versi bersih dari jawaban yang saat ini diterima: github.com/slorber/backspace-disabler (ini juga mendukung contenteditable dan tidak memiliki ketergantungan)
Sebastien Lorber

62

Kode ini berfungsi pada semua browser dan menelan tombol backspace ketika tidak pada elemen form, atau jika elemen form dinonaktifkan | readOnly. Ini juga efisien, yang penting ketika dijalankan pada setiap kunci yang diketikkan.

$(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
Silakan uji contoh saya, Anda mungkin ingin memperbarui kode Anda sesuai.
Biff MaGriff

10
Saya lebih suka ini daripada solusi @ erikkallen karena lebih bersih. Namun, saya ingin mengirim tombol, tombol radio, dan kotak centang juga diabaikan, jadi saya mengubah if () menjadi ini: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

@ theoolman, lihat komentar saya pada jawaban erikallen. Ini juga harus menjelaskan contentEditable.
Sentakan

10
@MaffooClock: Anda bisa lebih ringkas dengan.is(':checkbox,:radio,:submit')
cdmckay

1
@cdmckay: Saya tidak percaya saya tidak menulis seperti itu sejak awal. Terima kasih telah membersihkan itu untuk kita semua :)
Matthew Clark

41

Jawaban lain di sini telah menetapkan bahwa ini tidak dapat dilakukan tanpa elemen daftar putih di mana Backspace diizinkan. Solusi ini tidak ideal karena daftar putih tidak semudah hanya textareas dan input teks / kata sandi, tetapi berulang kali ditemukan tidak lengkap dan perlu diperbarui.

Namun, karena tujuan menekan fungsionalitas backspace hanyalah untuk mencegah pengguna kehilangan data secara tidak sengaja, solusi beforeunload adalah solusi yang bagus karena modal popup mengejutkan - modal popup buruk ketika dipicu sebagai bagian dari alur kerja standar, karena pengguna terbiasa mengabaikannya tanpa membacanya, dan mereka menjengkelkan. Dalam hal ini, popup modal hanya akan muncul sebagai alternatif untuk tindakan yang langka dan mengejutkan, dan karenanya dapat diterima.

Masalahnya adalah modal sebelumnya tidak boleh muncul setiap kali pengguna menavigasi jauh dari halaman (seperti ketika mengklik tautan atau mengirimkan formulir), dan kami tidak ingin memulai daftar putih atau memasukkan daftar hitam khusus pada kondisi sebelum memuat.

Kombinasi ideal pengorbanan untuk solusi umum adalah sebagai berikut: melacak apakah backspace ditekan, dan hanya memunculkan modal onbeforeunload jika itu. Dengan kata lain:

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

Ini telah diuji untuk berfungsi di IE7 +, FireFox, Chrome, Safari, dan Opera. Cukup masukkan fungsi ini ke global.js Anda dan panggil dari halaman mana pun di mana Anda tidak ingin pengguna kehilangan data mereka.

Perhatikan bahwa modal onbeforeunload hanya dapat dipicu sekali, jadi jika pengguna menekan backspace lagi, modal tidak akan menyala lagi.

Perhatikan bahwa ini tidak akan memicu pada acara hashchange, namun dalam konteks itu Anda dapat menggunakan teknik lain untuk mencegah pengguna kehilangan data secara tidak sengaja.


2
Saya hanya pergi untuk menambahkan solusi yang sama dan melihat posting ini di bagian bawah halaman LOL. Satu perbedaan yang saya miliki adalah mengatur lastUserInputWasBackspace = false sebelum mengembalikan pernyataan "Apakah Anda yakin ...", jadi Anda tidak mendapatkan munculan jika Anda mengklik tombol kembali setelah melihat munculan (sehingga konsisten dengan perilaku yang dipengaruhi backspace).
David Russell

1
@ user2407309 Saya telah menghapus komentar saya (bukan keluhan) tentang firefox yang tidak berfungsi dengan solusi Anda. Ada masalah dengan debugger saya. Permintaan maaf saya untuk mengedit / memecahkan kode Anda. Saya menyadari sekarang bahwa saya melampaui batas saya (mengedit) maafkan saya. Saya benar-benar minta maaf dan saya tidak bermaksud mengeluh atas solusi hebat Anda untuk masalah ini. Sekali lagi, permintaan maaf saya. Kode ini berfungsi dengan baik. Saya percaya ini adalah jawaban terbaik dan saya memuji Anda untuk itu.
Charles Byrne

1
Solusi ini bekerja pada mesin lokal saya, tetapi ketika saya memindahkannya, klien (setidaknya beberapa dari mereka) kehilangan fungsionalitas setengah aplikasi. Saya kira ada sesuatu yang menolaknya, tetapi saya tidak tahu apa.
Steve

1
@Steve, langka atau tidak, jika ada masalah dengan fungsinya, informasi itu berada di sini. Saya hanya ingin tahu apakah memang ada masalah.
Vladimir Kornea

1
Solusi yang bagus, tetapi sayangnya, jika pengguna secara tidak sengaja menekan backspace dua kali, itu masih menavigasi kembali. (setidaknya pada firefox)
Remco de Zwart

26

Solusi yang lebih elegan / ringkas:

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

1
Ini jauh lebih ringkas dan dari apa yang saya dapat katakan berhasil juga. Mengapa jawaban yang paling populer memiliki semua yang memeriksa jenis input, dan tampaknya lebih rumit? Apakah ini lebih dapat diandalkan?
Nearpoint

1
Jawaban yang paling populer adalah yang pertama untuk menjawab pertanyaan, dengan demikian suara yang tinggi.
Darwayne

4
ketika bidang yang hanya dibaca terfokus, hapus masih menavigasi kembali di chrome
Will D

16

Modifikasi Jawaban erikkallen untuk mengatasi berbagai jenis input

Saya telah menemukan bahwa pengguna yang giat dapat menekan backspace pada kotak centang atau tombol radio dalam upaya sia-sia untuk menghapusnya dan sebaliknya mereka akan menavigasi mundur dan kehilangan semua data mereka.

Perubahan ini harus mengatasi masalah itu.

Edit Baru untuk membahas konten yang dapat diedit

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

Contoh
Untuk menguji membuat 2 file.

starthere.htm - buka ini dulu sehingga Anda punya tempat untuk kembali

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

test.htm - Ini akan menavigasi mundur ketika backspace ditekan saat kotak centang atau kirim memiliki fokus (dicapai dengan tabbing). Ganti dengan kode saya untuk memperbaikinya.

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

Browser apa yang Anda lihat tekan backspace di radio | checkbox | submit -> kembali fungsi? Saya belum melihat browser melakukan ini ..
thetoolman

Internet Explorer 8 dan Chrome
Biff MaGriff

2
Saya mencoba sejumlah solusi lain di utas ini, tetapi yang ini bekerja dengan baik dalam semua situasi saya dan memiliki kode yang paling bersih dan termudah untuk dipahami. Terima kasih.
Ezward

Apakah Anda mencoba @Darwayne Saya ingin tahu mengapa yang begitu pendek dan ini lebih kompleks, tetapi keduanya tampaknya bekerja sama untuk saya
Nearpoint

Apakah ini berfungsi pada tautan? Saya memiliki aplikasi ASP.Net dengan tombol gambar untuk menghapus item. Itulah satu-satunya hal yang belum berhasil sejauh ini ...
Steve

8

Berdasarkan komentar, tampaknya Anda ingin menghentikan orang kehilangan informasi dalam bentuk, jika mereka menekan backspace untuk menghapus tetapi bidang tidak fokus.

Dalam hal ini, Anda ingin melihat event handler onunload . Stack Overflow menggunakannya - jika Anda mencoba untuk meninggalkan halaman ketika Anda mulai menulis jawaban, itu muncul peringatan.


4
maaf itu komentar kasar. Maksud saya adalah, pengguna mungkin tidak ingin dimarahi karena melakukan sesuatu yang mereka bahkan tidak tahu itu salah. Mengapa tidak diam saja makan kunci dengan onkeydown? Tujuannya bukan untuk sepenuhnya mencegah pengguna meninggalkan halaman, tetapi untuk menjaga dari kesalahan umum ini. Selain itu, dialog sembulan tidak terlalu efektif, atau berguna. Pengguna tidak membacanya. Anda yakin ingin meninggalkan halaman? Baik! Tidak tunggu tunggu, saya tidak ingin meninggalkan halaman .. oops terlambat
Breton

3
OK lalu ambil atau tinggalkan. Saya pikir Anda mencoba merekayasa secara berlebihan masalah yang tidak benar-benar ada, atau setidaknya tidak penting. Dan dalam pengalaman saya, hanya pengguna berkuasa yang mengklik "OK" pada dialog yang tidak dikenal tanpa membacanya dengan benar. ;)
DisgruntledGoat

3
Apakah Anda dan Breton adalah orang yang sama? Ngomong-ngomong, Anda agak menembak diri Anda sendiri di sana - artikel itu mengatakan "jawaban defaultnya adalah Cancel" jadi ketika melihat dialog tentang meninggalkan halaman, mereka akan menekan "Cancel" dan karenanya tidak meninggalkan halaman tersebut. Meskipun harus dicatat bahwa opsi Chrome pada dialog itu adalah "Tinggalkan halaman ini" dan "Tetap di halaman ini" yang sangat jelas.
DisgruntledGoat

1
Tidak, dia bukan aku, tapi aku pernah menemukan tautan itu sebelumnya. Saya pikir komentarnya lucu. "Apa !? Orang-orang mengabaikan kotak dialog modal? Kita harus menemukan cara untuk membuat mereka LEBIH gigih dan menjengkelkan!". Benar-benar menjelaskan banyak tentang perangkat lunak microsoft.
Breton

3
@ Disgruntled: Tidak, saya bukan Breton, dan maksud artikelnya bukanlah "Pilihan default adalah ..." tetapi "pengguna tidak membaca apa pun."
erikkallen

7

Berhenti menavigasi kode ini berfungsi!

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

Tetapi untuk tidak membatasi bidang teks tetapi yang lain

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

Untuk mencegahnya untuk bidang tertentu cukup gunakan

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

Mengacu pada yang di bawah ini!

Cegah BACKSPACE dari menavigasi kembali dengan jQuery (Seperti Beranda Google)


7

Sebagian besar jawabannya adalah jquery. Anda dapat melakukan ini dengan sempurna dalam Javascript murni, sederhana dan tidak perlu pustaka. Artikel ini adalah titik awal yang baik bagi saya tetapi karena keyIdentifier sudah tidak digunakan lagi, saya ingin kode ini lebih aman sehingga saya menambahkan || e.keyCode == 8 ke pernyataan if. Juga, kode tidak berfungsi dengan baik pada Firefox jadi saya menambahkan return false; dan sekarang ini bekerja dengan sangat baik. Ini dia:

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

Kode ini berfungsi dengan baik karena,

  1. Itu dalam javascript murni (tidak perlu perpustakaan)
  2. Tidak hanya memeriksa tombol yang ditekan, itu menegaskan apakah tindakan itu benar-benar tindakan "kembali" browser.
  3. Bersama dengan hal di atas, pengguna dapat mengetik dan menghapus teks dari kotak teks input pada halaman web tanpa masalah sambil tetap mencegah aksi tombol kembali.
  4. Ini pendek, bersih, cepat dan langsung ke intinya.

Anda dapat menambahkan console.log (e); untuk keperluan pengujian Anda, dan tekan F12 di chrome, buka tab "konsol" dan tekan "backspace" pada halaman dan lihat di dalamnya untuk melihat nilai apa yang dikembalikan, maka Anda dapat menargetkan semua parameter tersebut untuk lebih meningkatkan kode di atas sesuai dengan kebutuhan Anda.


6

Menggabungkan solusi yang diberikan oleh "thetoolman" && "Biff MaGriff"

kode berikut tampaknya berfungsi dengan benar di 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();
    });
}); 

Menambahkan IMAGE mungkin juga berguna.
mrswadge

Saya memutuskan yang ini.
Corentin

5

Tidak yakin mengapa tidak ada yang menjawab ini - sepertinya pertanyaan teknis yang masuk akal untuk menanyakan apakah itu mungkin.

Tidak, saya tidak berpikir ada cara lintas browser untuk menonaktifkan tombol backspace. Saya tahu itu tidak diaktifkan secara default di FF hari ini.


3
Minus 1 karena tidak menjawab pertanyaan aktual dan membuang-buang waktu
Andrew

4

Saya kesulitan menemukan jawaban non-JQUERY. Terima kasih kepada Stas karena telah menempatkan saya di trek.

Chrome: Jika Anda tidak memerlukan dukungan lintas browser, Anda bisa menggunakan daftar hitam, bukan daftar putih. Versi JS murni ini berfungsi di Chrome, tetapi tidak di IE. Tidak yakin tentang FF.

Di Chrome (ver. 36, pertengahan 2014), penekanan tombol yang bukan pada input atau elemen yang dapat diedit tampaknya ditargetkan untuk <BODY>. Ini memungkinkan menggunakan daftar hitam, yang saya pilih untuk masuk daftar putih. IE menggunakan target klik terakhir - jadi mungkin div atau apa pun. Itu membuat ini tidak berguna di 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();
        }
    }
}  

Cross Browser: Untuk javascript murni, saya menemukan jawaban Stas sebagai yang terbaik. Menambahkan satu lagi pemeriksaan kondisi untuk konten yang dapat diedit membuatnya berfungsi untuk saya *:

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

* Perhatikan bahwa IEs [edit: dan Spartan / TechPreview] memiliki "fitur" yang membuat elemen terkait tabel tidak dapat diedit . Jika Anda mengklik salah satunya dan MAKA tekan backspace, itu AKAN menavigasi kembali. Jika Anda tidak memiliki <td>s yang dapat diedit , ini bukan masalah.


3

Solusi ini mirip dengan yang lain yang telah diposting, tetapi menggunakan daftar putih sederhana sehingga mudah disesuaikan untuk memungkinkan backspace dalam elemen tertentu hanya dengan mengatur pemilih dalam fungsi .is ().

Saya menggunakannya dalam formulir ini untuk mencegah backspace pada halaman dari menavigasi kembali:

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

2
Saat pengguna menggunakan contenteditable, ini akan membuatnya dinonaktifkan. Jadi, Anda mungkin ingin menambahkan contenteditable = true dalam daftar putih
Miguel

3

Untuk sedikit menguraikan jawaban luar biasa @ erikkallen , berikut adalah fungsi yang memungkinkan semua jenis input berbasis keyboard, termasuk yang diperkenalkan dalam 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();
    }
});

Terima kasih, saya menggunakan jawaban ini! Apakah Anda menemukan masalah dengan solusi ini sejauh ini?
Nearpoint

1
Saya akan merekomendasikan memindahkan INPUTTYPES, deklarasi TEXTRE keluar dari fungsi sehingga mereka tidak dihitung ulang pada setiap peristiwa keydown.
thetoolman

3

JavaScript - cara jQuery:

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

Javascript - cara asli, yang berfungsi untuk saya:

<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 Tidak apa-apa untuk kasus penggunaan saya, sejak lama. Tolong, silakan berkontribusi dengan meningkatkan / mengubah jawaban saya. Terima kasih!
Vladimir Djuricic

2

Saya punya beberapa masalah dengan solusi yang diterima dan plugin Select2.js; Saya tidak dapat menghapus karakter dalam kotak yang dapat diedit karena tindakan penghapusan sedang dicegah. Ini solusi saya:

//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 membuat Span dengan atribut "contentEditable" yang disetel ke true untuk kotak kombo yang dapat diedit di dalamnya. Saya menambahkan kode ke akun untuk span tagName dan atribut yang berbeda. Ini menyelesaikan semua masalah saya.

Sunting: Jika Anda tidak menggunakan plugin combobox Select2 untuk jquery, maka solusi ini mungkin tidak diperlukan oleh Anda, dan solusi yang diterima mungkin lebih baik.


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
Anda seharusnya tidak menggunakan return false. e.preventDefault direkomendasikan. Anda juga menghentikan penyebaran acara untuk setiap kunci dan bukan hanya backspace. Akhirnya, keyCode 13 dimasukkan dan pertanyaannya adalah tentang mencegah navigasi kembali dengan backspace, tetapi ini akan mencegah masuk mengirimkan formulir atau melakukan tindakan lain.
Tidak ada

1

Kode ini menyelesaikan masalah di semua browser:

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
Saya menemukan kode ini tidak berfungsi seperti yang diharapkan karena d.tagname menjadi DIVatau TD.
Biff MaGriff

Kode dari Haseeb Akhtar berfungsi dengan sempurna di Chrome dan Firefox, tetapi mengejutkan !! tidak dalam IE6-9 Ada saran?
Martin Andersen

1

Cara termudah untuk mencegah navigasi saat menekan backspace

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

Mencegah navigasi pada menekan backspcae, dan pada saat yang sama memungkinkan backspace dengan semua kontrol input
Mohammed Irfan Mayan

Dan jangan lewatkan baris pertama .. $ (document) .keydown (function () {
Mohammed Irfan Mayan

3
ini akan menonaktifkan tombol belakang di dalam textareas dan input
nodrog

1

Menggunakan Dojo toolkit 1.7, ini berfungsi di 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

Sudahkah Anda mencoba solusi yang sangat sederhana dengan hanya menambahkan atribut berikut ke bidang teks hanya baca Anda:

onkeydown = "return false;"

Ini akan menjaga browser agar tidak kembali ke riwayat ketika tombol Backspace ditekan dalam bidang teks hanya baca. Mungkin saya kehilangan niat Anda yang sebenarnya, tetapi sepertinya ini akan menjadi solusi paling sederhana untuk masalah Anda.


1

Solusi yang jauh lebih rapi -

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

Bergantian, Anda hanya dapat memeriksa apakah

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

1

Versi javascript murni, yang berfungsi di semua browser:

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

Tentu saja Anda dapat menggunakan "INPUT, TEXTAREA" dan gunakan "if (! Regex.test (elements))" lalu. Yang pertama bekerja dengan baik untuk saya.


1

Performa?

Saya khawatir tentang kinerja dan membuat biola: http://jsfiddle.net/felvhage/k2rT6/9/embedded/result/

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

Saya telah menganalisis metode paling menjanjikan yang saya temukan di utas ini. Ternyata, mereka semua sangat cepat dan kemungkinan besar tidak menimbulkan masalah dalam hal "kelesuan" saat mengetik. Metode paling lambat yang saya lihat adalah sekitar 125 ms untuk 10.000 Panggilan di IE8. Yaitu 0,0125 ms per Stroke.

Saya menemukan metode yang diposting oleh Codenepal dan Robin Maben menjadi yang tercepat ~ 0.001ms (IE8) tetapi waspadalah terhadap semantik yang berbeda.

Mungkin ini melegakan bagi seseorang yang memperkenalkan fungsi semacam ini pada kodenya.


1

Jawaban erikkallen yang dimodifikasi:

$(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
Jawaban sempurna. Solusi yang saya dapatkan dari orang lain tidak bekerja di firefox, tetapi yang ini bekerja dengan sempurna di ketiganya (Firefox, IE dan crome) tanpa masalah. Prozi terima kasih.
Nikhil Dinesh

1

Solusi ini bekerja dengan sangat baik ketika diuji.

Saya memang menambahkan beberapa kode untuk menangani beberapa bidang input yang tidak ditandai dengan input, dan untuk mengintegrasikan dalam aplikasi Oracle PL / SQL yang menghasilkan formulir input untuk pekerjaan saya.

"Dua sen" saya:

 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

Saya membuat proyek NPM dengan versi bersih dari erikkallen yang saat ini diterima

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

Pada dasarnya ia menggunakan prinsip yang sama tetapi:

  • Tidak ada ketergantungan
  • Dukungan untuk konten yang dapat diedit
  • Basis kode lebih mudah dibaca / dipelihara
  • Akan didukung karena akan digunakan dalam produksi oleh perusahaan saya
  • Lisensi 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

Inilah penulisan ulang jawaban yang saya pilih. Saya mencoba memeriksa element.value! == undefined (karena beberapa elemen seperti mungkin tidak memiliki atribut html tetapi mungkin memiliki properti nilai javascript di suatu tempat di rantai prototipe), namun itu tidak berfungsi dengan baik dan memiliki banyak kasus tepi. Tampaknya tidak ada cara yang baik untuk membuktikan di masa depan, jadi daftar putih tampaknya merupakan pilihan terbaik.

Ini mendaftarkan elemen pada akhir fase gelembung acara, jadi jika Anda ingin menangani Backspace dengan cara kustom apa pun, Anda bisa melakukannya di penangan lain.

Ini juga memeriksa instance dari HTMLTextAreElement karena seseorang secara teoritis dapat memiliki komponen web yang diwarisi dari itu.

Ini tidak memeriksa contentEditable (gabungkan dengan jawaban lain).

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

Sitepoint: Nonaktifkan kembali untuk Javascript

event.stopPropagation()dan event.preventDefault()tidak melakukan apa pun di IE. Saya harus mengirim kembali event.keyCode == 11(saya hanya mengambil sesuatu) daripada hanya mengatakan "if not = 8, run the event"untuk membuatnya bekerja. event.returnValue = falsejuga berfungsi.


0

Metode lain menggunakan 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>

Harap dicatat ini tidak berfungsi jika kontrol (kotak teks) telah ditambahkan secara dinamis.
CodeNepal

0

Saya telah menggunakan ini dalam kode saya untuk beberapa waktu sekarang. Saya menulis tes online untuk siswa dan mengalami masalah ketika siswa menekan backspace selama tes mereka dan itu akan membawa mereka kembali ke layar login. Frustrasi! Ini bekerja pada FF pasti.

document.onkeypress = Backspace;
function Backspace(event) {
    if (event.keyCode == 8) {
        if (document.activeElement.tagName == "INPUT") {
            return true;
        } else {
            return false;
        }
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.