textarea关于输入问题
我有一个textarea,我想要从键盘或鼠标/编辑菜单捕获必要的事件。 现在,当用户副本通过CTRL-V在textarea中粘贴文本时,将在keydown和paste上调用processUserInput两次,这是出于各种原因所不希望的。
我用这种方式“解决”了它:
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事件,因为用户可以通过鼠标右键单击或通过浏览器编辑菜单复制粘贴文本。
提前致谢!
你正在做正确的方式。 如果您更改keydown
更好,但如果您愿意,可以让您的代码更时尚:
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-worker来处理事件,这样您就不会冻结UI线程。
PS。:超时不会阻止UI线程冻结,它只会将您的进程放在执行队列的末尾。
啊,另一个提示!
如果您正在处理textarea中的文本,那么最好使用keypress
而不是keydown
因为如果你在keydown中获得textarea值它将没有更改,但是按键将通过您按下的键获得更改的值。
http://www.quirksmode.org/dom/events/keys.html
当然,如果你仍然想使用keydown,你可以使用我在示例中创建的setTimeout
来推迟处理。