現象
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相關操做