在JavaScript中监听IME键盘输入事件


Posted in Javascript onMay 29, 2011

输入法应当如何触发键盘事件呢?是每一下击键都触发一次事件,还是选词完毕才触发事件呢?整句输入又该如何触发事件呢?不同的操作系统和不同的浏览器对此有不同的看法。在最糟糕的情况下,用户使用输入法后浏览器就只触发一次 keydown ,之后就没有任何的键盘事件了。这对于 Suggestion 控件的实现来说是个大问题,因为 Suggestion 控件需要监听文本输入框的变化,而事件是最准确也最节省计算资源的做法,如果换成轮询的话性能就可能受到影响。
首先,要监听启用输入法后的击键事件应当使用 keydown 事件,这是信息最丰富的一个事件,因为在启用输入法后别的键盘事件可能不会被触发。其次,大多数操作系统和浏览器都实现了一个事实标准,就是在用户使用输入法输入时, keydown 事件传入的 keyCode 取值为 229 。然而触发 keydown 的频率是不确定的,有些情况下每一下击键都触发事件,有些情况下只有选词完毕才触发事件。这时候,如果我们还是要实时监控文本框的内容变化,就必须使用轮询了。

var timer; 
var imeKey = 229; 
function keydownHandler (e) { 
clearInterval(timer) 
if (e.keyCode == imeKey) { 
timer = setInterval(checkTextValue, 50); 
} else { 
checkTextValue(); 
} 
} 
function checkTextValue() { 
/* handle input text change */ 
}

Opera 是一款有趣的浏览器,别人做的事情它都不做,别人都不做的事情它都喜欢做。例如说,它偏偏不支持 keyCode == 229 这个事实标准,而要使用 keyCode == 197 来表示输入法的使用。因此,你需要在上述代码的基础上做一下改良,如果监测到是 Opera 浏览器,就换一个 keyCode 常量来做比较。
var imeKey = (UA.Opera == 0) ? 229 : 197;
最后,还有一个更不受重视的浏览器叫做 Firefox for Mac 。估计是因为 Mac 版本对于 Mozilla 来说实在是太不重要了,所以很多 Windows 版本都没问题的地方 Mac 版本就会出小问题,例如说对上述事件的支持。 Firefox for Mac 不会出现 keyCode == 229 的情况,而且在输入法启用后只有第一下击键会触发 keydown 事件,因此只能在击键后一直使用轮询。
if (e.keyCode == imeKey || UA.Firefox > 0 && UA.OS == 'Macintosh') {
在添加了这两项改进后,实时监控文本框的变化就没有问题了,即使用户启用了输入法。完整的代码如下:
var timer; 
var imeKey = (UA.Opera == 0) ? 229 : 197; 
function keydownHandler (e) { 
clearInterval(timer) 
if (e.keyCode == imeKey || UA.Firefox > 0 && UA.OS == 'Macintosh') { 
timer = setInterval(checkTextValue, 50); 
} else { 
checkTextValue(); 
} 
} 
function checkTextValue() { 
/* handle input text change */ 
}
Javascript 相关文章推荐
jQuery的实现原理的模拟代码 -5 Ajax
Aug 07 Javascript
点击标签切换和自动切换DIV选项卡
Aug 10 Javascript
JavaScript字符串对象slice方法入门实例(用于字符串截取)
Oct 16 Javascript
jquery实现可拖拽弹出层特效
Jan 04 Javascript
js判断浏览器类型及设备(移动页面开发)
Jul 30 Javascript
JavaScript数组的栈方法与队列方法详解
May 26 Javascript
jQuery基于BootStrap样式实现无限极地区联动
Aug 26 Javascript
Vue集成Iframe页面的方法示例
Dec 12 Javascript
vue 使用html2canvas将DOM转化为图片的方法
Sep 11 Javascript
VUE v-for循环中每个item节点动态绑定不同函数的实例
Sep 26 Javascript
apicloud拉起小程序并传递参数的方法示例
Nov 21 Javascript
基于vue.js仿淘宝收货地址并设置默认地址的案例分析
Aug 20 Javascript
解读JavaScript代码 var ie = !-[1,] 最短的IE判定代码
May 28 #Javascript
Jquery css函数用法(判断标签是否拥有某属性)
May 28 #Javascript
最新28个很棒的jQuery 教程
May 28 #Javascript
JavaScript使用IEEE 标准进行二进制浮点运算产生莫名错误的解决方法
May 28 #Javascript
真正的JQuery.ajax传递中文参数的解决方法
May 28 #Javascript
jquery 图片上传按比例预览插件集合
May 28 #Javascript
使用jquery实现select添加实现后台权限添加的效果
May 28 #Javascript
You might like
解析PHP SPL标准库的用法(遍历目录,查找固定条件的文件)
2013/06/18 PHP
探讨GDFONTPATH能否被winxp下的php支持
2013/06/21 PHP
php三种实现多线程类似的方法
2015/10/30 PHP
CodeIgniter基于Email类发邮件的方法
2016/03/29 PHP
php通过各种函数判断0和空
2020/07/04 PHP
jQuery层次选择器选择元素使用介绍
2013/04/18 Javascript
jquery解析JSON数据示例代码
2014/03/17 Javascript
jQuery中delegate()方法用法实例
2015/01/19 Javascript
jQuery实现跨域
2015/02/03 Javascript
readonly和disabled属性的区别
2015/07/26 Javascript
javascript实现base64 md5 sha1 密码加密
2015/09/09 Javascript
浅谈node.js中async异步编程
2015/10/22 Javascript
原生js实现自由拖拽弹窗代码demo
2016/06/29 Javascript
mui back 返回刷新页面的实例
2017/12/06 Javascript
浅谈vuepress 踩坑记
2018/04/18 Javascript
js console.log打印对象时属性缺失的解决方法
2019/05/23 Javascript
JS自定义对象创建与简单使用方法示例
2020/01/15 Javascript
vue 避免变量赋值后双向绑定的操作
2020/11/07 Javascript
关于Js中new操作符的作用详解
2021/02/21 Javascript
[50:58]2018DOTA2亚洲邀请赛 4.1 小组赛 B组 Mineski vs EG
2018/04/03 DOTA
python实现代码行数统计示例分享
2014/02/10 Python
python实现计算倒数的方法
2015/07/11 Python
在Django中限制已登录用户的访问的方法
2015/07/23 Python
12步入门Python中的decorator装饰器使用方法
2016/06/20 Python
python输出100以内的质数与合数实例代码
2018/07/08 Python
详解Python 爬取13个旅游城市,告诉你五一大家最爱去哪玩?
2019/05/07 Python
使用python来调用CAN通讯的DLL实现方法
2019/07/03 Python
Python网络编程之使用TCP方式传输文件操作示例
2019/11/01 Python
将python字符串转化成长表达式的函数eval实例
2020/05/11 Python
python中lower函数实现方法及用法讲解
2020/12/23 Python
Mistine官方海外旗舰店:泰国国民彩妆品牌
2016/12/28 全球购物
基本公共卫生服务健康教育工作方案
2014/05/22 职场文书
车间安全生产标语
2014/06/06 职场文书
初中家长评语和期望
2014/12/26 职场文书
教师旷工检讨书
2015/08/15 职场文书
java设计模式--三种工厂模式详解
2021/07/21 Java/Android