Як я можу запобігти навігації клавіші назад?


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

вирішує проблему, але робить клавішу зворотної області непридатною для сторінки, що навіть гірше, ніж оригінальна поведінка.

EDIT: Причиною цього я є те, що я створюю не просту веб-сторінку, а великий додаток. Неймовірно прикро втратити 10 хвилин роботи тільки тому, що ти натиснув на задній простір в неправильному місці. Співвідношення запобігання помилкам та дратівливим користувачам повинно бути набагато вище 1000/1, запобігаючи навігації назад клавіші назад.

EDIT2: Я не намагаюся запобігати навігації по історії, просто аварії.

EDIT3: коментар @brentonstrines (переміщений сюди, оскільки питання настільки популярне): Це довгострокове "виправлення", але ви можете кинути свою підтримку за помилку Chromium, щоб змінити цю поведінку в веб-програмі


137
Тому що клавіша зворотної області перевантажена. Ви, можливо, цього не помічали, але ви, ймовірно, використовуєте його весь час для стирання букв, які ви тільки що ввели у текстовому полі. Деякі мої клієнти мали проблеми з тим, що викликає повернення сторінки назад, тому це корисна інформація. Ніхто, крім вас клоунів, не знає, що backspace повинен повернутися на сторінку. Це я ніколи не знав, і це відверта ворожа поведінка для браузера. Я думаю, що всі сторінки повинні відключити таку поведінку.
Бретон

80
Чому люди вважають це дивним? Використання зворотної області для навігації - це дійсно німий ярлик! Є так багато текстових полів, з яких користувачі можуть захотіти видалити текст - уявіть, що ви маєте довгу відповідь ТА, переходите в інше вікно, щоб щось перевірити, а потім повертаєтесь і неправильно клацніть область редагування, натискаєте зворотну простір, щоб видалити слово та раптом браузер повертається на сторінку, і ви потенційно втратили все, що ви написали.
Пітер Бауфтон,

57
Чому я хочу це зробити? Я створюю не веб-сайт, а веб-додаток. Деякі поля введення є лише для читання, і в цьому випадку вони виглядають редагованими, але якщо натиснути зворотну простір, ви залишаєте сторінку. Співвідношення натискань у зворотному
просторі, що

42
Питання в тому, як це зробити, а не ваша думка щодо того, чи це гарна ідея чи ні. Не знаючи деталей проекту, ваша думка є безглуздою. Мій клієнт спеціально попросив подібну поведінку для одного з моїх проектів і справжню відповідь, а не "Чому б вам це хотілося робити?" було б корисно.
Немає

7
Це довгострокове "виправлення", але ви можете кинути свою підтримку за помилкою Chromium, щоб змінити таку поведінку в webkit: code.google.com/p/chromium/isissue/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;
        }
    }
});

6
Порушує поля паролів.
Хемлок

7
Як заявив Хемлок - перевіряйте d.type.toUpperCase() === 'PASSWORD'також. Інакше виглядає добре
stevendesu

17
Оскільки ви вже використовуєте jQueryif( $(d).is( ":input" ) )...
Пол Олександр

23
Це гадає, що це повинно бути білим списком, а не тим, що в змозі скласти чорний список функцій "назад". Ви можете додати чек d.isContentEditableтут.
іоно

3
Я створив проект NPM з чистою версією прийнятої на даний момент відповіді: github.com/slorber/backspace-disabler (він також підтримує вміст змінних і не має залежності)
Sebastien Lorber

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

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, дивіться мій коментар до відповіді erikallen. На це також слід враховувати contentEditable.
поштовх

10
@MaffooClock: ви можете бути більш короткими.is(':checkbox,:radio,:submit')
cdmckay

1
@cdmckay: Я не можу повірити, що я не написав це так в першу чергу. Дякуємо за те, що ви очистили нас усіх :)
Меттью Кларк

41

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

Однак, оскільки метою придушення функціональності зворотного простору є лише запобігти випадковому втраті даних користувачами, рішення перед завантаженням є гарним, оскільки модальне спливаюче вікно дивно - модальні спливаючі вікна погані, коли вони спрацьовують як частина стандартного робочого процесу, тому що користувач звикає звільняти їх, не читаючи, і вони дратують. У цьому випадку модальне спливаюче вікно з’явиться лише як альтернатива рідкісній та дивовижній дії, і тому є прийнятною.

Проблема полягає в тому, що модальний режим перед завантаженням не повинен з’являтися, коли користувач переходить зі сторінки (наприклад, при натисканні на посилання або надсиланні форми), і ми не хочемо починати білі списки чи чорний список конкретних умов перед завантаженням.

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

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 і зателефонуйте їй з будь-якої сторінки, де ви не хочете, щоб користувачі випадково втратили свої дані.

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

Зауважте, що це не призведе до подій хеш-змін, однак у цьому контексті ви можете використовувати інші методи, щоб утримати користувачів від випадкових втрат даних.


2
Я просто пішов додати це саме рішення і побачив цю публікацію внизу сторінки LOL. Однією з моїх різниць є встановлення lastUserInputWasBackspace = false перед поверненням оператора "Ви впевнені ...", тож ви не отримаєте спливаюче вікно, якщо вам трапиться натиснути кнопку "назад" після того, як ви побачите спливаюче вікно (тому воно відповідає не- поведінка під впливом зворотного простору).
Девід Рассел

1
@ user2407309 Я видалив свій коментар (не скарга) про те, що firefox не працює з вашим рішенням. Виникла проблема з моїм налагоджувачем. Мої вибачення за редагування / порушення вашого коду. Зараз я усвідомлюю, що я переступив свої межі (редагування) пробач мене. Мені справді шкода, і я не мав на увазі скарг на ваше чудове рішення цієї проблеми. Знову мої вибачення. Цей код добре працює. Я вважаю, що це найкраща відповідь, і я вам за це вдячний.
Чарльз Берн

1
Це рішення працювало на моїй локальній машині, але коли я перемістив його, клієнт (принаймні деякі з них) втратив функціональність половини програми. Я здогадуюсь, що щось це відкидає, але я поняття не маю.
Стів

1
@Steve, рідкісне чи ні, якщо є проблема з функцією, ця інформація тут належить. Я просто хочу знати, чи є насправді проблема.
Володимир Корнеа

1
Приємне рішення, але, на жаль, якщо користувач випадково натискає назад, він все одно переміщається назад. (принаймні на 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();
  }
})

1
Це набагато більш стисло і з того, що я можу сказати, працює так само добре. Чому саме найпопулярніша відповідь на всі перевіряє типи входів і здається складнішою? Це надійніше?
Близький пункт

1
Найпопулярніша відповідь була першою, яка відповіла на питання, таким чином, високими голосами.
Дарвейн

4
коли поля для читання лише фокусуються, видалення все ще повертається в хром
Буде D

16

Модифікація відповіді erikkallen на адресу різних типів введення

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

Ця зміна повинна вирішити це питання.

Нова редакція для адреси вмісту, який можна редагувати вмістом

    //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 - Це буде переміщуватися назад, коли натискається зворотний простір, поки прапорець у полі або прапорці має фокус (досягається вкладкою). Замініть мій код, щоб виправити.

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

Який веб-переглядач бачив натиснутою на зворотному просторі функцію радіо | прапорець | подати -> назад? Я не бачив, щоб браузер це робив ..
thetoolman

Internet Explorer 8 і Chrome
Biff MaGriff

2
Я спробував низку інших рішень у цій темі, але це добре працювало у всіх моїх ситуаціях і мав найчистіший, найпростіший для розуміння код. Дякую.
Ezward

Ви спробували @Darwayne Мені цікаво дізнатись, чому це так коротко, і це складніше, але обидва, здається, працюють однаково для мене
Nearpoint

Чи працює це за посиланнями? У мене є програма ASP.Net з кнопкою зображення для видалення елемента. Це єдине, на чому це не працювало досі ...
Стів

8

Виходячи з коментарів, схоже, ви хочете зупинити людей, які втрачають інформацію у формах, якщо вони натискають зворотну простір для видалення, але поле не фокусується.

У цьому випадку, ви хочете подивитися на OnUnload обробник подій. Переповнення стека використовує його - якщо ви спробуєте залишити сторінку, коли ви почали писати відповідь, у ній з’являється попередження.


4
вибачте, що це був грубий коментар. Що я маю на увазі, це те, що користувач, ймовірно, не хоче, щоб його зазнавали за те, що він робив те, що навіть не знав, що не так. Чому б просто мовчки не з'їсти ключ із натисканням клавіші? Мета - не повністю перешкодити користувачеві залишати сторінку, а захистити від цієї поширеної помилки. Крім того, спливаючі діалоги не дуже ефективні чи корисні. Користувачі не читають їх. Ви впевнені, що хочете залишити сторінку? Добре! Не чекайте, чекайте, я не хотів залишати сторінку .. ой, занадто пізно.
Бретон

3
Добре, тоді візьміть або залиште. Я думаю, ти намагаєшся надмірно розробити проблему, яка насправді не існує, або, принаймні, не важлива. На мій досвід, лише незначні користувачі натискають "ОК" у незнайомих діалогах, не читаючи їх належним чином. ;)
НезадоволенняGoat

3
Ви та Бретон одна людина? У будь-якому випадку ви ніколи не застрелилися там у ногу - у статті йдеться про "відповідь за замовчуванням - Скасувати", тож побачивши діалогове вікно про вихід зі сторінки, вони натискають "Скасувати" і тому не залишають сторінки. Хоча слід зазначити, що параметри Chrome у цьому діалоговому вікні - це "Залишити цю сторінку" та "Залишитись на цій сторінці", які є дуже зрозумілими.
НезадоволенняGoat

1
Ні, він - це не я, але я вже наткнувся на це посилання. Я думаю, що коментарі веселі. "Що !? люди ігнорують модальні діалогові вікна? Ми повинні знайти спосіб зробити їх БІЛЬШЕ стійкими та дратівливими!". Дійсно багато пояснює програмне забезпечення мікрософт.
Бретон

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 в хромі, перейдіть на вкладку "консоль" і натисніть "назад" на сторінці та загляньте всередину, щоб побачити, які значення повертаються, тоді ви можете націлити всі ці параметри для подальшого покращення коду. вище, щоб відповідати вашим потребам.


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

Додавання IMAGE також може бути корисним.
mrswadge

я зупинився на цьому.
Корентін

5

Не впевнений, чому ніхто просто не відповів на це - здається, цілком розумним технічним питанням, щоб задати, чи це можливо.

Ні, я не думаю, що існує спосіб переключення кнопки повернення в браузері. Я знаю, що це не включено за замовчуванням у FF сьогодні.


3
Мінус 1 за те, що не відповів на фактичне запитання та витрачав час
Андрій

3

Це рішення схоже на інші, які були опубліковані, але воно використовує простий білий список, що робить його легко настроюваним, щоб дозволити назад область у визначених елементах, просто встановивши селектор у функції .is ().

Я використовую його в цій формі, щоб запобігти поверненню назад на сторінках:

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

2
Якщо користувач використовує вміст, це може зробити його відключеним. Тому ви можете додати 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();
    }
});

Дякую, я використовую цю відповідь! Чи знайшли ви якісь проблеми з цим рішенням?
Nearpoint

1
Я рекомендую перенести декларації INPUTTYPES, TEXTRE з функції, щоб вони не перераховувалися під час кожної події клавіатури.
thetoolman

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 Це було добре для мого випадку використання, давно. Будь ласка, не соромтесь робити внесок, покращуючи / змінюючи мою відповідь. Дякую!
Володимир Джуричич

3

Мені важко було знайти невідповідну відповідь. Дякую Стасу, що вивів мене на трасу.

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 я знайшов відповідь Стаса найкращою. Додавання ще однієї перевірки умови на предмет вмісту змусило мене працювати *:

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] мають "функцію", яка робить елементи, пов'язані з таблицею, непридатними . Якщо ви натиснете один із них, а потім натисніть зворотну простір, він буде переміщатися назад. Якщо у вас немає прав для редагування <td>, це не проблема.


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" для редагованого комбінованого поля в ньому. Я додав код до облікового запису spans tagName та іншого атрибута. Це вирішило всі мої проблеми.

Редагувати: Якщо для jquery ви не використовуєте плагін Select2 combobox, то це рішення вам може не знадобиться, і прийняте рішення може бути кращим.


1
    document.onkeydown = function (e) {    
        e.stopPropagation();
        if ((e.keyCode==8  ||  e.keyCode==13) &&
            (e.target.tagName != "TEXTAREA") && 
            (e.target.tagName != "INPUT")) { 
            return false;
        }
    };

2
Ви не повинні використовувати false 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.
Biff MaGriff

Код від Haseeb Akhtar ідеально працює в Chrome та Firefox, але сюрприз !! не в IE6-9 Будь-які пропозиції?
Мартін Андерсен

1

Найпростіший спосіб запобігти навігації при натисканні на задню область

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

Перешкоджає навігації при натисканні backspcae, і в той же час дозволяє повернути назад у всіх контрольних елементах введення
Mohammed Irfan Mayan

І не пропустіть перший рядок .. $ (document) .keydown (function () {
Mohammed Irfan Mayan

3
це вимкне функцію зворотної кнопки у текстових областях та введеннях
nodrog

1

Використовуючи інструментарій Dojo 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()});
});

1

Ви спробували дуже просте рішення просто додати наступний атрибут до текстового поля лише для читання:

onkeydown = "повернути помилково;"

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


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 (елементи))". Перший добре працював для мене.


1

Продуктивність?

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

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

Я проаналізував найбільш перспективні методи, які я знайшов у цій темі. Виявляється, всі вони були дуже швидкими і, швидше за все, не створювали проблем з точки зору "млявості" при наборі тексту. Найповільніший метод, який я дивився, становив приблизно 125 мс за 10 000 дзвінків в IE8. Що становить 0,0125 мс на інсульт.

Я виявив, що методи, опубліковані Codenepal та Робіном Мабеном, найшвидші ~ 0,001 мс (IE8), але остерігайтеся різної семантики.

Можливо, це полегшення тому, хто вводить подібний функціонал у свій код.


1

Відповідь на модифіковану ерікаллен:

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

Він використовує в основному ті самі принципи, але:

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

Це також перевіряє instanceof 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

0

Sitepoint: Відключення назад для 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

0

Я використовую це в своєму коді вже деякий час. Я писав онлайн-тести для студентів і зіткнувся з проблемою, коли студенти під час тесту натискали на зворотний простір, і це поверне їх на екран входу. Розчарування! Це працює на FF точно.

document.onkeypress = Backspace;
function Backspace(event) {
    if (event.keyCode == 8) {
        if (document.activeElement.tagName == "INPUT") {
            return true;
        } else {
            return false;
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.