输入系的元素主要是说input[type=text],input[type=password],textarea这三种元素. 通常第一个输入用户名,第二个输入密码,第三个输入详细消息.
它们都表现为一个凹入的框框,里面可以让用户输入内容,不同的是输入域只能输入一条, 输入区可以输入多行,密码域使用圆点来遮掩用户的输入.
由于是一个框框,它就存在焦点获得与失去的时机, 还有输入法切换的时机, 于是衍生了一大堆事件.
首先是focus, blur事件, 其次是keydown, keyup, keypress事件, 然后是针对输入内容的监听事件, input是每添加或删除一个字符时触发, change是所有内容输入好,用户点击页面其他元素,让当前表单元素失去焦点时触发! 从IE9开始,添加了compositionstart,compositionupdate,compositionend用来监听用户切换输入法. 因此像中文,我们用五笔或拼音敲了好几下,才生成一个中文,没有这监听,我们恰恰好为元素添加了maxlength属性时,可能输入不了内容.
有关输入法监听事件的更详细的认识,可以看这篇文章《经验总结:应对中文输入法的字符串截断方案》
因此输入系表单元素主要纠缠在用什么事件上,前面几个事件还好办,难点是输入法监听事件,这个特别难兼容,目前我在facebook的react库中有发现兼容处理
但这个很难抽取出来,并且在各浏览器中的表现也不太好,详见这文章:
DOM COMPOSITION EVENTS COMPATIBILITY NOTES
那么剩下能处理的事件就是oninput。oninput也是IE9才支持的事件,在IE6-8中,拥有一个无敌能监听所有属性变动的事件onpropertychange事件。
if(!/null|function/(typeof el.oninput)){ el.attachEvent("onpropertychange", function(e){ if(e.propertyName === "value"){ //这里写input事件的罗辑 } }) }
但这个也不完美,在avalon源码中,兼容input事件涉及更多东西, 大家可以用这个jquery插件实现相应的功能。
此外,输入系表单元素还有一个其他元素没有东西——光标
默认光标总在我们输入内容的后面,但等我们用程序直接对input.value赋值时,光标位置就会丢失。
function getCaret(ctrl) { var start = NaN, end = NaN if (ctrl.setSelectionRange) { start = ctrl.selectionStart end = ctrl.selectionEnd } else if (document.selection && document.selection.createRange) { var range = document.selection.createRange() start = 0 - range.duplicate().moveStart('character', -100000) end = start + range.text.length } return { start: start, end: end } } function setCaret(ctrl, begin, end) { if (!ctrl.value || ctrl.readOnly) return if (ctrl.createTextRange) {//IE6-8 var range = ctrl.createTextRange() range.collapse(true) range.moveStart("character", begin) range.moveEnd('character', end - begin); range.select() } else { ctrl.selectionStart = begin ctrl.selectionEnd = Math.min(end, ctrl.value.length) } }
此外光标的高度可能也受字体影响,可以看这篇文章处理一下。