• IE下点击scrollbar会导致焦点移动到body


    现象

    IE这货果然与众不同,当光标焦点在input时,点击同页面内其他区域的scrollbar,会导致焦点移动到body,从而触发绑定在input上的blur事件,如果input中的值与之前不同,甚至还会触发change事件... Chrome曾经也有类似的问题,但在最新版中已经修正了,而Firefox则完全没有这样的问题。

    影响

    这个问题看起来微不足道,实际上影响还是非常大的,主要表现在下面2个方面

    • 多数的suggest控件会出错
      suggest往往是通过input(输入部分)和div(下拉框部分)组成。有时,下拉框内容过多,用户需要移动滚动条才能看全选项,但因为点击滚动条会让input失去焦点,导致控件误认为用户结束输入,从而关闭suggest的下拉部分,导致用户实际上无法正确的进行滚动条操作。

    • form
      这个更容易理解了,一般来说form的验证都是绑定在blur或者change事件上,如果form太长,需要移动滚动条才能看全的情况下,一旦鼠标点击滚动条就会错误的触发form验证操作,将无用的错误信息显示给用户。

    解决方案

    我们来看看jQueryUI的Autocomplete是怎么解决这个问题的。

    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();
                    }
                });
            });
        }
    }
    

    这下就很清楚了,要处理这个问题,要点有两个:

    • 通过自定义的flag判断是否需要跳过(直接return)input的blur事件
    • 全局(document)监视下一次mousedown事件,如果不是特定区域才执行blur相关操作
  • 相关阅读:
    mysql中的几种join 及 full join问题
    MySQL基础练习题
    SQL之IFNULL()
    SQL之查找表中字段的值相同的记录
    Mysql之将一张表内容导入另一张表中
    selenium无界面操作浏览器与Chrome Options的启动项设置
    SQL UNION 和 UNION ALL 操作符
    Python断言方法assert
    Python标准库--contextlib模块
    Python标准库--itertools模块
  • 原文地址:https://www.cnblogs.com/betarabbit/p/3141482.html
Copyright © 2020-2023  润新知