MirrorMirror
MirrorMirror

Reputation: 188

textarea on input issue

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!

Upvotes: 4

Views: 2289

Answers (1)

Gabriel Gartz
Gabriel Gartz

Reputation: 2870

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.

Upvotes: 5

Related Questions