Come posso impedire al tasto backspace di tornare indietro?


275

Su IE posso farlo con jQuery (terribilmente non standard, ma funzionante)

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

Ma è possibile farlo in un modo che funziona su Firefox o in modo cross-browser per un bonus?

Per il record:

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

non fa nulla.

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

risolve il problema, ma rende la chiave backspace inutilizzabile sulla pagina, il che è persino peggiore del comportamento originale.

EDIT: Il motivo per cui lo faccio è che non sto creando una semplice pagina Web ma un'applicazione di grandi dimensioni. È incredibilmente fastidioso perdere 10 minuti di lavoro solo perché hai premuto backspace nel posto sbagliato. Il rapporto tra prevenzione degli errori e fastidiosi utenti dovrebbe essere molto al di sopra di 1000/1 impedendo al tasto backspace di tornare indietro.

EDIT2: Sto Non cercare di impedire la navigazione storia, pochi incidenti.

EDIT3: commento di @brentonstrines (spostato qui poiché la domanda è così popolare): questa è una 'correzione' a lungo termine, ma potresti fornire il tuo supporto dietro il bug Chromium per cambiare questo comportamento nel webkit


137
Perché la chiave backspace è sovraccarica. Potresti non averlo notato, ma probabilmente lo usi sempre per cancellare le lettere che hai appena digitato in un campo di testo. Alcuni dei miei clienti hanno avuto problemi a causare il ritorno della pagina, quindi si tratta di informazioni utili. Nessuno tranne i clown sa che backspace dovrebbe tornare indietro di una pagina. È qualcosa che non ho mai saputo, ed è un comportamento decisamente ostile per un browser. Penso che tutte le pagine dovrebbero disabilitare quel comportamento.
Bretone,

80
Perché la gente pensa che questo sia strano? L'uso del backspace per la navigazione è una scorciatoia davvero stupida! ci sono così tanti campi di testo che gli utenti potrebbero voler eliminare il testo: immagina di avere una lunga risposta SO, passare a un'altra finestra per controllare qualcosa, quindi ritorni e fai clic errato sull'area di modifica, premi backspace per rimuovere una parola e improvvisamente il browser torna indietro di una pagina e potenzialmente hai perso tutto ciò che hai appena scritto.
Peter Boughton,

57
Perché voglio farlo? Non sto creando un sito web ma un'applicazione web. Alcuni campi di input sono di sola lettura, nel qual caso sembrano modificabili, ma se si preme backspace si lascia la pagina. Il rapporto tra le macchine da stampa backspace che intendono navigare indietro e quelle da backspace che cercano di cancellare qualcosa è probabilmente molto inferiore a 1/1000.
1/1000 erikkallen,

42
La domanda è come farlo, non la tua opinione sul fatto che sia una buona idea o meno. Senza conoscere i dettagli del progetto le tue opinioni sono prive di significato. Il mio cliente ha specificamente richiesto questo comportamento per uno dei miei progetti e una vera risposta piuttosto che "Perché mai vorresti farlo?" sarebbe utile.
Nessuna

7
Questa è una 'correzione' a lungo termine, ma potresti fornire il tuo supporto dietro il bug Chromium per cambiare questo comportamento nel webkit: code.google.com/p/chromium/issues/detail?id=144832
brentonstrine

Risposte:


335

Questo codice risolve il problema, almeno in IE e Firefox (non ne ho provato altri, ma gli do una ragionevole possibilità di funzionare se il problema esiste anche in altri browser).

// 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
Rompe i campi della password.
Hemlock,

7
Come ha affermato Hemlock, controlla anche per d.type.toUpperCase() === 'PASSWORD'. Altrimenti sembra buono
stevendesu

17
Dato che stai già utilizzando jQueryif( $(d).is( ":input" ) )...
Paul Alexander,

23
Fa schifo che questa debba essere una lista bianca, piuttosto che essere in grado di inserire nella lista nera la funzionalità "back". Potresti voler aggiungere un check- d.isContentEditablein qui.
iono,

3
Ho creato un progetto NPM con una versione pulita della risposta attualmente accettata: github.com/slorber/backspace-disabler (supporta anche contenteditables e non ha dipendenze)
Sebastien Lorber

62

Questo codice funziona su tutti i browser e ingoia la chiave backspace quando non è su un elemento del modulo o se l'elemento del modulo è disabilitato | readOnly. È anche efficiente, il che è importante quando viene eseguito su ogni chiave digitata.

$(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
Per favore prova il mio esempio, potresti voler aggiornare il tuo codice di conseguenza.
Biff MaGriff,

10
Preferisco questo alla soluzione di @ erikkallen perché è più pulito. Tuttavia, volevo che anche i pulsanti di invio, i pulsanti di opzione e le caselle di controllo fossero ignorati, quindi ho cambiato l'if () in questo: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, vedi il mio commento sulla risposta di erikallen. Questo dovrebbe anche tenere conto di contentEditable.
scossa

10
@MaffooClock: puoi essere più conciso con.is(':checkbox,:radio,:submit')
cdmckay,

1
@cdmckay: non posso credere di non averlo scritto in questo modo in primo luogo. Grazie per aver ripulito tutto per noi :)
Matthew Clark,

41

Le altre risposte qui hanno stabilito che ciò non può essere fatto senza elementi della whitelisting in cui è consentito Backspace. Questa soluzione non è ideale perché la whitelist non è così semplice come semplici input di testo e input di testo / password, ma viene ripetutamente trovata incompleta e deve essere aggiornata.

Tuttavia, poiché lo scopo di sopprimere la funzionalità di backspace è semplicemente quello di impedire agli utenti di perdere accidentalmente dati, la soluzione di pre-caricamento è buona perché il popup modale è sorprendente: i popup modali sono cattivi quando vengono attivati ​​come parte di un flusso di lavoro standard, perché l'utente si abitua a licenziarli senza leggerli e sono fastidiosi. In questo caso, il popup modale sembrerebbe solo un'alternativa a un'azione rara e sorprendente ed è quindi accettabile.

Il problema è che un modale onbeforeunload non deve apparire ogni volta che l'utente si allontana dalla pagina (come quando fa clic su un collegamento o invia un modulo) e non vogliamo iniziare la whitelist o la blacklist specifiche delle condizioni onload prima dello scaricamento.

La combinazione ideale di compromessi per una soluzione generalizzata è la seguente: tenere traccia del fatto che il backspace sia premuto e far apparire il modale onbeforeunload solo se lo è. In altre parole:

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

Questo è stato testato per funzionare in IE7 +, FireFox, Chrome, Safari e Opera. Basta rilasciare questa funzione in global.js e chiamarla da qualsiasi pagina in cui non si desidera che gli utenti perdano accidentalmente i propri dati.

Si noti che un modale onbeforeunload può essere attivato solo una volta, quindi se l'utente preme di nuovo backspace, il modal non si attiverà più.

Nota che questo non si attiverà su eventi di hashchange, tuttavia in quel contesto puoi usare altre tecniche per impedire agli utenti di perdere accidentalmente i loro dati.


2
Sono appena andato ad aggiungere la stessa soluzione e ho visto questo post in fondo alla pagina LOL. Una differenza che ho è impostare lastUserInputWasBackspace = false prima dell'istruzione "Sei sicuro ..." di ritorno, quindi non otterrai il popup se ti capita di fare clic sul pulsante indietro dopo aver già visto il popup (quindi è coerente con non- comportamento influenzato dal backspace).
David Russell,

1
@ user2407309 Ho rimosso il mio commento (non un reclamo) su firefox che non funziona con la tua soluzione. Si è verificato un problema con il mio debugger. Mi scuso per la modifica / violazione del codice. Ora mi rendo conto di aver superato i miei limiti (modifica), perdonami. Mi dispiace davvero e non intendevo lamentarmi della tua meravigliosa soluzione a questo problema. Ancora una volta, le mie scuse. Questo codice funziona bene. Credo che questa sia la risposta migliore e ti raccomando per questo.
Charles Byrne,

1
Questa soluzione ha funzionato sul mio computer locale, ma quando l'ho spostato, il client (almeno alcuni di essi) ha perso la funzionalità di metà dell'applicazione. Immagino che qualcosa lo stia rifiutando, ma non ho idea di cosa.
Steve

1
@Steve, raro o no, se c'è un problema con la funzione, quell'informazione appartiene qui. Voglio solo sapere se c'è davvero un problema.
Vladimir Kornea,

1
Bella soluzione, ma sfortunatamente, se un utente preme accidentalmente backspace due volte, naviga ancora indietro. (almeno su Firefox)
Remco de Zwart,

26

Una soluzione più elegante / concisa:

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

1
Questo è molto più conciso e da quello che posso dire funziona altrettanto bene. Perché la risposta più popolare ha tutti quei controlli per i tipi di input e sembra più complicata? È più affidabile?
Nearpoint,

1
La risposta più popolare è stata la prima a rispondere alla domanda, quindi ai voti alti.
Darwayne,

4
quando i campi di sola lettura sono focalizzati, cancella ancora torna in Chrome
Will D,

16

Modifica della risposta di erikkallen per affrontare diversi tipi di input

Ho scoperto che un utente intraprendente potrebbe premere backspace su una casella di controllo o un pulsante di opzione nel vano tentativo di cancellarlo e invece dovrebbe spostarsi indietro e perdere tutti i suoi dati.

Questa modifica dovrebbe risolvere tale problema.

Nuova modifica per affrontare i div modificabili del contenuto

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

Esempio
Per testare 2 file.

starthere.htm - apri questo per primo in modo da avere un posto dove tornare

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

test.htm - Naviga all'indietro quando si preme backspace mentre la casella di controllo o invia ha lo stato attivo (ottenuto tramite tabulazione). Sostituisci con il mio codice per risolvere.

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

Quale browser hai visto premere backspace alla radio | checkbox | submit -> back function? Non ho mai visto un browser fare questo ...
thetoolman il

Internet Explorer 8 e Chrome
Biff MaGriff,

2
Ho provato diverse altre soluzioni in questo thread, ma questa ha funzionato bene in tutte le mie situazioni e aveva il codice più pulito e più facile da capire. Grazie.
Ezward,

Hai provato @Darwayne Sono curioso di sapere perché quello è così corto e questo è più complesso, ma entrambi sembrano funzionare allo stesso modo per me
Nearpoint

Funziona con i link? Ho un'applicazione ASP.Net con un pulsante immagine per rimuovere un elemento. Questa è l'unica cosa su cui non ha funzionato finora ...
Steve

8

Sulla base dei commenti sembra che tu voglia impedire alle persone di perdere informazioni nei moduli, se premono backspace per eliminare ma il campo non è focalizzato.

In tal caso, si desidera esaminare il gestore eventi onunload . Stack Overflow lo utilizza: se provi a lasciare una pagina quando hai iniziato a scrivere una risposta, viene visualizzato un avviso.


4
mi dispiace che sia stato un commento scortese. Quello che voglio dire è che l'utente probabilmente non vuole essere rimproverato per aver fatto qualcosa che non sapeva nemmeno che fosse sbagliato. Perché non semplicemente mangiare in silenzio la chiave con un onkeydown? L'obiettivo non è impedire completamente all'utente di lasciare la pagina, ma proteggersi da questo errore comune. Inoltre, i dialoghi a comparsa non sono molto efficaci o utili. Gli utenti non li leggono. Sei sicuro di voler lasciare la pagina? Va bene! No aspetta, non volevo lasciare la pagina .. oops troppo tardi.
Breton,

3
OK allora prendilo o lascialo. Penso che tu stia cercando di progettare troppo un problema che non esiste davvero, o almeno non è importante. E nella mia esperienza, sono solo gli utenti esperti che fanno clic su "OK" nelle finestre di dialogo sconosciute senza leggerle correttamente. ;)
DisgruntledGoat

3
Tu e Breton siete la stessa persona? Ad ogni modo ti sei sparato ai piedi lì - l'articolo dice "la risposta di default è Annulla", quindi quando vedono la finestra di dialogo sull'uscita dalla pagina, premeranno "Annulla" e quindi non abbandoneranno la pagina. Tuttavia, va notato che le opzioni di Chrome in quella finestra di dialogo sono "Lascia questa pagina" e "Resta su questa pagina" che sono molto chiare.
DisgruntledGoat

1
No, non sono io, ma ho già incontrato quel link. Penso che i commenti siano esilaranti. "Cosa !? le persone ignorano le finestre di dialogo modali? Dobbiamo trovare un modo per renderle ancora PIÙ persistenti e fastidiose!". Spiega davvero molto sul software Microsoft.
Breton,

3
@Disgruntled: No, non sono bretone e il punto dell'articolo non è "La scelta predefinita è ..." ma "gli utenti non leggono nulla".
erikkallen,

7

Stop dalla navigazione di questo codice funziona!

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

Ma per non limitare i campi di testo ma altri

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

Per impedirlo per un campo specifico basta usare

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

Riferendosi a questo qui sotto!

Impedisci a BACKSPACE di tornare indietro con jQuery (come la home page di Google)


7

La maggior parte delle risposte sono in jquery. Puoi farlo perfettamente in puro Javascript, semplice e senza libreria richiesta. Questo articolo è stato un buon punto di partenza per me, ma poiché keyIdentifier è obsoleto, volevo che questo codice fosse più sicuro, quindi ho aggiunto || e.keyCode == 8 all'istruzione if. Inoltre, il codice non funzionava bene su Firefox, quindi ho aggiunto return false; e ora funziona perfettamente. Ecco qui:

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

Questo codice funziona alla grande perché,

  1. È in puro javascript (nessuna libreria richiesta).
  2. Non solo controlla il tasto premuto, ma conferma se l'azione è realmente un'azione "indietro" del browser.
  3. Insieme a quanto sopra, l'utente può digitare ed eliminare il testo dalle caselle di testo di input sulla pagina Web senza problemi, evitando comunque l'azione del pulsante Indietro.
  4. È corto, pulito, veloce e diretto al punto.

È possibile aggiungere console.log (e); per i tuoi scopi di test e premi F12 in Chrome, vai alla scheda "console" e premi "backspace" sulla pagina e guarda al suo interno per vedere quali valori vengono restituiti, quindi puoi scegliere come target tutti quei parametri per migliorare ulteriormente il codice sopra per soddisfare le tue esigenze.


6

Combinazione di soluzioni fornite da "thetoolman" && "Biff MaGriff"

il seguente codice sembra funzionare correttamente in 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();
    });
}); 

L'aggiunta di IMMAGINE potrebbe anche essere utile.
mrswadge,

mi sono deciso su questo.
Corentin,

5

Non so perché nessuno abbia appena risposto a questa domanda - sembra una domanda tecnica perfettamente ragionevole per chiedersi se sia possibile.

No, non credo che ci sia un modo cross-browser per disabilitare il pulsante backspace. So che al giorno d'oggi non è abilitato per impostazione predefinita in FF.


3
Meno 1 per non rispondere alla domanda effettiva e perdere tempo
Andrew

4

Ho avuto difficoltà a trovare una risposta non JQUERY. Grazie a Stas per avermi messo in pista.

Chrome: se non hai bisogno del supporto per più browser, puoi semplicemente utilizzare una lista nera, piuttosto che una whitelist. Questa pura versione JS funziona in Chrome, ma non in IE. Non sono sicuro di FF.

In Chrome (versione 36, metà 2014), i tasti premuti non su un input o su un elemento contenteditable sembrano essere indirizzati a <BODY>. Ciò rende possibile l'uso di una lista nera, che preferisco autorizzare. IE utilizza la destinazione dell'ultimo clic, quindi potrebbe essere un div o qualsiasi altra cosa. Questo lo rende inutile in 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: per puro javascript, ho trovato la risposta di Stas come la migliore. L'aggiunta di un ulteriore controllo delle condizioni per contenteditable mi ha fatto funzionare *:

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

* Si noti che gli IE [modifica: e Spartan / TechPreview] hanno una "caratteristica" che rende immodificabili gli elementi relativi alla tabella . Se fai clic su uno di questi e POI premi backspace, tornerà indietro. Se non hai messaggi modificabili <td>, questo non è un problema.


3

Questa soluzione è simile ad altre che sono state pubblicate, ma utilizza una semplice whitelist che la rende facilmente personalizzabile per consentire il backspace negli elementi specificati semplicemente impostando il selettore nella funzione .is ().

Lo uso in questo modulo per impedire al backspace delle pagine di tornare indietro:

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

2
Quando l'utente utilizza contenteditable, questo lo renderebbe disabilitato. Quindi potresti voler aggiungere contenteditable = true nella whitelist
Miguel

3

Per approfondire leggermente la risposta eccellente di @ erikkallen , ecco una funzione che consente tutti i tipi di input basati su tastiera, compresi quelli introdotti 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();
    }
});

Grazie, sto usando questa risposta! Finora hai riscontrato problemi con questa soluzione?
Nearpoint,

1
Consiglio di spostare le dichiarazioni INPUTTYPES, TEXTRE fuori dalla funzione in modo che non vengano ricalcolate su ogni evento di keydown.
thetoolman,

3

JavaScript - modo jQuery:

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

Javascript - il modo nativo, che funziona per me:

<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 Va bene per il mio caso d'uso, molto tempo fa. Per favore, sentiti libero di contribuire migliorando / alterando la mia risposta. Grazie!
Vladimir Djuricic,

2

Ho avuto dei problemi con la soluzione accettata e il plugin Select2.js; Non sono stato in grado di eliminare i caratteri nella casella modificabile poiché è stata impedita l'azione di eliminazione. Questa era la mia soluzione:

//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 crea uno span con un attributo di "contentEditable" che è impostato su true per la casella combinata modificabile al suo interno. Ho aggiunto il codice per tenere conto degli spans tagName e del diverso attributo. Questo ha risolto tutti i miei problemi.

Modifica: se non si utilizza il plug-in della casella combinata Select2 per jquery, questa soluzione potrebbe non essere necessaria e la soluzione accettata potrebbe essere migliore.


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
Non dovresti usare return false. Si consiglia e.preventDefault. Inoltre stai interrompendo la propagazione dell'evento per ogni chiave e non solo per il backspace. Infine, keyCode 13 è enter e la domanda riguardava la prevenzione della navigazione posteriore con backspace, ma ciò impediva a enter di inviare il modulo o eseguire altre azioni.
Nessuno

1

Questo codice risolve il problema in tutti i 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
Trovo che questo codice non funzioni come previsto a causa del nome d.tagname DIVo TD.
Biff MaGriff,

Il codice di Haseeb Akhtar funziona perfettamente su Chrome e Firefox, ma sorprende !! non in IE6-9 Qualche suggerimento?
Martin Andersen,

1

Il modo più semplice per impedire la navigazione premendo backspace

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

Impedisce la navigazione premendo backspcae e allo stesso tempo consente il backspace con tutti i controlli di input
Mohammed Irfan Mayan

E non perdere la prima riga .. $ (documento) .keydown (funzione () {
Mohammed Irfan Mayan

3
questo disabiliterà il pulsante indietro all'interno di textareas e input
nodrog

1

Utilizzando Dojo toolkit 1.7, funziona in 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

Hai provato la soluzione molto semplice di aggiungere il seguente attributo al tuo campo di testo di sola lettura:

onkeydown = "return false;"

Ciò impedirà al browser di tornare indietro nella cronologia quando si preme il tasto Backspace in un campo di testo di sola lettura. Forse mi manca il tuo vero intento, ma sembra che questa sarebbe la soluzione più semplice al tuo problema.


1

Una soluzione molto più ordinata -

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

In alternativa, puoi solo verificare se

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

1

Versione javascript pura, che funziona in tutti i 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;
    }
  }
}

Ovviamente puoi usare "INPUT, TEXTAREA" e usare "if (! Regex.test (elements))" allora. Il primo ha funzionato bene per me.


1

Prestazione?

Ero preoccupato per le prestazioni e ho suonato un violino: http://jsfiddle.net/felvhage/k2rT6/9/embedded/result/

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

Ho analizzato i metodi più promettenti che ho trovato in questo thread. Si scopre che sono stati tutti molto veloci e molto probabilmente non causano problemi in termini di "lentezza" durante la digitazione. Il metodo più lento che ho osservato è stato di circa 125 ms per 10.000 chiamate in IE8. Che è 0,0125 ms per colpo.

Ho trovato i metodi pubblicati da Codenepal e Robin Maben per essere il più veloce ~ 0.001ms (IE8) ma attenzione alle diverse semantiche.

Forse questo è un sollievo per qualcuno che introduce questo tipo di funzionalità nel suo codice.


1

Risposta erikkallen modificata:

$(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
Risposta perfetta La soluzione che ho ottenuto da altri non ha funzionato in Firefox, ma questa ha funzionato perfettamente in tutti e tre (Firefox, IE e crome) senza alcun problema. Grazie Prozi.
Nikhil Dinesh,

1

Questa soluzione ha funzionato molto bene quando testata.

Ho aggiunto del codice per gestire alcuni campi di input non contrassegnati con l'input e per integrarmi in un'applicazione Oracle PL / SQL che genera un modulo di input per il mio lavoro.

I miei due centesimi":

 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

Ho creato un progetto NPM con una versione pulita di quella attualmente accettata (di erikkallen)

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

Utilizza sostanzialmente gli stessi principi ma:

  • Nessuna dipendenza
  • Supporto per contenteditable
  • Base di codice più leggibile / gestibile
  • Sarà supportato in quanto verrà utilizzato nella produzione dalla mia azienda
  • Licenza 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

Ecco la mia riscrittura della risposta più votata. Ho provato a controllare element.value! == undefined (dal momento che alcuni elementi come potrebbero non avere alcun attributo html ma potrebbero avere una proprietà del valore javascript da qualche parte nella catena del prototipo), tuttavia ciò non ha funzionato molto bene e ha avuto molti casi limite. Non sembra esserci un buon modo per renderlo a prova di futuro, quindi una lista bianca sembra l'opzione migliore.

Ciò registra l'elemento al termine della fase di bolla dell'evento, quindi se si desidera gestire Backspace in qualsiasi modo personalizzato, è possibile farlo in altri gestori.

Questo controlla anche l'istanza di HTMLTextAreElement poiché si potrebbe teoricamente avere un componente web che eredita da quello.

Questo non controlla contentEditable (combinalo con altre risposte).

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: disabilita indietro per Javascript

event.stopPropagation()e event.preventDefault()non fare nulla in IE. Ho dovuto inviare il reso event.keyCode == 11(ho appena scelto qualcosa) invece di dire semplicemente "if not = 8, run the event"di farlo funzionare, però. event.returnValue = falsefunziona anche.


0

Un altro metodo che utilizza 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>

Si noti che questo non funziona se i controlli (casella di testo) sono stati aggiunti in modo dinamico.
CodeNepal,

0

Lo sto usando nel mio codice da un po 'di tempo ormai. Scrivo test online per gli studenti e ho riscontrato il problema quando gli studenti premevano backspace durante il test e li riportava alla schermata di accesso. Frustrante! Funziona sicuramente su FF.

document.onkeypress = Backspace;
function Backspace(event) {
    if (event.keyCode == 8) {
        if (document.activeElement.tagName == "INPUT") {
            return true;
        } else {
            return false;
        }
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.