web-dev-qa-db-fra.com

Comment puis-je empêcher la touche Retour arrière de revenir en arrière?

Sur IE je peux le faire avec jQuery (terriblement non standard, mais fonctionnel)

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

Mais est-il possible de le faire d'une manière qui fonctionne sur Firefox, ou d'une manière multi-navigateur pour un bonus?

Pour mémoire:

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

ne fait rien.

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

résout le problème, mais rend la touche Retour arrière inutilisable sur la page, ce qui est encore pire que le comportement d'origine.

EDIT: La raison pour laquelle je le fais est que je ne crée pas une simple page Web, mais une grande application. Il est incroyablement agaçant de perdre 10 minutes de travail simplement parce que vous avez appuyé sur la touche de retour arrière au mauvais endroit. Le rapport prévention des erreurs par rapport aux utilisateurs agaçants devrait être bien supérieur à 1000/1 en empêchant la touche Retour arrière de revenir en arrière.

EDIT2: Je n'essaie pas d'empêcher la navigation dans l'historique, mais uniquement les accidents.

EDIT3: Commentaire de @brentonstrines (déplacé ici depuis que la question est si populaire): Il s'agit d'un 'correctif' à long terme, mais vous pouvez jeter votre soutien derrière le bug de Chromium pour modifier ce comportement dans webkit

266
erikkallen

Ce code résout le problème, du moins dans IE et Firefox (n’en ai testé aucun autre, mais je lui donne une chance raisonnable de fonctionner si le problème existe même dans d’autres navigateurs).

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

Ce code fonctionne sur tous les navigateurs et avale la touche Retour arrière lorsqu'il ne se trouve pas sur un élément de formulaire ou si l'élément de formulaire est désactivé | readOnly. Il est également efficace, ce qui est important lorsqu’il s’applique à chaque clé saisie.

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

Les autres réponses ici ont établi que cela ne pouvait se faire sans éléments de la liste blanche dans lesquels le retour arrière est autorisé. Cette solution n’est pas idéale car la liste blanche n’est pas aussi simple que les entrées textareas et text/password, mais elle est maintes fois incomplète et doit être mise à jour.

Cependant, comme la suppression de la fonctionnalité de retour arrière a simplement pour but d'empêcher les utilisateurs de perdre accidentellement des données, la solution beforeunload est intéressante car la fenêtre contextuelle modale est surprenante - les fenêtres contextuelles modales sont mauvaises lorsqu'elles sont déclenchées dans le cadre d'un processus standard parce que l'utilisateur s'habitue à les renvoyer sans les lire et qu'ils sont ennuyeux. Dans ce cas, la fenêtre contextuelle modale n'apparaîtrait que comme une alternative à une action rare et surprenante, et est donc acceptable.

Le problème est qu’un modal onbeforeunload ne doit pas apparaître lorsque l’utilisateur navigue en dehors de la page (par exemple, lorsqu'il clique sur un lien ou soumet un formulaire) et que nous ne voulons pas commencer à mettre des listes blanches ou des listes noires dans des conditions spécifiques.

La combinaison idéale de compromis pour une solution généralisée est la suivante: notez si le retour arrière est enfoncé et affichez le modal onbeforeunload s'il l'est. En d'autres termes:

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

Cela a été testé pour fonctionner dans IE7 +, FireFox, Chrome, Safari et Opera. Déposez simplement cette fonction dans votre fichier global.js et appelez-la depuis n'importe quelle page sur laquelle vous ne souhaitez pas que les utilisateurs perdent leurs données par accident.

Notez que cela ne déclenchera pas d'événements hashchange. Toutefois, dans ce contexte, vous pouvez utiliser d'autres techniques pour empêcher les utilisateurs de perdre accidentellement leurs données.

41
Vladimir Kornea

Une solution plus élégante/concise:

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

Modification de la réponse de erikkallen pour traiter différents types d'entrée

J'ai découvert qu'un utilisateur entreprenant pouvait appuyer sur le retour arrière d'une case à cocher ou d'un bouton radio pour tenter de l'effacer, mais au lieu de cela, il reviendrait en arrière et perdrait toutes ses données.

Ce changement devrait résoudre ce problème.

Nouvelle édition pour adresser le contenu éditable divs

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

Exemple
Pour tester créer 2 fichiers.

starthere.htm - ouvrez cette première pour avoir un endroit où retourner à

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

test.htm - Cette option permet de revenir en arrière lorsque vous appuyez sur la touche Retour arrière ou que la case à cocher ou le bouton Soumettre a le focus (obtenu par tabulation). Remplacez par mon code pour corriger.

<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>
15
Biff MaGriff

Selon les commentaires, il semble que vous souhaitiez empêcher les personnes de perdre des informations dans les formulaires, si elles appuient sur la touche retour pour la supprimer mais que le champ n'est pas ciblé.

Dans ce cas, vous souhaitez consulter le gestionnaire d'événements onunload. Stack Overflow l'utilise. Si vous essayez de quitter une page lorsque vous avez commencé à rédiger une réponse, un avertissement s'affiche.

8
DisgruntledGoat

Arrêtez de naviguer ce code fonctionne!

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

Mais pour ne pas restreindre les champs de texte mais les autres

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

Pour éviter cela pour un domaine spécifique, utilisez simplement

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

En référence à celui-ci ci-dessous!

Empêchez BACKSPACE de revenir en arrière avec jQuery (comme la page d'accueil de Google)

7
Syed Ehtsham Abbas

La plupart des réponses sont en JQuery. Vous pouvez le faire parfaitement en Javascript pur, simple et aucune bibliothèque requise. Cet article était un bon point de départ pour moi, mais comme keyIdentifier est obsolète, je voulais que ce code soit plus sécurisé, donc je ajouté || e.keyCode == 8 à l'instruction if. De plus, le code ne fonctionnait pas bien sur Firefox, alors j'ai ajouté , qui renvoie false; et maintenant, il fonctionne parfaitement. C'est ici:

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

Ce code fonctionne très bien car,

  1. Il est en javascript pur (aucune bibliothèque requise).
  2. Non seulement il vérifie la touche enfoncée, mais il confirme si l'action est vraiment une action "de retour" du navigateur.
  3. Avec ce qui précède, l'utilisateur peut taper et supprimer du texte des zones de texte de saisie sur la page Web sans aucun problème, tout en empêchant l'action du bouton Précédent.
  4. C'est court, propre, rapide et droit au but.

Vous pouvez ajouter console.log (e); Pour vos besoins de test, appuyez sur F12 en chrome, accédez à l'onglet "Console", cliquez sur "retour arrière" sur la page et regardez à l'intérieur pour voir les valeurs renvoyées. Vous pouvez ensuite cibler tous ces paramètres pour améliorer encore le code. ci-dessus pour répondre à vos besoins.

6
Tarik

Combinaison de solutions données par "thetoolman" && "Biff MaGriff"

le code suivant semble fonctionner correctement dans 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();
    });
}); 
5
CodeNepal

Je ne sais pas pourquoi personne ne vient de répondre à cette question - cela semble être une question technique tout à fait raisonnable de demander si c'est possible.

Non, je ne pense pas qu'il existe un moyen inter-navigateur de désactiver le bouton de retour arrière. Je sais que ce n'est pas activé par défaut dans FF ces jours-ci.

5
brabster

JavaScript - manière jQuery:

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

Javascript - à la manière native, ça marche pour moi:

<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>
3
Vladimir Djuricic

Cette solution est similaire aux autres qui ont été publiées, mais elle utilise une simple liste blanche le rendant facilement personnalisable pour autoriser le retour arrière dans les éléments spécifiés en définissant simplement le sélecteur dans la fonction .is ().

Je l'utilise sous cette forme pour empêcher le retour arrière des pages:

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

J'ai eu du mal à trouver une réponse non-JQUERY. Merci à Stas de m'avoir mis sur la piste.

Chrome: Si vous n'avez pas besoin de la prise en charge multi-navigateurs, vous pouvez simplement utiliser une liste noire, plutôt qu'une liste blanche. Cette version JS pure fonctionne dans Chrome, mais pas dans IE. Pas sûr de FF.

Dans Chrome (ver. 36, mi-2014), les pressions sur les touches autres que celles d'un élément d'entrée ou contenteditable semblent être ciblées sur <BODY>. Cela permet d'utiliser une liste noire, que je préfère ajouter à la liste blanche. IE utilise la cible du dernier clic - ce peut donc être une div ou autre chose. Cela rend cela inutile dans 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: Pour le javascript pur, j'ai trouvé que la réponse de Stas était la meilleure. L'ajout d'une vérification de condition supplémentaire pour contenteditable l'a fait fonctionner pour moi *:

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

* Notez que les IE [edit: et Spartan/TechPreview] ont une "fonctionnalité" qui rend éléments liés à la table non modifiables . Si vous cliquez sur l'un de ceux-ci et appuyez sur backspace, il reviendra en arrière. Si vous n'avez pas de <td>s éditable, ce n'est pas un problème.

3
Josiah

Pour élaborer légèrement sur l'excellente réponse de @ erikkallen , voici une fonction qui autorise tous les types de saisie basés sur le clavier, y compris ceux introduits dans 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();
    }
});
3
Gingi

J'ai eu quelques problèmes avec la solution acceptée et le plugin Select2.js; Je n'ai pas été en mesure de supprimer des caractères dans la zone modifiable, car l'action de suppression était empêchée. C'était ma solution:

//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 crée une étendue avec un attribut "contentEditable" qui est défini sur true pour la liste déroulante modifiable qu'elle contient. J'ai ajouté du code pour prendre en compte les portées tagName et l'attribut différent. Cela a résolu tous mes problèmes.

Edit: Si vous n’utilisez pas le plug-in SelectBox combobox pour jQuery, cette solution peut ne pas être utile pour vous et la solution acceptée peut-être meilleure.

2
Pytry

Avec Dojo Toolkit 1.7, cela fonctionne dans 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
Chris V

Réponse erikkallen modifiée:

$(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
Jacek Pietal
    document.onkeydown = function (e) {    
        e.stopPropagation();
        if ((e.keyCode==8  ||  e.keyCode==13) &&
            (e.target.tagName != "TEXTAREA") && 
            (e.target.tagName != "INPUT")) { 
            return false;
        }
    };
1
elico3000

Une solution beaucoup plus soignée -

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

Alternativement, vous pouvez seulement vérifier si

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

Ce code résout le problème dans tous les navigateurs:

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

Voici ma réécriture de la réponse la plus votée. J'ai essayé de vérifier element.value! == undefined (certains éléments, par exemple, n'ont peut-être pas d'attribut html mais peuvent avoir une propriété de valeur javascript quelque part sur la chaîne du prototype), mais cela n'a pas très bien fonctionné et comportait de nombreux cas Edge. Cela ne semble pas être un bon moyen de le prouver, une liste blanche semble donc la meilleure option.

Cela enregistre l’élément à la fin de la phase de bulle d’événement. Ainsi, si vous souhaitez gérer Backspace de manière personnalisée, vous pouvez le faire avec d’autres gestionnaires.

Ceci vérifie également l’instance de HTMLTextAreElement puisqu’il est théoriquement possible d’avoir un composant Web qui en hérite.

Cela ne vérifie pas contentEditable (à combiner avec d'autres réponses).

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

Cette solution a très bien fonctionné lors des tests.

J'ai ajouté du code pour gérer des champs d'entrée non étiquetés avec l'entrée et pour l'intégrer dans une application Oracle PL/SQL qui génère un formulaire d'entrée pour mon travail.

Mes deux centimes":

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

Avez-vous essayé la solution très simple d'ajouter simplement l'attribut suivant à votre champ de texte en lecture seule:

onkeydown = "return false;"

Cela empêchera le navigateur de revenir dans l'historique lorsque la touche Retour arrière est enfoncée dans un champ de texte en lecture seule. Peut-être que je manque votre véritable intention, mais cela semble être la solution la plus simple à votre problème.

1
B-Dog

Version javascript pure, qui fonctionne dans tous les navigateurs:

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

Bien sûr, vous pouvez utiliser "INPUT, TEXTAREA" et utiliser "if (! Regex.test (elements))" puis. Le premier a bien fonctionné pour moi.

1

J'ai créé un projet NPM avec une version propre de ce qui est actuellement accepté (de erikkallen)

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

Il utilise fondamentalement les mêmes principes mais:

  • Pas de dépendance
  • Prise en charge de contenteditable
  • Base de code plus lisible/maintenable
  • Sera pris en charge car il sera utilisé dans la production par mon entreprise
  • Licence 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
Sebastien Lorber

Le moyen le plus simple d'empêcher la navigation en appuyant sur la touche Retour arrière

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

Performance?

J'étais inquiet à propos de la performance et j'ai fait un violon: http://jsfiddle.net/felvhage/k2rT6/9/embedded/result/

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

J'ai analysé les méthodes les plus prometteuses que j'ai trouvées dans ce fil. En fait, ils étaient tous très rapides et ne posaient probablement pas de problème de "lenteur" lors de la frappe. La méthode la plus lente que j’ai examinée était d’environ 125 ms pour 10 000 appels dans IE8. Ce qui correspond à 0,0125ms par course.

J'ai trouvé que les méthodes publiées par Codenepal et Robin Maben étaient les plus rapides: environ 0,001 ms (IE8), mais méfiez-vous des différentes sémantiques.

C’est peut-être un soulagement pour une personne qui introduit ce type de fonctionnalité dans son code.

1
felvhage

Pour ceux qui sont intéressés, j'ai créé un plugin jQuery qui incorpore les commentaires de thetoolman (plus @ MaffooClock/@ cdmckay) et de @ Vladimir Kornea .

Usage:

//# Disable backspace on .disabled/.readOnly fields for the whole document
$(document).disableBackspaceNavigation();

//# Disable backspace on .disabled/.readOnly fields under FORMs
$('FORM').disableBackspaceNavigation();

//# Disable backspace on .disabled/.readOnly fields under #myForm
$('#myForm').disableBackspaceNavigation();

//# Disable backspace on .disabled/.readOnly fields for the whole document with confirmation
$(document).disableBackspaceNavigation(true);

//# Disable backspace on .disabled/.readOnly fields for the whole document with all options
$(document).disableBackspaceNavigation({
    confirm: true,
    confirmString: "Are you sure you want to navigate away from this page?",
    excludeSelector: "input, select, textarea, [contenteditable='true']",
    includeSelector: ":checkbox, :radio, :submit"
});

Brancher:

//# Disables backspace initiated navigation, optionally with a confirm dialog
//#     From: https://stackoverflow.com/questions/1495219/how-can-i-prevent-the-backspace-key-from-navigating-back
$.fn.disableBackspaceNavigation = function (vOptions) {
    var bBackspaceWasPressed = false,
        o = $.extend({
            confirm: (vOptions === true),   //# If the caller passed in `true` rather than an Object, default .confirm accordingly,
            confirmString: "Are you sure you want to leave this page?",
            excludeSelector: "input, select, textarea, [contenteditable='true']",
            includeSelector: ":checkbox, :radio, :submit"
        }, vOptions)
    ;

    //# If we are supposed to use the bConfirmDialog, hook the beforeunload event
    if (o.confirm) {
        $(window).on('beforeunload', function () {
            if (bBackspaceWasPressed) {
                bBackspaceWasPressed = false;
                return o.confirmString;
            }
        });
    }

    //# Traverse the passed elements, then return them to the caller (enables chainability)
    return this.each(function () {
        //# Disable backspace on disabled/readonly fields
        $(this).bind("keydown keypress", function (e) {
            var $target = $(e.target /*|| e.srcElement*/);

            //# If the backspace was pressed
            if (e.which === 8 /*|| e.keyCode === 8*/) {
                bBackspaceWasPressed = true;

                //# If we are not using the bConfirmDialog and this is not a typeable input (or a non-typeable input, or is .disabled or is .readOnly), .preventDefault
                if (!o.confirm && (
                    !$target.is(o.excludeSelector) ||
                    $target.is(o.includeSelector) ||
                    e.target.disabled ||
                    e.target.readOnly
                )) {
                    e.preventDefault();
                }
            }
        });
    });
}; //# $.fn.disableBackspaceNavigation
0
Campbeln

Je l'utilise dans mon code depuis un certain temps maintenant. J'écris des tests en ligne pour les étudiants et je rencontrais le problème lorsque les étudiants appuyaient sur la touche arrière pendant leur test et cela les ramènerait à l'écran de connexion. Frustrant! Cela fonctionne sur FF à coup sûr.

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

ne autre méthode utilisant 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>
0
CodeNepal

A travaillé pour moi

<script type="text/javascript">


 if (typeof window.event != 'undefined')
    document.onkeydown = function()
    {
        if (event.srcElement.tagName.toUpperCase() != 'INPUT')
            return (event.keyCode != 8);
    }
else
    document.onkeypress = function(e)
    {
        if (e.target.nodeName.toUpperCase() != 'INPUT')
            return (e.keyCode != 8);
    }

</script>
0
Pieter de Vries

Toutes les réponses données jusqu'à présent se concentrent sur la création d'un script pour le correctif dans la page Web, mais que se passe-t-il si je veux simplement la fonctionnalité pour moi-même, sans affecter les autres utilisateurs?

Dans ce cas, une solution pour le navigateur lui-même est à privilégier:
- Firefox sous Linux a "démappé" le comportement de retour arrière depuis 2006, de sorte qu'il n'est pas affecté. (en tout cas, il a simplement été configuré pour faire défiler avant)
- Chrome vient d'annoncer qu'il fera de même à partir de maintenant; ( http://forums.theregister.co.uk/forum/1/2016/05/20/chrome_deletes_backspace/ )
- Firefox sous Windows peut être configuré pour ignorer le retour arrière en allant dans about: config et en modifiant le paramètre backspace_action en 2; ( http://kb.mozillazine.org/Browser.backspace_action )
- Safari?!

0
Paolo

Sitepoint: Désactiver pour Javascript

event.stopPropagation() et event.preventDefault() ne font rien dans IE. Je devais envoyer un retour event.keyCode == 11 (je venais de choisir quelque chose) au lieu de simplement dire "if not = 8, run the event" pour que tout se passe bien. event.returnValue = false fonctionne également.

0
Tom