4

キーボードまたはマウス/編集メニューから必要なイベントをキャプチャしたいテキストエリアがあります。これで、ユーザーがCTRL-Vを使用してテキスト領域にテキストをコピーして貼り付けると、キーダウンと貼り付けの両方でprocessUserInputが2回呼び出されますが、これはさまざまな理由で望ましくありません。

私はそれをこのように「解決」しました:

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;
    }
}

この問題に対してもっと洗練された解決策があるかどうか疑問に思いました。

ps onpasteイベントが必要なのは、ユーザーがマウスの右クリックまたはブラウザの編集メニューからテキストをコピーして貼り付けることができるためです。

前もって感謝します!

4

1 に答える 1

5

あなたは正しい方法でやっています。keydownに変更した方が良いですがkeypress、必要に応じてコードをスタイリッシュにすることができます。

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;
}

しかし、もしよろしければ、を使用しpromissesてユーザー入力の処理を行います。そうすれば、プロセスを待機している間にすべての UI スレッドをフリーズすることはできません。

次のようになります。

$("#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);
}

これは非同期の例ですが、非同期 ajax または Web ワーカーを使用してイベントを処理することもできます。これにより、UI スレッドがフリーズしなくなります。

PS .: タイムアウトは UI スレッドのフリーズを妨げません。プロセスを実行中のキューの最後に置くだけです。

ああ、別のヒント!

テキストエリアのテキストを処理している場合は、keypress代わりに使用するよりも優れkeydownています。キーダウンでテキストエリアの値を取得すると変更はありませんが、キーを押すと、押しているキーによって変更された値が取得されます。

http://www.quirksmode.org/dom/events/keys.html

もちろん、引き続き keydown を使用したい場合setTimeoutは、例で作成した を使用して処理を延期できます。

于 2013-01-06T20:19:26.277 に答える