i have a textarea where i want to capture the necessary events either them be from the keyboard or the mouse/edit menu. Now, when a user copy pastes a text in the textarea through CTRL-V, processUserInput is called twice, both on keydown and on paste which is undesirable for various reasons.
i have "solved" it this way:
var IsProcessingEvent = false;
$("#textarea").on('click keydown cut paste', processUserInput);
function processUserInput(e) {
if(!IsProcessingEvent) {
IsProcessingEvent = true;
// do the actual processing of user input
IsProcessingEvent = false;
}
}
I was wondering if there is a more elegant solution to this problem.
p.s the onpaste event is needed because the user may copy paste the text through the mouse right click or through the browser edit menu.
thanks in advance!
-
Not sure, but try to use event.stopPropagation()sdespont– sdespont2013年01月06日 20:14:29 +00:00Commented Jan 6, 2013 at 20:14
-
@sdespont will not work because they are different events. It will stop keydown propagation then execute the past and stop it propagation too.Gabriel Gartz– Gabriel Gartz2013年01月06日 20:37:15 +00:00Commented Jan 6, 2013 at 20:37
1 Answer 1
You are doing the right way dude. Just better if you change keydown for keypress, but you can get your code stylish if you want:
var isProcessingEvent = false;
$("#textarea").on('click keypress cut paste', processUserInput);
function processUserInput(e) {
// Is processing event, so stop here.
if(isProcessingEvent) {
return;
}
isProcessingEvent = true;
// do the actual processing of user input
isProcessingEvent = false;
}
But if I would you, I will use a promisses to work with your processing of user input, that way you can not freeze all your UI Thread while wainting for the process.
Will be something like this:
$("#textarea").on('click keypress cut paste', processUserInput);
function processUserInput(e) {
// Is processing event, so stop here.
if(processUserInput.working) {
// The user trigger the event while it was processing
processUserInput.doAgain = {
// save context
ctx: this,
// save event
e: e
};
return;
}
processUserInput.working = true;
function finished() {
processUserInput.working = false;
// The process finished but has new changes in the textfield so...
var lastEvent = processUserInput.doAgain;
if (lastEvent) {
processUserInput.doAgain = null;
// Process this guy again
setTimeout(processUserInput.bind(lastEvent.ctx), 0, lastEvent.e);
}
}
function theProcess(e, cb) {
// do my async stuff here
// Unfreeze the click/keydown/cut/past events in the textarea
if (typeof cb === 'function') {
cb();
}
}
setTimeout(theProcess.bind(this), 0, e, finished);
}
This is a example for async, but you may use a async ajax, or web-worker to process your event, this way you would not freeze the UI Thread.
PS.: Timeout don't prevent UI Thread from freeze, it will just put your process in the end of the executing queue.
Ahh another tip!
If you are processing the text in the textarea, is better then you use keypress instead keydown because if you get the textarea value in the keydown it will not have changes, but the keypress will get the value changed by the key you are pressing.
http://www.quirksmode.org/dom/events/keys.html
Of course if you still want to use keydown you can defer the processing using the setTimeout that I made in the example.