First of all some background on event trigger order for the input
element:
keydown -> keypress -> paste -> input -> keyup -> change
Whenever you call preventDefault
it stops the chains, like nothing happened.
So my suggestion is to catch the paste event, prevent its default behavior and do your logic there.
I know I can use .on('paste', function(event) { ... }), but that
doesn't give me the text that's been pasted or the contents of the
input element after the paste
Actually you can retrieve the content of the clipboard. See this doc. Support is all major browser (but only IE11+). I do not know if by the time of the writing of the question this functionality was available or not.
Fiddle example
$('#myInput').on('paste', function(e) {
// Cancel the event - this prevents the text from being entered into the input and stops the event chain
e.preventDefault();
// Get the content of the clipboard
let paste = (event.clipboardData || window.clipboardData).getData('text');
// Validate what it is pasted
if (paste == "text to paste") {
// If condition is satisfied manually set the value of the input
$(this)
.val(paste)
// Manually trigger events if you want
.trigger('input')
.trigger('change');
}
});
Notes on the code:
- This solution does not include
setTimeout
. Whenever you make it with setTimeout
you see for a very short time the text being pasted, like a blinking effect.
- If text meets condition I manually set it in the
input
. However this does not trigger input
and change
events. If you need them, just manually trigger them
- Similar approach is to first check the text and if it does not meet requirements then call
preventDefault
, otherwise do nothing. This way you avoid manually setting value in the input and triggering events afterward.