输入法下keyup失效的解决方案
在某些情况下,比如自动补全(auto complete)的输入框中,需要使用keyup事件来监听键盘的输入以迅速作出回应。
关键在于keyup, 如果世界是美好的,那么就不会有这篇blog. 可是……
世界是不美好的。我们活在中文世界,我们要用输入法。在输入法开启的情况下,您会碰到不美好的事情:keyup失效。对于您绑定到keyup的任何回调函数,除非您把输入法切换回英文状态,否则它会无动于衷。如果能称之为bug,我会很高兴,因为bug会有修复的可能,如果是特征(feature),那么,我只好叹息一下。
问题
在开启输入法的情况下,三个浏览器的具体问题如下:
- IE:触发keydown和keyup, 不触发keypress. 能够获得输入值。
- Firefox:触发keydown和keypress, 不触发keyup. 输入值未能获得。在回车后会触发keyup, 可获得输入值。
- Opera:keydown, keypress和keyup都不触发,输入值也未能获。
(如果您能帮我试用一下Safari,我会很高兴并谢谢您。这里有一个测试页面:http://tonextone.com/test/eventTest.html)
解决方案
总结出以上问题,没有兴奋反而陷入绝望,因为没有google出解决方案(是的,对于拉丁语系的老外来说,不会存在输入法)。但是,wait, 谷歌搜索的自动补全不是工作得好好的吗?于是研究一下这个 http://www.google.cn/ac.js。嘿嘿,虽然混淆得还可以,但还是可以发现蛛丝马脚的。它使用一个计时器,当输入框处于聚焦(focus)状态时,每 10 毫秒执行一次回调函数。
虽然挺耗资源(所以建议在输入框失焦(blur)时,一定要清除这个计时器),但也只能如此了。作前端开发的,不仅要与语言(JavaScript, CSS, HTML) 斗,还要与浏览器斗,其乐无穷也。
更新:IE 有一个 onpropertychange 事件处理器可以随时检测变化,对应之,Firefox 和 Opera 有一个 oninput 事件处理器也可以达到目的。遗憾的是,在输入法开启的情况下,Opera对于 oninput 也没法随时监听(表现在:输入英文字母可以监听到,而中文则失效)。如果不考虑 Opera, IE使用 onpropertychange 而 Firefox 使用 oninput, 也可解决我们上述问题。
另外需要注意的是, oninput 比较诡异,您可以<input oninput="jsFunc()" ... />来绑定,也可以用addEventListener来绑定,就是不能使用 DOM 0 的element.oninput = function(){} 的形式来绑定,否则不生效。
未曾测试Safari, 有心者可自行测试之。
October 31st, 2007 at 05:01
终于能够感觉到做网站和企业应用如何不同了。做企业应用只要做IE就可以了,因为可以要求用户统一用IE。所以虽然貌似这种问题过去遇到过也都轻轻飘过了。
October 31st, 2007 at 09:49
safari
我试过了
可以获得值.
October 31st, 2007 at 10:07
我猜这篇一定是跟微软拼音有关。=。=
其实我以前也撞到过。。。。。。
对了。我换域名了。下面改改地址。
October 31st, 2007 at 10:47
感谢你的分享。
我们最近做的一个网站,登陆框不知怎么回事,按回车键无法提交。所以我想写个函数,在输入框获得焦点的时候,用keypress模拟提交事件。
请教一下,怎样判断一个输入框处于聚焦状态呢?我没有查到专门的属性。现在打算在输入框onfocus的时候绑定一个函数,onblur的时候取消它,这样做是不是太笨了呢……
October 31st, 2007 at 10:54
Safari出发down和up,但只有keyup正确找到输入内容
keyDown:å(229) :
keyPress:(0) :
keyUp:A(65) :
keyDown:å(229) :
keyPress:(0) :
keyUp:D(68) :
keyDown:å(229) :
keyPress:(0) :
keyUp:F(70) :
keyDown:å(229) :
keyPress:(0) :
keyUp:E(69) :
October 31st, 2007 at 11:07
还是比较偏向使用计时器。
用事件感觉有点怪。
October 31st, 2007 at 14:05
@aoao
貌似只有一些不常用的输入法比如陈桥五笔(未测试)之类才没有问题。
@kakawar
只能是这么做。不过可以先把主要的函数写好,onfocus/onblur只是作为一个计时器开关而已。
@Cloudream
非常感谢。
@Bonede
从理论上说,应该是监听事件比较合适。但是既然有问题,那么只好用计时器了。这属于trick了。
November 2nd, 2007 at 10:43
我在safari下使用,OpenVanilla+自己的五笔码表,没有问题
keyDown:K(75) :
keyUp:K(75) : 口
keyDown:W(87) : 口
keyUp:W(87) : 口人
keyDown:G(71) : 口人
keyUp:G(71) : 口人王
keyDown: (32) : 口人王
keyUp: (32) : 哈
keyDown:K(75) : 哈
keyUp:K(75) : 哈口
keyDown:W(87) : 哈口
keyUp:W(87) : 哈口人
keyDown:G(71) : 哈口人
keyUp:G(71) : 哈口人王
keyDown: (32) : 哈口人王
keyUp: (32) : 哈哈
onChange:哈哈
November 2nd, 2007 at 22:38
1、与浏览器斗
2、与输入法斗
3、与变态用户斗
November 4th, 2007 at 01:28
感谢你的分享。
学习了,支持一下。
November 5th, 2007 at 13:14
最近也写了一个自动完成的JS,因为是针对英文查询绑定动作的,所以没碰到过输入法问题,看来等以后扩展中文输入的时候,问题就明显起来了,呵呵
淘宝上不是也有一个类似的自动提示吗?不知道啥方法来绕过解决这个问题,有空去研究下,嘿嘿
November 8th, 2007 at 00:52
Safari works fine.
November 13th, 2007 at 21:56
虽然和输入法没多少关系,但是对键盘事件的讲解很详细:
http://unixpapa.com/js/key.html
November 14th, 2007 at 21:56
FF2.0下使用测试:
keyDown:(17) :
keyUp: (32) :
keyUp:(17) : keyDown:å(229) :
keyPress:å(229) :
keyUp: (32) : 你keyDown:å(229) : 你
keyPress:å(229) : 你
keyUp: (32) : 你好
IE6.0-SP2下测试:
keyDown:(17) :
keyUp: (32) :
keyUp:(17) :
——————————————————————————–
keyDown:å(229) :
keyUp:W(87) :
——————————————————————————–
keyDown:å(229) :
keyUp:Q(81) :
——————————————————————————–
keyDown:å(229) :
keyUp: (32) : 你
——————————————————————————–
keyDown:å(229) : 你
keyUp:V(86) : 你
——————————————————————————–
keyDown:å(229) : 你
keyUp:B(66) : 你
——————————————————————————–
keyDown:å(229) : 你
keyUp: (32) : 你好
——————————————————————————–
onChange:你好
January 15th, 2008 at 22:11
快被这个问题弄晕了。最后非ie下设了一个计时器检测value,ie下用onkeyup解决的
April 12th, 2008 at 15:30
能up就up,赫赫
May 4th, 2008 at 02:24
“每10秒执行一次回调函数。”
应该是每10毫秒,10秒太长了。
July 5th, 2008 at 00:46
onpropertychange别乱用啊…对象任何一个属性值变更了都会触发..包括样式….
August 2nd, 2008 at 16:55
谢谢!
August 26th, 2008 at 20:38
[...] Realazy的探索:http://realazy.org/blog/2007/10/31/solution-of-keyup-failing-when-ime-is-on/ [...]