Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vanilla javascript : intercept key on input and change key value

I want to intercept the keys typed in one input and change them to others.

For example, I want to simulate typing a 1 each time a key is pressed.

I was thinking to something like this :

           //this example does not work, it will trigger an endless loop

            Array.from(document.querySelectorAll('.onlyOne')).forEach(input =>
                               input.addEventListener('keydown', (event) => {      
                                event.preventDefault();
                                event.srcElement.dispatchEvent(new KeyboardEvent('keydown', { 'key': 49 }));

                            });
                        }
                    );

I canot just add 1 whith event.target.value += 1; cause when there is already text in the input and the cursor is not at the end of the text or the user has selected all text with the mouse , it would not act naturally if text is added at the end of input

Could you help me please?

like image 607
Pipo Avatar asked May 08 '26 20:05

Pipo


1 Answers

By dispatching an event from within the event that causes the same event, you're creating an infinite loop that will cause a Range Error: Maximum call stack size exceeded.

Instead of the event, simply add a 1 to where the cursor is on each keydown.

Array.from(document.querySelectorAll('.onlyOne')).forEach(input =>
  input.addEventListener('keydown', (event) => {
    event.preventDefault();
    event.target.insertAtCaret('1');
}));


HTMLInputElement.prototype.insertAtCaret = function (text) {
  text = text || '';
  if (document.selection) {
    // IE
    this.focus();
    var sel = document.selection.createRange();
    sel.text = text;
  } else if (this.selectionStart || this.selectionStart === 0) {
    // Others
    var startPos = this.selectionStart;
    var endPos = this.selectionEnd;
    this.value = this.value.substring(0, startPos) +
      text +
      this.value.substring(endPos, this.value.length);
    this.selectionStart = startPos + text.length;
    this.selectionEnd = startPos + text.length;
  } else {
    this.value += text;
  }
};
<input class='onlyOne' value="foo">

The HTMLInputElement.prototype.insertAtCaret is taken from this answer: https://stackoverflow.com/a/19961519/3993662

You can change that to a normal function if you don't want to extend the built in's prototype.

like image 133
baao Avatar answered May 11 '26 09:05

baao