现象
IE这货果真不同凡响,当光标焦点在input时,点击同页面内其余区域的scrollbar,会致使焦点移动到body,从而触发绑定在input上的blur事件,若是input中的值与以前不一样,甚至还会触发change事件... Chrome曾经也有相似的问题,但在最新版中已经修正了,而Firefox则彻底没有这样的问题。ide
影响
这个问题看起来微不足道,实际上影响仍是很是大的,主要表如今下面2个方面ui
多数的suggest控件会出错
suggest每每是经过input(输入部分)和div(下拉框部分)组成。有时,下拉框内容过多,用户须要移动滚动条才能看全选项,但由于点击滚动条会让input失去焦点,致使控件误认为用户结束输入,从而关闭suggest的下拉部分,致使用户实际上没法正确的进行滚动条操做。thisform
这个更容易理解了,通常来讲form的验证都是绑定在blur或者change事件上,若是form太长,须要移动滚动条才能看全的状况下,一旦鼠标点击滚动条就会错误的触发form验证操做,将无用的错误信息显示给用户。spa
解决方案
咱们来看看jQueryUI的Autocomplete是怎么解决这个问题的。code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
// input's blur event blur: function( event ) { if ( this.cancelBlur ) { delete this.cancelBlur; return; } clearTimeout( this.searching ); this.close( event ); this._change( event ); } // dropdown's mousedown event mousedown: function( event ) { // prevent moving focus out of the text field event.preventDefault(); // IE doesn't prevent moving focus even with event.preventDefault() // so we set a flag to know when we should ignore the blur event this.cancelBlur = true; this._delay(function() { delete this.cancelBlur; }); // clicking on the scrollbar causes focus to shift to the body // but we can't detect a mouseup or a click immediately afterward // so we have to track the next mousedown and close the menu if // the user clicks somewhere outside of the autocomplete var menuElement = this.menu.element[ 0 ]; if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { this._delay(function() { var that = this; this.document.one( "mousedown", function( event ) { if ( event.target !== that.element[ 0 ] && event.target !== menuElement && !$.contains( menuElement, event.target ) ) { that.close(); } }); }); } } |
这下就很清楚了,要处理这个问题,要点有两个:orm
- 经过自定义的flag判断是否须要跳过(直接return)input的blur事件
- 全局(document)监视下一次mousedown事件,若是不是特定区域才执行blur相关操做