Ruby's Louvre

每天学习一点点算法

导航

表单元素之输入系

输入系的元素主要是说input[type=text],input[type=password],textarea这三种元素. 通常第一个输入用户名,第二个输入密码,第三个输入详细消息.

它们都表现为一个凹入的框框,里面可以让用户输入内容,不同的是输入域只能输入一条, 输入区可以输入多行,密码域使用圆点来遮掩用户的输入.

由于是一个框框,它就存在焦点获得与失去的时机, 还有输入法切换的时机, 于是衍生了一大堆事件.

首先是focus, blur事件, 其次是keydown, keyup, keypress事件, 然后是针对输入内容的监听事件, input是每添加或删除一个字符时触发, change是所有内容输入好,用户点击页面其他元素,让当前表单元素失去焦点时触发! 从IE9开始,添加了compositionstart,compositionupdate,compositionend用来监听用户切换输入法. 因此像中文,我们用五笔或拼音敲了好几下,才生成一个中文,没有这监听,我们恰恰好为元素添加了maxlength属性时,可能输入不了内容.

有关输入法监听事件的更详细的认识,可以看这篇文章《经验总结:应对中文输入法的字符串截断方案》

因此输入系表单元素主要纠缠在用什么事件上,前面几个事件还好办,难点是输入法监听事件,这个特别难兼容,目前我在facebook的react库中有发现兼容处理

https://github.com/facebook/react/blob/master/src/renderers/dom/client/eventPlugins/BeforeInputEventPlugin.js#L175

但这个很难抽取出来,并且在各浏览器中的表现也不太好,详见这文章:

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插件实现相应的功能。

jquery.inputevent

此外,输入系表单元素还有一个其他元素没有东西——光标

默认光标总在我们输入内容的后面,但等我们用程序直接对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)
    }
}

此外光标的高度可能也受字体影响,可以看这篇文章处理一下。

关于调整input里面的输入光标大小

posted on 2016-01-11 15:41  司徒正美  阅读(1125)  评论(0编辑  收藏  举报