IE下點擊scrollbar會致使焦點移動到body

現象

IE這貨果真不同凡響,當光標焦點在input時,點擊同頁面內其餘區域的scrollbar,會致使焦點移動到body,從而觸發綁定在input上的blur事件,若是input中的值與以前不一樣,甚至還會觸發change事件... Chrome曾經也有相似的問題,但在最新版中已經修正了,而Firefox則徹底沒有這樣的問題。ide

影響

這個問題看起來微不足道,實際上影響仍是很是大的,主要表如今下面2個方面ui

  • 多數的suggest控件會出錯
    suggest每每是經過input(輸入部分)和div(下拉框部分)組成。有時,下拉框內容過多,用戶須要移動滾動條才能看全選項,但由於點擊滾動條會讓input失去焦點,致使控件誤認爲用戶結束輸入,從而關閉suggest的下拉部分,致使用戶實際上沒法正確的進行滾動條操做。this

  • form
    這個更容易理解了,通常來講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相關操做
相關文章
相關標籤/搜索