Changing the keypress

2019-01-05 04:44发布

In an input box or contenteditable=true div, how can I modify a keypress for the letter "a" to return a keybress for the letter "b"? I.e., every time you type the letter "a" in the div, the output is actually the letter "b".

I'm not that concerned with a solution that works in IE--just one that works in Safari, Chrome, & FF.

In Chrome, I can see that a keypress event has the properties "charCode", "keyCode", and "which", all of which get assigned the keypress event number. If I fire an event on a keypress, I can modify these values, but I can't figure out what to return so that the actual key that gets typed is different. For example:

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

I can also see that along with charCode, which, and keyCode, there is also an "originalEvent" property which in turn also has these properties. However, I haven't been able to modify those (I tried with things like e.originalEvent.charCode = 102).

5条回答
女痞
2楼-- · 2019-01-05 05:15

I'm not sure if this is "easily" do-able, with something like this:

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

I do know that jQuery has a simulate plug-in to simulate keypress events etc, jQuery Simulate. It might be worth looking into - also possibly some type of jQuery Trigger() event.

查看更多
你好瞎i
3楼-- · 2019-01-05 05:16

You can't change the character or key associated with a key event, or fully simulate a key event. However, you can handle the keypress yourself and manually insert the character you want at the current insertion point/caret. I've provided code to do this in a number of places on Stack Overflow. For a contenteditable element:

Here's a jsFiddle example: http://www.jsfiddle.net/Ukkmu/4/

For an input:

Cross-browser jsFiddle example: http://www.jsfiddle.net/EXH2k/6/

IE >= 9 and non-IE jsFiddle example: http://www.jsfiddle.net/EXH2k/7/

查看更多
三岁会撩人
4楼-- · 2019-01-05 05:22

Well what you could do for an <input> or <textarea> is just make sure that the value doesn't have any "a" characters in it:

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

This approach probably couldn't handle all the possible tricks you could pull with something that really swapped out the "pressed" character, but I don't know any way to actually do that.

edit — oh, and the reason that I typed in that example with the "fixup" happening in a timeout handler is that it makes sure that the browser has the opportunity to handle the native behavior for the "keypress" event. When the timeout handler code runs, we're sure that the value of the element will have been updated. There's a touch of the cargo cult to this code, I realize.

查看更多
走好不送
5楼-- · 2019-01-05 05:23

My solution example (change in input[type=text] the character ',' to '.'):

element.addEventListener('keydown', function (event) {
if(event.key === ','){
  setTimeout(function() {
    event.target.value += '.';
  }, 4);
  event.preventDefault();
};
查看更多
Luminary・发光体
6楼-- · 2019-01-05 05:28

Here is an example without using any libraries

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

查看更多
登录 后发表回答