Подтвердить что ты не робот

Изменение нажатия клавиши

В поле ввода или contenteditable = true div, как я могу изменить нажатие клавиши для буквы "a", чтобы вернуть keybress для буквы "b"? I.e., каждый раз, когда вы вводите букву "a" в div, вывод на самом деле является буквой "b".

Я не занимаюсь решением, которое работает в IE, - это тот, который работает в Safari, Chrome и FF.

В Chrome я вижу, что событие keypress имеет свойства "charCode", "keyCode" и "which", которым присваивается номер события нажатия клавиши. Если я запускаю событие при нажатии клавиши, я могу изменить эти значения, но я не могу понять, что вернуть, чтобы фактический ключ, который набрал, был другим. Например:

$(window).keypress(function(e){  //$(window) is a jQuery object
    e.charCode = 102;
    e.which = 102;
    e.keyCode = 102;
    console.log(e);
    return e;
});

Я также вижу, что наряду с charCode, который и keyCode, также имеет свойство "originalEvent", которое также имеет эти свойства. Однако я не смог их изменить (я пробовал такие вещи, как e.originalEvent.charCode = 102).

4b9b3361

Ответ 1

Вы не можете изменить символ или ключ, связанный с ключевым событием, или полностью имитировать ключевое событие. Тем не менее, вы можете обрабатывать нажатия клавиш самостоятельно и вручную вставлять символ, который вы хотите, в текущую точку вставки/каретку. Я предоставил код, чтобы сделать это в нескольких местах в Stack Overflow. Для элемента contenteditable:

Вот пример jsFiddle: http://www.jsfiddle.net/Ukkmu/4/

Для ввода:

Пример кросс-браузера jsFiddle: http://www.jsfiddle.net/EXH2k/6/

IE >= 9 и не-IE jsFiddle пример: http://www.jsfiddle.net/EXH2k/7/

Ответ 2

Хорошо, что вы могли бы сделать для <input> или <textarea>, просто убедитесь, что в нем нет никаких "a" символов:

$('input.whatever').keypress(function() {
  var inp = this;
  setTimeout(function() {
    inp.value = inp.value.replace(/a/g, 'b');
  }, 0);
});

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

edit — о, и причина, по которой я ввел этот пример с "исправлением", происходящим в обработчике тайм-аута, заключается в том, что он гарантирует, что браузер имеет возможность обрабатывать собственное поведение для события "keypress". Когда выполняется код обработчика тайм-аута, мы уверены, что значение элемента будет обновлено. Я понимаю, что прикосновение культа груза к этому кодексу.

Ответ 3

Пример моего решения (изменение input[type=text] символа ',' на '.'):

element.addEventListener('keydown', function (event) {
if(event.key === ','){
  setTimeout(function() {
    event.target.value += '.';
  }, 4);
  event.preventDefault();
};

Ответ 4

Я не уверен, что это "легко" сделать, с чем-то вроде этого:

$(window).keypress(function(e) { 
    //Captures 'a' or 'A'
    if(e.which == 97 || e.which == 65)
    {
        //Simulate a keypress in a specific field  
    }
});

Я знаю, что jQuery имеет симулирующий плагин для имитации событий нажатия клавиш и т.д. jQuery Simulate. Возможно, стоит посмотреть - также возможно какой-то тип события jQuery Trigger().

Ответ 5

Вот пример без использования каких-либо библиотек

const input = document.querySelector('input')

// this is the order of events into an input
input.addEventListener('focus', onFocus)
input.addEventListener('keydown', keyDown)
input.addEventListener('keypress', keyPress)
input.addEventListener('input', onInput)
input.addEventListener('keyup', keyUp)
input.addEventListener('change', onChange)
input.addEventListener('blur', onBlur)

function onFocus  (event) { info(event) }
function keyDown  (event) { info(event) }
function keyPress (event) {
  info(event)
  // this 2 calls will stop 'input' and 'change' events
  event.preventDefault();
  event.stopPropagation();
  
  // get current props
  const target = event.target
  const start = target.selectionStart;
  const end = target.selectionEnd;
  const val = target.value;
  
  // get some char based on event
  const char = getChar(event);
  
  // create new value
  const value = val.slice(0, start) + char + val.slice(end);
  
  // first attemp to set value
  // (doesn't work in react because value setter is overrided)
  // target.value = value

  // second attemp to set value, get native setter
  const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
    window.HTMLInputElement.prototype,
    "value"
  ).set;
  nativeInputValueSetter.call(target, value);

  // change cursor position
  target.selectionStart = target.selectionEnd = start + 1;
  
  // dispatch 'input' again
  const newEvent = new InputEvent('input', {
    bubbles: true,
    inputType: 'insertText',
    data: char
  })
  event.target.dispatchEvent(newEvent);
}
function keyUp    (event) { info(event) }
function onInput  (event) { info(event) }
function onChange (event) { info(event) }
function onBlur   (event) {
  // dispatch 'change' again
  const newEvent = new Event('change', { bubbles: true })
  event.target.dispatchEvent(newEvent);
  info(event)
}

function info     (event) { console.log(event.type) }

function getChar(event) {
  // will show X if letter, will show Y if Digit, otherwise Z
  return event.code.startsWith('Key')
    ? 'X'
    : event.code.startsWith('Digit')
      ? 'Y'
      : 'Z'
}
<input type="text">

Ответ 6

Вот простой пример для замены , чтобы . используя Vanilla JavaScript

// change ',' to '.'
document.getElementById('only_float').addEventListener('keypress', function(e){
    if (e.key === ','){
        // get old value
        var start = e.target.selectionStart;
        var end = e.target.selectionEnd;
        var oldValue = e.target.value;

        // replace point and change input value
        var newValue = oldValue.slice(0, start) + '.' + oldValue.slice(end)
        e.target.value = newValue;

        // replace cursor
        e.target.selectionStart = e.target.selectionEnd = start + 1;

        e.preventDefault();
    }
})
<input type="text" id="only_float" />