Get keys pressed with Clipboard event in Javascript?

28 Views Asked by At

I have a textarea where users can paste text from the clipboard.

The text pasted clipboarddata.getData('text') gets modified.

However, I need a switch that if pressing CTRL SHIFT V instead of CTRL V the pasted text does not get modified.

I tried to catch the shift key with keydown/keyup:

$('textarea').on('keyup', function(e) 
{
    shiftkey_down = e.shiftKey;
});

and then try to read the boolean variable in the paste event handler:

$('textarea').on('paste', function(e) 
{
    if (shiftkey_down)
    {
        // ...
    }
});

but the paste event comes after keydown and keyup. So I cannot read what key has been pressed. And shiftkey_down is always false inside the paste handler.

What would be the right way to handle this?

The only idea I got is to save the last key combination pressed inside the keydown event and then check the last one pressed inside the paste handler. But it does not seem to work either.


Update:

I tried to use a tiny timeout so the keydown boolean variable is not overwritten immediately:

var shiftkey_paste = false;

$('textarea').on('keydown', function(e) 
{
    if (!shiftkey_paste)
    {
        shiftkey_paste = e.shiftKey && e.ctrlKey;

        console.log('> '+shiftkey_paste);

        setTimeout( function() 
        {
            // set false again after timeout so paste event has chance to pick up a true value
            shiftkey_paste = false;
        }, 10);
    }
    
    console.log('>> ' + shiftkey_paste);
});

And inside the paste handler, I print the value with console.log('>>> ' + shiftkey_paste);.

Result:

> false
>> false
> true
>> true
> false
>> false
>>> false

Also false even though the timeout should have helped.


Update 2:

✔️ Wow, it works with a timeout of 100ms instead of 10ms (!)


If someone finds a better solution, please post your answer.

1

There are 1 best solutions below

5
IT goldman On

Use keydown and keyup to store state of ctrlKey and shiftKey. In case of the special key combo, we cancel the event and insert text to textarea in a patchy manner.

var ctrl = false
var shift = false
textarea.addEventListener('paste', function(ev) {
  var clipboardData = (event.clipboardData || window.clipboardData);

  var pastedText = clipboardData.getData('text');
  if (ctrl && shift) {
    pastedText = "*" + pastedText + "*"
    ev.preventDefault()

    // this code - i don't like it - because you can't ctrl+z
    var cursorPosition = textarea.selectionStart;
    var currentValue = textarea.value;
    var newValue = currentValue.substring(0, cursorPosition) + pastedText + currentValue.substring(textarea.selectionEnd);
    textarea.value = newValue;
    textarea.selectionStart = textarea.selectionEnd = cursorPosition + pastedText.length;
  }
})

textarea.addEventListener('keydown', function(ev) {
  ctrl = ev.ctrlKey
  shift = ev.shiftKey
})

textarea.addEventListener('keyup', function(ev) {
  ctrl = ev.ctrlKey
  shift = ev.shiftKey
})
<textarea id="textarea" style="width:100%" rows="8"></textarea>