Wie kann ich verhindern, dass die Rücktaste zurück navigiert?

275

Im IE kann ich dies mit der (furchtbar nicht standardmäßigen, aber funktionierenden) jQuery tun

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

Aber ist es möglich, dies auf eine Weise zu tun, die unter Firefox funktioniert, oder auf eine browserübergreifende Weise, um einen Bonus zu erhalten?

Für die Aufzeichnung:

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

tut nichts.

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

Behebt das Problem, macht jedoch die Rücktaste auf der Seite unbrauchbar, was noch schlimmer ist als das ursprüngliche Verhalten.

BEARBEITEN: Der Grund dafür ist, dass ich keine einfache Webseite erstelle, sondern eine große Anwendung. Es ist unglaublich ärgerlich, 10 Minuten Arbeit zu verlieren, nur weil Sie die Rücktaste an der falschen Stelle gedrückt haben. Das Verhältnis zwischen Fehlervermeidung und nervigen Benutzern sollte weit über 1000/1 liegen, indem verhindert wird, dass die Rücktaste zurück navigiert.

EDIT2: Ich versuche nicht , die Verlaufsnavigation zu verhindern, sondern nur Unfälle.

EDIT3: @ brentonstrines Kommentar (hierher verschoben, da die Frage so beliebt ist): Dies ist eine langfristige 'Korrektur', aber Sie könnten Ihre Unterstützung hinter den Chromium-Fehler werfen , um dieses Verhalten im Webkit zu ändern

erikkallen
quelle
137
Weil die Rücktaste überladen ist. Sie haben es vielleicht nicht bemerkt, aber Sie verwenden es wahrscheinlich die ganze Zeit, um Buchstaben zu löschen, die Sie gerade in ein Textfeld eingegeben haben. Einige meiner Kunden hatten Probleme damit, dass die Seite zurückging. Dies sind nützliche Informationen. Niemand , aber sie weiß , dass Clowns Backspace ist angeblich eine Seite zurück zu gehen. Das habe ich nie gewusst und es ist ein geradezu feindseliges Verhalten eines Browsers. Ich denke, alle Seiten sollten dieses Verhalten deaktivieren.
Breton
80
Warum finden die Leute das seltsam? Die Verwendung der Rücktaste für die Navigation ist eine wirklich dumme Abkürzung! Es gibt so viele Textfelder, aus denen Benutzer möglicherweise Text löschen möchten. Stellen Sie sich vor, Sie haben eine lange SO-Antwort, wechseln zu einem anderen Fenster, um etwas zu überprüfen. Dann kehren Sie zurück und klicken falsch auf den Bearbeitungsbereich. Drücken Sie die Rücktaste, um ein Wort zu entfernen Plötzlich geht der Browser eine Seite zurück und Sie haben möglicherweise alles verloren, was Sie gerade geschrieben haben.
Peter Boughton
57
Warum will ich das machen? Ich erstelle keine Website, sondern eine Webanwendung. Einige Eingabefelder sind schreibgeschützt. In diesem Fall können sie bearbeitet werden. Wenn Sie jedoch die Rücktaste drücken, verlassen Sie die Seite. Das Verhältnis von Rücktaste-Pressen, die zurück navigieren
möchten, zu Rücktaste-
42
Die Frage ist, wie das geht, nicht Ihre Meinung, ob es eine gute Idee ist oder nicht. Ohne die Details des Projekts zu kennen, sind Ihre Meinungen bedeutungslos. Mein Kunde hat dieses Verhalten speziell für eines meiner Projekte und eine echte Antwort angefordert und nicht "Warum sollten Sie das jemals tun wollen?" Wäre hilfreich.
Keine
7
Dies ist eine langfristige "Lösung", aber Sie können Ihre Unterstützung hinter den Chromium-Fehler werfen, um dieses Verhalten im Webkit zu ändern: code.google.com/p/chromium/issues/detail?id=144832
brentonstrine

Antworten:

335

Dieser Code löst das Problem, zumindest in IE und Firefox (habe keinen anderen getestet, aber ich gebe ihm eine vernünftige Chance zu arbeiten, wenn das Problem sogar in anderen Browsern besteht).

// 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;
        }
    }
});
erikkallen
quelle
6
Bricht Passwortfelder.
Hemlock
7
Wie Hemlock sagte - überprüfen Sie d.type.toUpperCase() === 'PASSWORD'auch. Ansonsten sieht gut aus
stevendesu
17
Da Sie bereits jQuery verwendenif( $(d).is( ":input" ) )...
Paul Alexander
23
Es ist schade, dass dies eine Whitelist sein muss, anstatt die "Zurück" -Funktionalität auf die schwarze Liste setzen zu können. Vielleicht möchten Sie hier einen Check- d.isContentEditablein hinzufügen .
Iono
3
Ich habe ein NPM-Projekt mit einer sauberen Version der aktuell akzeptierten Antwort erstellt: github.com/slorber/backspace-disabler (es unterstützt auch contenteditables und hat keine Abhängigkeit)
Sebastien Lorber
62

Dieser Code funktioniert in allen Browsern und verschluckt die Rücktaste, wenn er sich nicht in einem Formularelement befindet oder wenn das Formularelement deaktiviert ist | readOnly. Es ist auch effizient, was wichtig ist, wenn es für jeden eingegebenen Schlüssel ausgeführt wird.

$(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();
            }
        }
    });
});
der Werkzeugmann
quelle
1
Bitte testen Sie mein Beispiel. Möglicherweise möchten Sie Ihren Code entsprechend aktualisieren.
Biff MaGriff
10
Ich bevorzuge die Lösung von @ erikkallen, weil sie sauberer ist. Ich wollte jedoch, dass Senden-Schaltflächen, Optionsfelder und Kontrollkästchen ebenfalls ignoriert werden, also habe ich if () in 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, siehe meinen Kommentar zu erikallens Antwort. Dies sollte auch berücksichtigen contentEditable.
Ruck
10
@MaffooClock: Sie können prägnanter sein mit.is(':checkbox,:radio,:submit')
cdmckay
1
@cdmckay: Ich kann nicht glauben, dass ich es überhaupt nicht so geschrieben habe. Danke, dass du das für uns alle aufgeräumt
Matthew Clark
41

Die anderen Antworten hier haben gezeigt, dass dies nicht ohne Whitelist-Elemente möglich ist, in denen die Rücktaste zulässig ist. Diese Lösung ist nicht ideal, da die Whitelist nicht so einfach ist wie nur Textbereiche und Text- / Passworteingaben, sondern wiederholt als unvollständig befunden wird und aktualisiert werden muss.

Da der Zweck der Unterdrückung der Backspace-Funktionalität lediglich darin besteht, zu verhindern, dass Benutzer versehentlich Daten verlieren, ist die Lösung vor dem Herunterladen eine gute Lösung, da das modale Popup überraschend ist - modale Popups sind schlecht, wenn sie als Teil eines Standard-Workflows ausgelöst werden. weil der Benutzer sich daran gewöhnt, sie zu entlassen, ohne sie zu lesen, und sie nerven. In diesem Fall erscheint das modale Popup nur als Alternative zu einer seltenen und überraschenden Aktion und ist daher akzeptabel.

Das Problem ist, dass ein Onbeforeunload-Modal nicht angezeigt werden darf, wenn der Benutzer von der Seite weg navigiert (z. B. beim Klicken auf einen Link oder beim Senden eines Formulars), und wir nicht damit beginnen möchten, bestimmte Onbeforeunload-Bedingungen auf die Whitelist zu setzen oder auf die schwarze Liste zu setzen.

Die ideale Kombination von Kompromissen für eine verallgemeinerte Lösung lautet wie folgt: Verfolgen Sie, ob die Rücktaste gedrückt wird, und öffnen Sie das Onbeforeunload-Modal nur, wenn dies der Fall ist. Mit anderen Worten:

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

Dies wurde getestet, um in IE7 +, FireFox, Chrome, Safari und Opera zu funktionieren. Legen Sie diese Funktion einfach in Ihrer Datei global.js ab und rufen Sie sie von einer beliebigen Seite aus auf, auf der Benutzer nicht versehentlich ihre Daten verlieren sollen.

Beachten Sie, dass ein Onbeforeunload-Modal nur einmal ausgelöst werden kann. Wenn der Benutzer also erneut die Rücktaste drückt, wird das Modal nicht erneut ausgelöst.

Beachten Sie, dass dies bei Hashchange-Ereignissen nicht ausgelöst wird. In diesem Zusammenhang können Sie jedoch andere Techniken verwenden, um zu verhindern, dass Benutzer versehentlich ihre Daten verlieren.

Vladimir Kornea
quelle
2
Ich habe gerade dieselbe Lösung hinzugefügt und diesen Beitrag am Ende der Seite LOL gesehen. Ein Unterschied, den ich habe, besteht darin, lastUserInputWasBackspace = false vor der Rückgabe der Anweisung "Sind Sie sicher ..." zu setzen, damit Sie das Popup nicht erhalten, wenn Sie zufällig auf die Schaltfläche "Zurück" klicken, nachdem Sie das Popup bereits gesehen haben (es ist also konsistent mit Nicht- Rücktaste-beeinflusstes Verhalten).
David Russell
1
@ user2407309 Ich habe meinen Kommentar (keine Beschwerde) darüber entfernt, dass Firefox nicht mit Ihrer Lösung funktioniert. Es gab ein Problem mit meinem Debugger. Ich entschuldige mich für das Bearbeiten / Brechen Ihres Codes. Mir ist jetzt klar, dass ich meine Grenzen überschritten habe (Bearbeitung), vergib mir. Es tut mir wirklich leid und ich meinte keine Beschwerden über Ihre wunderbare Lösung für dieses Problem. Nochmals, ich entschuldige mich. Dieser Code funktioniert gut. Ich glaube, das ist die beste Antwort und ich empfehle Ihnen dafür.
Charles Byrne
1
Diese Lösung funktionierte auf meinem lokalen Computer, aber als ich sie verschob, verlor der Client (zumindest einige von ihnen) die Funktionalität der Hälfte der Anwendung. Ich denke, etwas lehnt es ab, aber ich habe keine Ahnung, was.
Steve
1
@Steve, selten oder nicht, wenn es ein Problem mit der Funktion gibt, gehören diese Informationen hierher. Ich möchte nur wissen, ob es wirklich ein Problem gibt.
Vladimir Kornea
1
Gute Lösung, aber wenn ein Benutzer versehentlich zweimal die Rücktaste drückt, navigiert er leider immer noch zurück. (zumindest auf Firefox)
Remco de Zwart
26

Eine elegantere / prägnantere Lösung:

$(document).on('keydown',function(e){
  var $target = $(e.target||e.srcElement);
  if(e.keyCode == 8 && !$target.is('input,[contenteditable="true"],textarea'))
  {
    e.preventDefault();
  }
})
Darwayne
quelle
1
Das ist viel prägnanter und soweit ich das beurteilen kann, funktioniert es genauso gut. Warum prüft die beliebteste Antwort alle diese Arten von Eingaben und scheint komplizierter zu sein? Ist es zuverlässiger?
Nearpoint
1
Die beliebteste Antwort war die erste, die die Frage beantwortete, also die hohen Stimmen.
Darwayne
4
Wenn schreibgeschützte Felder fokussiert sind, navigiert Löschen immer noch in Chrom zurück
Will D
16

Änderung der Antwort von erikkallen, um verschiedene Eingabetypen anzusprechen

Ich habe festgestellt, dass ein unternehmungslustiger Benutzer bei einem vergeblichen Versuch, es zu löschen, die Rücktaste auf einem Kontrollkästchen oder einem Optionsfeld drücken könnte. Stattdessen würde er rückwärts navigieren und alle seine Daten verlieren.

Diese Änderung sollte dieses Problem beheben.

Neue Bearbeitung, um inhaltsbearbeitbare Divs zu adressieren

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

Beispiel
Zum Testen machen Sie 2 Dateien.

starthere.htm - öffne dies zuerst, damit du einen Ort hast, zu dem du zurückkehren kannst

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

test.htm - Dies navigiert rückwärts, wenn die Rücktaste gedrückt wird, während das Kontrollkästchen oder das Senden den Fokus hat (erreicht durch Tabulieren). Ersetzen Sie durch meinen Code, um zu beheben.

<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>
Biff MaGriff
quelle
Welchen Browser haben Sie gesehen, wie die Rücktaste auf Radio | Kontrollkästchen | Senden -> Zurück-Funktion gedrückt wurde? Ich habe noch keinen Browser gesehen, der dies tat.
Toolman
Internet Explorer 8 und Chrome
Biff MaGriff
2
Ich habe in diesem Thread eine Reihe anderer Lösungen ausprobiert, aber diese funktionierte in all meinen Situationen gut und hatte den saubersten und am einfachsten zu verstehenden Code. Danke dir.
Ezward
Haben Sie @Darwayne ausprobiert? Ich bin gespannt, warum dieser so kurz und komplexer ist, aber beide scheinen für mich genauso zu funktionieren
Nearpoint
Funktioniert das bei Links? Ich habe eine ASP.Net-Anwendung mit einer Bildschaltfläche zum Entfernen eines Elements. Das ist das einzige, woran das bisher noch nicht funktioniert hat ...
Steve
8

Basierend auf den Kommentaren scheint es, dass Sie verhindern möchten, dass Personen Informationen in Formularen verlieren, wenn sie zum Löschen die Rücktaste drücken, das Feld jedoch nicht fokussiert ist.

In diesem Fall möchten Sie sich den Ereignishandler onunload ansehen . Stack Overflow verwendet es. Wenn Sie versuchen, eine Seite zu verlassen, wenn Sie mit dem Schreiben einer Antwort begonnen haben, wird eine Warnung angezeigt.

DisgruntledGoat
quelle
4
Entschuldigung, das war ein unhöflicher Kommentar. Ich meine, der Benutzer möchte wahrscheinlich nicht beschimpft werden, wenn er etwas tut, von dem er nicht einmal wusste, dass es falsch ist. Warum nicht einfach still den Schlüssel mit einem Onkeydown essen? Das Ziel ist nicht, den Benutzer vollständig daran zu hindern, die Seite zu verlassen, sondern sich vor diesem häufigen Fehler zu schützen. Darüber hinaus sind Popup-Dialoge nicht sehr effektiv oder nützlich. Benutzer lesen sie nicht. Möchten Sie die Seite wirklich verlassen? Okay! Nein, warte, warte, ich wollte die Seite nicht verlassen. Ups zu spät.
Breton
3
OK, dann nimm es oder lass es. Ich denke, Sie versuchen, ein Problem zu überentwickeln, das nicht wirklich existiert oder zumindest nicht wichtig ist. Und meiner Erfahrung nach sind es nur Power-User, die in unbekannten Dialogen auf "OK" klicken, ohne sie richtig zu lesen. ;)
DisgruntledGoat
3
Sind Sie und Breton dieselbe Person? Wie auch immer, Sie haben sich dort irgendwie in den Fuß geschossen - der Artikel sagt "Die Standardantwort ist Abbrechen". Wenn Sie also den Dialog zum Verlassen der Seite sehen, drücken sie "Abbrechen" und verlassen die Seite daher nicht . Es ist jedoch zu beachten, dass die Optionen von Chrome in diesem Dialogfeld "Diese Seite verlassen" und "Auf dieser Seite bleiben" sehr klar sind.
DisgruntledGoat
1
Nein, er ist nicht ich, aber ich bin schon einmal auf diesen Link gestoßen. Ich finde die Kommentare komisch. "Was !? Leute ignorieren modale Dialogfelder? Wir müssen einen Weg finden, sie noch beständiger und nerviger zu machen!". Erklärt wirklich viel über Microsoft-Software.
Bretonischer
3
@Disgruntled: Nein, ich bin kein Breton und der Punkt des Artikels ist nicht "Die Standardauswahl ist ...", sondern "Benutzer lesen nichts".
Erikkallen
7

Stoppen Sie die Navigation in diesem Code funktioniert!

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

Aber um nicht Textfelder einzuschränken, sondern andere

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

Um dies für ein bestimmtes Feld zu verhindern, verwenden Sie einfach

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

Bezugnehmend auf dieses unten!

Verhindern Sie, dass BACKSPACE mit jQuery zurück navigiert (wie die Google-Startseite).

Syed Ehtsham Abbas
quelle
7

Die meisten Antworten sind in jquery. Sie können dies perfekt in reinem Javascript tun, einfach und ohne Bibliothek. Dieser Artikel war ein guter Ausgangspunkt für mich, aber da keyIdentifier veraltet ist, wollte ich, dass dieser Code sicherer ist, und fügte der if-Anweisung || e.keyCode == 8 hinzu . Außerdem funktionierte der Code in Firefox nicht gut, daher habe ich return false hinzugefügt . und jetzt funktioniert es perfekt. Hier ist es:

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

Dieser Code funktioniert gut, weil,

  1. Es ist in reinem Javascript (keine Bibliothek erforderlich).
  2. Es überprüft nicht nur die gedrückte Taste, sondern bestätigt auch, ob es sich bei der Aktion wirklich um eine "Zurück" -Aktion des Browsers handelt.
  3. Zusammen mit dem oben Gesagten kann der Benutzer problemlos Text aus Eingabetextfeldern auf der Webseite eingeben und löschen, ohne die Aktion der Zurück-Schaltfläche zu verhindern.
  4. Es ist kurz, sauber, schnell und direkt auf den Punkt.

Sie können console.log (e) hinzufügen. Für Ihre Testzwecke und drücken Sie F12 in Chrome, gehen Sie zur Registerkarte "Konsole" und klicken Sie auf "Rücktaste" auf der Seite und schauen Sie hinein, um zu sehen, welche Werte zurückgegeben werden. Dann können Sie alle diese Parameter als Ziel festlegen, um den Code weiter zu verbessern oben, um Ihren Bedürfnissen zu entsprechen.

Tarik
quelle
6

Kombinieren von Lösungen von "thetoolman" && "Biff MaGriff"

Der folgende Code scheint in IE 8 / Mozilla / Chrome korrekt zu funktionieren

$(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();
    });
}); 
CodeNepal
quelle
Das Hinzufügen von IMAGE kann ebenfalls hilfreich sein.
Frau Wadge
Ich habe mich für diesen entschieden.
Corentin
5

Ich bin mir nicht sicher, warum niemand dies gerade beantwortet hat - scheint eine völlig vernünftige technische Frage zu sein, ob es möglich ist.

Nein, ich glaube nicht, dass es eine browserübergreifende Möglichkeit gibt, die Rücktaste zu deaktivieren. Ich weiß, dass es heutzutage in FF nicht standardmäßig aktiviert ist.

Brabster
quelle
3
Minus 1 für die Nichtbeantwortung der eigentlichen Frage und Zeitverschwendung
Andrew
3

Diese Lösung ähnelt anderen, die veröffentlicht wurden, verwendet jedoch eine einfache Whitelist, die leicht anpassbar ist, um die Rücktaste in bestimmten Elementen zuzulassen, indem Sie einfach den Selektor in der Funktion .is () festlegen.

Ich verwende es in dieser Form, um zu verhindern, dass die Rücktaste auf den Seiten zurück navigiert:

$(document).on("keydown", function (e) {
    if (e.which === 8 && !$(e.target).is("input:not([readonly]), textarea")) {
        e.preventDefault();
    }
});
Keiner
quelle
2
Wenn der Benutzer contenteditable verwendet, wird dies deaktiviert. Vielleicht möchten Sie also contenteditable = true in die Whitelist aufnehmen
Miguel
3

Um die hervorragende Antwort von @ erikkallen etwas näher zu erläutern , finden Sie hier eine Funktion, die alle tastaturbasierten Eingabetypen zulässt, einschließlich der in HTML5 eingeführten :

$(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();
    }
});
Gingi
quelle
Danke, ich benutze diese Antwort! Haben Sie bisher Probleme mit diesen Lösungen gefunden?
Nearpoint
1
Ich würde empfehlen, die Deklarationen INPUTTYPES, TEXTRE aus der Funktion zu entfernen, damit sie nicht bei jedem Keydown-Ereignis neu berechnet werden.
Werkzeugmann
3

JavaScript - jQuery Weg:

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

Javascript - der native Weg, der für mich funktioniert:

<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>
Vladimir Djuricic
quelle
@ MichaelPotter Es war okay für meinen Anwendungsfall vor langer Zeit. Bitte zögern Sie nicht, einen Beitrag zu leisten, indem Sie meine Antwort verbessern / ändern. Danke!
Vladimir Djuricic
3

Es fiel mir schwer, eine Antwort zu finden, die nicht von JQUERY stammt. Vielen Dank an Stas, der mich auf die Strecke gebracht hat.

Chrome: Wenn Sie keine browserübergreifende Unterstützung benötigen, können Sie statt einer Whitelist nur eine Blacklist verwenden. Diese reine JS-Version funktioniert in Chrome, jedoch nicht im IE. Ich bin mir nicht sicher über FF.

In Chrome (Version 36, Mitte 2014) scheinen Tastendrücke, die nicht auf eine Eingabe oder ein inhaltsbearbeitbares Element gerichtet sind, gezielt zu sein <BODY>. Dies ermöglicht die Verwendung einer Blacklist, die ich der Whitelist vorziehe. IE verwendet das Ziel für den letzten Klick - es kann sich also um ein Div oder etwas anderes handeln. Das macht dies im IE nutzlos.

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: Für reines Javascript fand ich die Antwort von Stas die beste. Durch Hinzufügen einer weiteren Bedingungsprüfung für contenteditable funktionierte dies für mich *:

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

* Beachten Sie, dass IEs [edit: und Spartan / TechPreview] eine "Funktion" haben, die tabellenbezogene Elemente unbearbeitbar macht . Wenn Sie auf eine dieser Optionen klicken und dann die Rücktaste drücken, wird zurück navigiert. Wenn Sie keine bearbeitbaren <td>s haben, ist dies kein Problem.

Josiah
quelle
2

Ich hatte einige Probleme mit der akzeptierten Lösung und dem Select2.js-Plugin. Ich konnte keine Zeichen in der bearbeitbaren Box löschen, da die Löschaktion verhindert wurde. Das war meine Lösung:

//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 erstellt einen Span mit dem Attribut "contentEditable", das für das bearbeitbare Kombinationsfeld darin auf "true" gesetzt ist. Ich habe Code hinzugefügt, um den Bereich tagName und das andere Attribut zu berücksichtigen. Dies löste alle meine Probleme.

Bearbeiten: Wenn Sie das Combobox-Plugin Select2 nicht für jquery verwenden, wird diese Lösung möglicherweise nicht von Ihnen benötigt, und die akzeptierte Lösung ist möglicherweise besser.

Pytry
quelle
1
    document.onkeydown = function (e) {    
        e.stopPropagation();
        if ((e.keyCode==8  ||  e.keyCode==13) &&
            (e.target.tagName != "TEXTAREA") && 
            (e.target.tagName != "INPUT")) { 
            return false;
        }
    };
elico3000
quelle
2
Sie sollten return false nicht verwenden. e.preventDefault wird empfohlen. Außerdem stoppen Sie die Weitergabe des Ereignisses für jeden Schlüssel und nicht nur für die Rücktaste. Schließlich wird keyCode 13 eingegeben, und es ging darum, die Rücknavigation mit der Rücktaste zu verhindern. Dies würde jedoch verhindern, dass die Eingabe das Formular sendet oder andere Aktionen ausführt.
Keine
1

Dieser Code löst das Problem in allen Browsern:

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

  }
Haseeb Akhtar
quelle
1
Ich finde, dass dieser Code nicht wie erwartet funktioniert, da der d.tagname DIVoder ist TD.
Biff MaGriff
Der Code von Haseeb Akhtar funktioniert perfekt in Chrome und Firefox, aber Überraschung !! nicht in IE6-9 Irgendwelche Vorschläge?
Martin Andersen
1

Einfachste Möglichkeit, die Navigation beim Drücken der Rücktaste zu verhindern

$(document).keydown(function () {
    if (event.keyCode == 8) {
        if (event.target.nodeName == 'BODY') {
            event.preventDefault();
        }
    }
});
Mohammed Irfan Mayan
quelle
Verhindert die Navigation beim Drücken von Backspcae und ermöglicht gleichzeitig die Rücktaste bei allen Eingabesteuerelementen
Mohammed Irfan Mayan
Und verpassen Sie nicht die erste Zeile .. $ (Dokument) .keydown (Funktion () {
Mohammed Irfan Mayan
3
Dadurch wird der Backbutton in Textbereichen und Eingaben deaktiviert
Nodrog
1

Mit Dojo Toolkit 1.7 funktioniert dies 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()});
});
Chris V.
quelle
1

Haben Sie die sehr einfache Lösung ausprobiert, einfach das folgende Attribut zu Ihrem schreibgeschützten Textfeld hinzuzufügen:

onkeydown = "return false;"

Dadurch wird verhindert, dass der Browser in den Verlauf zurückkehrt, wenn die Rücktaste in einem schreibgeschützten Textfeld gedrückt wird. Vielleicht fehlt mir Ihre wahre Absicht, aber dies scheint die einfachste Lösung für Ihr Problem zu sein.

B-Hund
quelle
1

Eine viel sauberere Lösung -

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

Alternativ können Sie nur prüfen, ob

$(document.activeElement).is('body')
Robin Maben
quelle
1

Reine Javascript-Version, die in allen Browsern funktioniert:

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

Natürlich können Sie dann "INPUT, TEXTAREA" und dann "if (! Regex.test (elements))" verwenden. Das erste hat gut für mich funktioniert.

Stanislav Parkhomenko
quelle
1

Performance?

Ich machte mir Sorgen um die Leistung und machte eine Geige: http://jsfiddle.net/felvhage/k2rT6/9/embedded/result/

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

Ich habe die vielversprechendsten Methoden analysiert, die ich in diesem Thread gefunden habe. Es stellte sich heraus, dass sie alle sehr schnell waren und höchstwahrscheinlich kein Problem in Bezug auf "Trägheit" beim Tippen verursachen. Die langsamste Methode, die ich mir angesehen habe, war ungefähr 125 ms für 10.000 Aufrufe in IE8. Das sind 0,0125 ms pro Hub.

Ich fand die von Codenepal und Robin Maben veröffentlichten Methoden am schnellsten ~ 0,001 ms (IE8), aber Vorsicht vor der unterschiedlichen Semantik.

Vielleicht ist dies eine Erleichterung für jemanden, der diese Art von Funktionalität in seinen Code einführt.

felvhage
quelle
1

Geänderte erikkallen Antwort:

$(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;
    }
});
Jacek Pietal
quelle
1
Perfekte Antwort. Die Lösung, die ich von anderen bekommen habe, hat in Firefox nicht funktioniert, aber diese hat in allen drei (Firefox, IE und Crome) problemlos funktioniert. Danke Prozi.
Nikhil Dinesh
1

Diese Lösung hat beim Testen sehr gut funktioniert.

Ich habe Code hinzugefügt, um einige Eingabefelder zu verarbeiten, die nicht mit Eingaben versehen sind, und um sie in eine Oracle PL / SQL-Anwendung zu integrieren, die ein Eingabeformular für meinen Job generiert.

Meine zwei Cent":

 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";
      }                              
   }
Luis Cuellar
quelle
1

Ich habe ein NPM-Projekt mit einer sauberen Version der aktuell akzeptierten (von erikkallen) erstellt.

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

Es verwendet im Grunde die gleichen Prinzipien, aber:

  • Keine Abhängigkeit
  • Unterstützung für inhaltsbearbeitbare
  • Besser lesbare / wartbare Codebasis
  • Wird unterstützt, da es von meiner Firma in der Produktion verwendet wird
  • MIT-Lizenz

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);
};
Sebastien Lorber
quelle
1

Hier ist meine Neufassung der am besten bewerteten Antwort. Ich habe versucht, element.value! == undefined zu überprüfen (da einige Elemente wie möglicherweise kein HTML-Attribut haben, aber möglicherweise irgendwo in der Prototypenkette eine Javascript-Werteigenschaft haben), aber das hat nicht sehr gut funktioniert und viele Randfälle. Es scheint keinen guten Weg zu geben, dies zukunftssicher zu machen, daher scheint eine Whitelist die beste Option zu sein.

Dadurch wird das Element am Ende der Ereignisblasenphase registriert. Wenn Sie also die Rücktaste auf benutzerdefinierte Weise behandeln möchten, können Sie dies in anderen Handlern tun.

Dies prüft auch die Instanz von HTMLTextAreElement, da theoretisch eine Webkomponente vorhanden sein könnte, die davon erbt.

Dies überprüft contentEditable nicht (kombiniert mit anderen Antworten).

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
Ninjagecko
quelle
0

Sitepoint: Zurück für Javascript deaktivieren

event.stopPropagation()und event.preventDefault()nichts im IE tun. Ich musste eine Rücksendung senden event.keyCode == 11(ich habe gerade etwas ausgewählt), anstatt nur zu sagen "if not = 8, run the event", dass es funktioniert. event.returnValue = falsefunktioniert auch.

Tom
quelle
0

Eine andere Methode mit 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>
CodeNepal
quelle
Bitte beachten Sie, dass dies nicht funktioniert, wenn Steuerelemente (Textfeld) dynamisch hinzugefügt wurden.
CodeNepal
0

Ich benutze dies seit einiger Zeit in meinem Code. Ich schreibe Online-Tests für Schüler und bin auf das Problem gestoßen, als die Schüler während ihres Tests die Rücktaste gedrückt haben und sie zum Anmeldebildschirm zurückkehren. Frustrierend! Es funktioniert auf FF sicher.

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