Как я могу помешать клавише возврата вернуться назад?

275

В IE я могу сделать это с помощью (ужасно нестандартного, но работающего) jQuery

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

Но возможно ли это сделать способом, который работает на Firefox, или кросс-браузерным способом для получения бонуса?

Для записи:

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

ничего не делает.

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

решает проблему, но делает клавишу Backspace непригодной для использования на странице, что еще хуже, чем исходное поведение.

РЕДАКТИРОВАТЬ: Причина, по которой я это делаю, заключается в том, что я не создаю простую веб-страницу, а большое приложение. Потерять 10 минут работы невероятно раздражает только потому, что ты нажал клавишу возврата в неправильном месте. Соотношение предотвращения ошибок и раздражающих пользователей должно быть намного выше 1000/1 за счет предотвращения возврата клавиши назад.

РЕДАКТИРОВАТЬ 2: Я не пытаюсь предотвратить историю навигации, просто несчастные случаи.

EDIT3: комментарий @brentonstrines (перенесен сюда, поскольку вопрос очень популярен): это долгосрочное «исправление», но вы можете оставить свою поддержку за ошибкой Chromium, чтобы изменить это поведение в webkit

erikkallen
источник
137
Потому что клавиша Backspace перегружена. Возможно, вы этого не заметили, но вы, вероятно, используете это все время для стирания букв, которые вы только что набрали в текстовом поле. У некоторых из моих клиентов возникли проблемы с тем, что страница вернулась назад, так что это полезная информация. Никто, кроме вас, клоунов, не знает, что backspace должен вернуться на страницу. Это то, чего я никогда не знал, и это совершенно враждебное поведение для браузера. Я думаю, что все страницы должны отключить это поведение.
Бретон
80
Почему люди думают, что это странно? Использование backspace для навигации - это действительно тупой путь! Есть так много текстовых полей, из которых пользователи могут захотеть удалить текст - представьте, что у вас длинный SO-ответ, переключитесь в другое окно, чтобы проверить что-то, а затем вы вернетесь и неправильно щелкнете область редактирования, нажмите клавишу Backspace, чтобы удалить слово вдруг браузер возвращается на страницу, и вы потенциально потеряете все, что только что написали.
Питер Боутон
57
Почему я хочу это сделать? Я не создаю веб-сайт, но веб-приложение. Некоторые поля ввода доступны только для чтения, в этом случае они выглядят редактируемыми, но если вы нажмете клавишу Backspace, вы покинете страницу. Соотношение количества нажатий на
клавишу Backspace, нацеленных
42
Вопрос в том, как это сделать, а не в вашем мнении о том, хорошая это идея или нет. Не зная деталей проекта, ваши мнения не имеют смысла. Мой клиент специально запросил такое поведение для одного из моих проектов и реальный ответ, а не «Почему вы когда-нибудь захотите это сделать?» было бы полезно.
Нет
7
Это долгосрочное «исправление», но вы можете оставить свою поддержку за ошибкой Chromium, чтобы изменить это поведение в webkit: code.google.com/p/chromium/issues/detail?id=144832
brentonstrine

Ответы:

335

Этот код решает проблему, по крайней мере, в IE и Firefox (не тестировал ни один другой, но я даю ему разумную возможность работать, если проблема существует даже в других браузерах).

// 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
источник
6
Разрывает поля пароля.
Хэмлок
7
Как сказал Хэмлок - проверьте d.type.toUpperCase() === 'PASSWORD'также. В остальном хорошо выглядит
stevendesu
17
Так как вы уже используете jQueryif( $(d).is( ":input" ) )...
Пол Александр
23
Это отстой, что это должен быть белый список, а не возможность занести в черный список функцию «назад». Вы можете добавить проверку d.isContentEditableздесь.
Ионо
3
Я создал проект NPM с чистой версией принятого в настоящее время ответа: github.com/slorber/backspace-disabler (он также поддерживает contenteditables и не имеет зависимости)
Себастьен Лорбер,
62

Этот код работает во всех браузерах и глотает клавишу возврата, когда его нет в элементе формы или если элемент формы отключен | readOnly. Он также эффективен, что важно, когда он выполняется для каждого введенного ключа.

$(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();
            }
        }
    });
});
thetoolman
источник
1
Пожалуйста, проверьте мой пример, вы можете обновить свой код соответственно.
Biff MaGriff
10
Я предпочитаю это решению @ erikkallen, потому что оно чище. Однако я хотел, чтобы кнопки отправки, переключатели и флажки также игнорировались, поэтому я изменил if () на это:if(!rx.test(e.target.tagName) || $(e.target).is(':checkbox') || $(e.target).is(':radio') || $(e.target).is(':submit') || e.target.disabled || e.target.readOnly )
Мэтью Кларк,
@thetoolman, см. мой комментарий к ответу Эрикален. Это также следует учитывать contentEditable.
Толчок
10
@MaffooClock: вы можете быть более кратким.is(':checkbox,:radio,:submit')
cdmckay
1
@ cdmckay: я не могу поверить, что я не написал это так во-первых. Спасибо за то, что вычистили это для всех нас :)
Мэтью Кларк
41

Другие ответы здесь доказали, что это невозможно сделать без элементов белого списка, в которых разрешен Backspace. Это решение не является идеальным, потому что белый список не так прост, как просто текстовые поля и ввод текста / пароля, но он часто оказывается неполным и нуждается в обновлении.

Однако, поскольку целью подавления функциональности backspace является просто предотвращение случайной потери данных пользователями, решение beforeunload является хорошим решением, поскольку модальное всплывающее окно вызывает удивление - модальные всплывающие окна плохие, когда они запускаются как часть стандартного рабочего процесса, потому что пользователь привыкает отклонять их, не читая их, и они раздражают. В этом случае модальное всплывающее окно появляется только в качестве альтернативы редкому и неожиданному действию и поэтому является приемлемым.

Проблема заключается в том, что модал onbeforeunload не должен появляться, когда пользователь уходит со страницы (например, при нажатии на ссылку или при отправке формы), и мы не хотим создавать белый или черный список определенных условий onbeforeunload.

Идеальная комбинация компромиссов для обобщенного решения заключается в следующем: следите за тем, нажата ли клавиша Backspace, и вынимайте только режим onbeforeunload, если он есть. Другими словами:

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

Это было проверено на работу в IE7 +, FireFox, Chrome, Safari и Opera. Просто поместите эту функцию в ваш global.js и вызывайте ее с любой страницы, где вы не хотите, чтобы пользователи случайно потеряли свои данные.

Обратите внимание, что модальное состояние onbeforeunload может быть запущено только один раз, поэтому, если пользователь снова нажимает клавишу Backspace, модальное соединение не будет запускаться снова.

Обратите внимание, что это не сработает при событиях hashchange, однако в этом контексте вы можете использовать другие методы, чтобы предотвратить случайную потерю данных пользователями.

Владимир Корнеа
источник
2
Я просто пошел, чтобы добавить это же решение и увидел этот пост в нижней части страницы LOL. Одно из отличий, которое у меня есть, состоит в том, чтобы установить lastUserInputWasBackspace = false перед оператором возврата «Вы уверены ...», поэтому вы не получите всплывающее окно, если случайно нажмете кнопку «Назад» после того, как уже увидели всплывающее окно (так что это не соответствует поведение, вызванное backspace).
Дэвид Рассел
1
@ user2407309 Я удалил свой комментарий (не жалобу) о том, что Firefox не работает с вашим решением. Была проблема с моим отладчиком. Мои извинения за редактирование / нарушение вашего кода. Теперь я понимаю, что я перешагнул мои границы (редактирование), прости меня. Мне очень жаль, и я не имел в виду никаких претензий к вашему замечательному решению этой проблемы. Опять мои извинения. Этот код работает хорошо. Я считаю, что это лучший ответ, и я благодарю вас за это.
Чарльз Бирн
1
Это решение работало на моей локальной машине, но когда я переместил его, клиент (по крайней мере, некоторые из них) потерял функциональность половины приложения. Я думаю, что-то это отвергает, но я понятия не имею, что.
Стив
1
@ Стив, редко или нет, если есть проблема с функцией, эта информация принадлежит здесь. Я просто хочу знать, действительно ли существует проблема.
Владимир Корнеа
1
Хорошее решение, но, к сожалению, если пользователь случайно нажимает клавишу Backspace дважды, он все равно перемещается назад. (по крайней мере на Firefox)
Ремко де Зварт
26

Более элегантное / краткое решение:

$(document).on('keydown',function(e){
  var $target = $(e.target||e.srcElement);
  if(e.keyCode == 8 && !$target.is('input,[contenteditable="true"],textarea'))
  {
    e.preventDefault();
  }
})
Darwayne
источник
1
Это намного более кратко, и из того, что я могу сказать, работает так же хорошо. Почему самый популярный ответ содержит все эти проверки типов входов и кажется более сложным? Это надежнее?
Ближайшая точка
1
Самый популярный ответ был первым, кто ответил на вопрос, таким образом, высокие голоса.
Дарвейн
4
когда поля доступны только для чтения, удаление по-прежнему выполняется в Chrome
Will D
16

Модификация ответа erikkallen для адресации различных типов ввода

Я обнаружил, что предприимчивый пользователь может нажимать клавишу Backspace на флажок или переключатель в тщетной попытке очистить его, и вместо этого они будут перемещаться назад и потерять все свои данные.

Это изменение должно решить эту проблему.

Новое редактирование для редактирования содержимого div

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

Пример
Для тестирования сделайте 2 файла.

starthere.htm - сначала откройте его, чтобы у вас было место, куда можно вернуться

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

test.htm - Это будет навигация в обратном направлении, когда нажата клавиша Backspace, в то время как флажок или отправить имеет фокус (достигается путем вкладки). Замените моим кодом, чтобы исправить.

<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
источник
В каком браузере вы видели нажатие на клавишу возврата на радио | checkbox | submit -> back function? Я не видел, чтобы браузер делал это ..
thetoolman
Internet Explorer 8 и Chrome
Biff MaGriff
2
Я попробовал ряд других решений в этой теме, но эта работала хорошо во всех моих ситуациях и имела самый простой и понятный код. Спасибо.
Эзвард
Вы пробовали @Darwayne? Мне любопытно узнать, почему он такой короткий, а он более сложный, но оба, кажется, работают одинаково для меня
Nearpoint
Это работает на ссылках? У меня есть приложение ASP.Net с кнопкой изображения, чтобы удалить элемент. Это единственное, с чем это не сработало до сих пор ...
Стив
8

Судя по комментариям, вы хотите, чтобы люди не теряли информацию в формах, если они нажимают клавишу возврата, чтобы удалить, но поле не сфокусировано.

В этом случае вы хотите посмотреть на обработчик события onunload . Stack Overflow использует его - если вы попытаетесь покинуть страницу, когда начали писать ответ, появится всплывающее предупреждение.

DisgruntledGoat
источник
4
извините, это был грубый комментарий. Я имею в виду, что пользователь, вероятно, не хочет, чтобы его ругали за то, что он сделал что-то, чего он даже не знал, что это неправильно. Почему бы просто не съесть ключ с ключом от дома? Цель состоит не в том, чтобы полностью запретить пользователю покидать страницу, а в том, чтобы предотвратить эту распространенную ошибку. Кроме того, всплывающие диалоги не очень эффективны или полезны. Пользователи их не читают. Вы уверены, что хотите покинуть страницу? Ладно! Не ждите, подождите, я не хотел покидать страницу .. ой слишком поздно.
Бретон
3
Хорошо, тогда возьми или оставь. Я думаю, что вы пытаетесь чрезмерно спроектировать проблему, которая на самом деле не существует или, по крайней мере, не важна. По моему опыту, только опытные пользователи нажимают «ОК» в незнакомых диалогах, не читая их должным образом. ;)
Рассерженная шлюха
3
Вы и Бретон один и тот же человек? Как бы то ни было, вы в какой-то мере застрелились - в статье написано, что «ответ по умолчанию -« Отмена », поэтому, увидев диалог об уходе со страницы, они нажмут« Отмена »и, следовательно, не покинут страницу. Хотя следует отметить, что параметры Chrome в этом диалоговом окне: «Покинуть эту страницу» и «Оставаться на этой странице», которые очень понятны.
Рассерженная шлюха
1
Нет, он не я, но я сталкивался с этой ссылкой раньше. Я думаю, что комментарии веселые. «Что !? люди игнорируют модальные диалоговые окна? Мы должны найти способ сделать их еще более настойчивыми и раздражающими!». Действительно многое объясняет о программном обеспечении Microsoft.
Бретон
3
@ Disgruntled: Нет, я не бретонец, и смысл статьи не в том, что «выбор по умолчанию ...», а в том, что «пользователи ничего не читают».
erikkallen
7

Стоп от навигации этот код работает!

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

Но не для ограничения текстовых полей, а других

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

Чтобы предотвратить это для конкретной области просто используйте

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

Обращаясь к этому ниже!

Запретить BACKSPACE вернуться назад с помощью jQuery (как на главной странице Google)

Сайед Этшам Аббас
источник
7

Большинство ответов в JQuery. Вы можете сделать это идеально в чистом Javascript, простом и не требующем библиотеки. Эта статья была хорошей отправной точкой для меня, но поскольку keyIdentifier устарел, я хотел, чтобы этот код был более безопасным, поэтому я добавил || e.keyCode == 8 в оператор if. Кроме того, код не очень хорошо работал в Firefox, поэтому я добавил return false; и теперь это работает на отлично Вот:

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

Этот код прекрасно работает, потому что,

  1. Это в чистом JavaScript (библиотека не требуется).
  2. Он не только проверяет нажатие клавиши, но и подтверждает, действительно ли действие браузера «назад».
  3. Вместе с вышеизложенным пользователь может без каких-либо проблем вводить и удалять текст из текстовых полей ввода на веб-странице, в то же время предотвращая действие кнопки «Назад».
  4. Это коротко, чисто, быстро и прямо к делу.

Вы можете добавить console.log (e); для ваших целей тестирования и нажмите F12 в Chrome, перейдите на вкладку «консоль» и нажмите «Backspace» на странице и загляните внутрь нее, чтобы увидеть, какие значения возвращаются, затем вы можете настроить все эти параметры для дальнейшего улучшения кода выше, чтобы удовлетворить ваши потребности.

Тарик
источник
6

Объединение решений от "thetoolman" && "Biff MaGriff"

следующий код, кажется, работает правильно в 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();
    });
}); 
CodeNepal
источник
Добавление ИЗОБРАЖЕНИЯ также может быть полезным.
mrswadge
я остановился на этом.
Корентин
5

Не уверен, почему никто просто не ответил на это - кажется вполне разумным техническим вопросом, чтобы спросить, возможно ли это.

Нет, я не думаю, что есть кросс-браузерный способ отключения кнопки возврата. Я знаю, что в эти дни он не включен по умолчанию в FF.

brabster
источник
3
Минус 1 за то, что не отвечал на фактический вопрос и не тратил время
Эндрю
4

Мне было трудно найти ответ не из JQUERY. Спасибо Стасу за то, что поставил меня на трассу.

Chrome: если вам не нужна поддержка нескольких браузеров, вы можете просто использовать черный список, а не белый список. Эта чистая версия JS работает в Chrome, но не в IE. Не уверен насчет FF.

В Chrome (версия 36, середина 2014 г.), кажется, нацелены клавиши, не входящие или не подлежащие удовлетворению <BODY>. Это позволяет использовать черный список, который я предпочитаю белый список. IE использует цель последнего клика - так что это может быть div или что-то еще. Это делает это бесполезным в 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();
        }
    }
}  

Кросс-браузер: для чистого javascript я нашел ответ Стаса лучшим. Добавление еще одной проверки условия для contenteditable заставило меня работать *:

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

* Обратите внимание, что в IE [edit: и Spartan / TechPreview] есть «функция», которая делает элементы, связанные с таблицей, недоступными для редактирования. . Если вы нажмете одну из них, а затем нажмите клавишу Backspace, она вернется назад. Если у вас нет редактируемых <td>s, это не проблема.

Иосия
источник
3

Это решение аналогично другим, которые были опубликованы, но оно использует простой белый список, что делает его легко настраиваемым, чтобы разрешить возврат в заданных элементах, просто установив селектор в функции .is ().

Я использую это в этой форме, чтобы предотвратить возврат назад на страницы:

$(document).on("keydown", function (e) {
    if (e.which === 8 && !$(e.target).is("input:not([readonly]), textarea")) {
        e.preventDefault();
    }
});
Никто
источник
2
Когда пользователь использует contenteditable, это отключит его. Так что вы можете добавить contenteditable = true в белый список
Мигель
3

Чтобы немного пояснить отличный ответ @ erikkallen , вот функция, которая позволяет вводить все типы ввода с клавиатуры, в том числе введенные в 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();
    }
});
Gingi
источник
Спасибо, я использую этот ответ! Нашли ли вы какие-либо проблемы с этим решением?
Ближайшая точка
1
Я бы порекомендовал убрать объявления INPUTTYPES, TEXTRE из функции, чтобы они не пересчитывались при каждом событии нажатия клавиши.
Театр
3

JavaScript - способ jQuery:

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

Javascript - родной способ, который работает для меня:

<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 Это было хорошо для моего случая использования, давным-давно. Пожалуйста, не стесняйтесь вносить свой вклад, улучшая / изменяя мой ответ. Спасибо!
Владимир
2

У меня были некоторые проблемы с принятым решением и плагином Select2.js; Мне не удалось удалить символы в редактируемом поле, поскольку действие по удалению было предотвращено. Это было мое решение:

//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 создает Span с атрибутом «contentEditable», который имеет значение true для редактируемого поля со списком в нем. Я добавил код в учетную запись для тегов spanName и другого атрибута. Это решило все мои проблемы.

Редактировать: Если вы не используете плагин комбобокса Select2 для jquery, то это решение может вам не понадобиться, и принятое решение может быть лучше.

Pytry
источник
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
источник
2
Вы не должны использовать return false. Рекомендуется e.preventDefault. Также вы останавливаете распространение события для каждого ключа, а не только для возврата. Наконец, keyCode 13 - это ввод, и вопрос был в том, чтобы предотвратить обратную навигацию с помощью возврата, но это не позволило бы вводу формы отправить или выполнить другие действия.
Нет
1

Этот код решает проблему во всех браузерах:

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
Я считаю, что этот код не работает должным образом из-за d.tagname DIVили TD.
Бифф Магрифф
Код от Haseeb Akhtar отлично работает в Chrome и Firefox, но удивительно! нет в IE6-9 Есть предложения?
Мартин Андерсен
1

Самый простой способ предотвратить навигацию при нажатии на клавишу возврата

$(document).keydown(function () {
    if (event.keyCode == 8) {
        if (event.target.nodeName == 'BODY') {
            event.preventDefault();
        }
    }
});
Мохаммед Ирфан Майя
источник
Предотвращает навигацию при нажатии backspcae, и в то же время позволяет backspace с во всех элементах управления вводом
Мохаммед Ирфан Майя
И не пропустите первую строку .. $ (document) .keydown (function () {
Мохаммед Ирфан, майя,
3
это отключит кнопку внутри текстовых полей и входов
nodrog
1

Используя Dojo toolkit 1.7, это работает в 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()});
});
Крис V
источник
1

Вы пробовали очень простое решение, просто добавив следующий атрибут в текстовое поле только для чтения:

onkeydown = "вернуть ложь";

Это не позволит браузеру вернуться в историю, когда клавиша Backspace нажата в текстовом поле только для чтения. Может быть, я упускаю ваше истинное намерение, но, похоже, это было бы самым простым решением вашей проблемы.

B-Dog
источник
1

Гораздо более аккуратное решение -

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

Кроме того, вы можете только проверить, если

$(document.activeElement).is('body')
Робин Мабен
источник
1

Чистая версия JavaScript, которая работает во всех браузерах:

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

Конечно, вы можете использовать «INPUT, TEXTAREA» и использовать «if (! Regex.test (elements))» затем. Первый работал нормально для меня.

Станислав Пархоменко
источник
1

Производительность?

Я беспокоился о производительности и сделал скрипку: http://jsfiddle.net/felvhage/k2rT6/9/embedded/result/

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

Я проанализировал наиболее перспективные методы, которые я нашел в этой теме. Оказывается, все они были очень быстрыми и, скорее всего, не вызывали проблем с точки зрения «медлительности» при наборе текста. Самый медленный метод, который я рассмотрел, был около 125 мс для 10.000 вызовов в IE8. Что составляет 0,0125 мс на удар.

Я обнаружил, что методы, опубликованные Коденепалом и Робином Мабеном, являются самыми быстрыми ~ 0,001 мс (IE8), но остерегайтесь различной семантики.

Возможно, это облегчение для тех, кто внедряет такую ​​функциональность в свой код.

felvhage
источник
1

Модифицированный ответ erikkallen:

$(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
Идеальный ответ. Решение, которое я получил от других, не сработало в Firefox, но это прекрасно сработало во всех трех (Firefox, IE и crome) без проблем. Спасибо, Прози.
Нихил Динеш,
1

Это решение работало очень хорошо при тестировании.

Я добавил некоторый код для обработки некоторых полей ввода, не помеченных для ввода, и для интеграции в приложение Oracle PL / SQL, которое генерирует форму ввода для моей работы.

Мои два цента":

 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

Я создал проект NPM с чистой версией принятого в настоящее время (erikkallen)

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

Он использует в основном те же принципы, но:

  • Нет зависимости
  • Поддержка contenteditable
  • Более читаемая / поддерживаемая кодовая база
  • Будет поддерживаться, так как будет использоваться моей компанией в производстве
  • Лицензия 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

Вот мой переписанный ответ. Я попытался проверить element.value! == undefined (поскольку некоторые элементы наподобие могут не иметь атрибута html, но могут иметь свойство значения javascript где-то в цепочке прототипов), однако это не сработало очень хорошо и имело множество крайних случаев. Кажется, нет хорошего способа убедиться в этом на будущее, поэтому белый список кажется лучшим вариантом.

Это регистрирует элемент в конце фазы всплывающего события, поэтому, если вы хотите обрабатывать Backspace любым другим способом, вы можете сделать это в других обработчиках.

Это также проверяет экземпляр HTMLTextAreElement, поскольку теоретически можно иметь веб-компонент, который наследуется от этого.

Это не проверяет contentEditable (в сочетании с другими ответами).

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
источник
0

Точка сайта: отключить обратно для Javascript

event.stopPropagation()и event.preventDefault()ничего не делать в IE. Я должен был отправить возврат event.keyCode == 11(я только что взял что-то) вместо того, чтобы просто сказать, "if not = 8, run the event"чтобы заставить это работать, все же. event.returnValue = falseтоже работает.

Том
источник
0

Еще один метод с использованием 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
источник
Обратите внимание, что это не работает, если элементы управления (текстовое поле) были добавлены динамически.
CodeNepal
0

Я использую это в своем коде в течение некоторого времени. Я пишу онлайн-тесты для студентов и столкнулся с проблемой, когда студенты нажимали клавишу Backspace во время теста, и это возвращало их обратно к экрану входа в систему. Срыв! Это работает на FF точно.

document.onkeypress = Backspace;
function Backspace(event) {
    if (event.keyCode == 8) {
        if (document.activeElement.tagName == "INPUT") {
            return true;
        } else {
            return false;
        }
    }
}
загар
источник