【问题标题】:Detecting Browser Autofill检测浏览器自动填充
【发布时间】:2012-07-27 07:54:37
【问题描述】:

如何判断浏览器是否自动填充了文本框?尤其是在页面加载时自动填充的用户名和密码框。

我的第一个问题是这在页面加载序列中什么时候发生?是在 document.ready 之前还是之后?

其次,我如何使用逻辑来确定是否发生了这种情况?不是我想阻止这种情况发生,只是加入事件。最好是这样的:

if (autoFilled == true) {

} else {

}

如果可能的话,我希望看到一个 jsfiddle 显示你的答案。

可能的重复

DOM event for browser password autofill?

Browser Autofill and Javascript triggered events

--这两个问题都没有真正解释触发了什么事件,它们只是不断地重新检查文本框(不利于性能!)。

【问题讨论】:

  • 检查需要几微秒,而间隔将每 100 毫秒左右触发一次检查......这将如何影响性能?如果存在浏览器触发的事件,我相信他们会使用它。
  • 我明白你的意思,但这取决于我的问题的第一部分,JavaScript 是否知道刚刚发生了变化(例如在 document.ready 之前)
  • Chrome / WebKit 的最佳解决方案是使用 DOM 选择器:document.querySelectorAll('input:-webkit-autofill');经过短暂的延迟 setTimeout(... 这里的代码... 250);
  • 基本上我想自动登录用户,如果它是自动填充的,在它自动注销时又重新登录很烦人。
  • @ChrisN 您的评论实际上给了我一个(简单的)解决方案。不过,我不认为这是一个答案!将它作为一个发布并 ping 我,所以我可以在感谢中投票。

标签: javascript jquery events event-handling autofill


【解决方案1】:

问题是不同浏览器对自动填充的处理方式不同。有些发送更改事件,有些则不发送。因此,几乎不可能挂钩在浏览器自动完成输入字段时触发的事件。

  • 改变不同浏览器的事件触发器:

    • 对于用户名/密码字段:

      1. Firefox 4、IE 7 和 IE 8 不调度更改事件。
      2. Safari 5 和 Chrome 9 会调度 change 事件。
    • 对于其他表单域:

      1. IE 7 和 IE 8 不调度更改事件。
      2. 当用户从建议列表中选择一个值并从字段中跳出标签时,Firefox 4 会调度 change change 事件。
      3. Chrome 9 不会调度更改事件。
      4. Safari 5 确实调度了 change 事件。

您最好的选择是在表单中使用 autocomplete="off" 禁用表单的自动完成功能,或者定期轮询以查看其是否已填写。

对于您是否在 document.ready 之前或之前填写的问题,它因浏览器而异,甚至因版本而异。仅当您选择用户名密码字段时,才会填写用户名/密码字段。因此,如果您尝试附加到任何事件,您将拥有一个非常混乱的代码。

你可以好好阅读这个HERE

【讨论】:

  • 请注意自动填充和自动填充之间的区别。 OP 特指浏览器在页面加载时填写保存的登录详细信息。
  • 通常的黑客攻击是在页面的某些重要部分上插入鼠标。当用户的鼠标指向按钮等时触发该事件。
  • @Bryce 我个人会选择“模糊”事件,因为自动填充是在您进入输入区域后发生的事情。显然它并不理想,但作为上面列出的浏览器的后备,它可能非常有用
  • 不要忘记input 事件。这就是 Chrome 在自动完成时触发的(如果 Chrome 有,也可能是自动填充;我总是关闭这些东西)。
  • 如果您只想知道文本框中的值是否由谷歌浏览器自动完成填写,请查看我的单行答案。
【解决方案2】:

WebKit 浏览器解决方案

来自 :-webkit-autofill CSS 伪类的 MDN 文档:

当一个元素的值被浏览器自动填充时,:-webkit-autofill CSS 伪类匹配

我们可以在所需的<input> 元素上定义一个 void transition css 规则,一旦它是:-webkit-autofilled。然后 JS 将能够连接到 animationstart 事件。

感谢Klarna UI 团队。在这里查看他们很好的实现:

【讨论】:

  • 这是迄今为止最好的解决方案!在这里向列夫致敬。感谢您分享 Klarna UI 的解决方案......在我找到这个之前,没有其他任何东西对我有用。救生员!
  • 除了CSS规则,这里github.com/klarna/ui/blob/v4.10.0/Field/styles.scss#L181-L189的关键帧也是需要的
  • 这对我来说完美无缺!需要稍微玩一下以找出确切的方法。感谢 Klarna 团队
  • 可能是因为这个答案很久以前了,但是这个解决方案和 Klarna 的代码对我不起作用,因为我不得不将钩子改为“transitionstart”而不是“animationstart” . stackoverflow.com/a/41530600
【解决方案3】:

这适用于我最新的 Firefox、Chrome 和 Edge:

$('#email').on('blur input', function() {
    ....
});

【讨论】:

  • 'input'!这对我来说是最简单的解决方案,但我只测试了自动完成,而不是自动填充。
  • 模糊不适用于一些自动完成的附加组件
  • 每次按键都会触发输入。如果您进行服务器调用,它可能会经常触发。
  • 很好的解决方案!这种事件组合解决了用户填充和浏览器自动填充的问题。
【解决方案4】:

我阅读了很多有关此问题的信息,并希望提供一个对我有帮助的快速解决方法。

let style = window.getComputedStyle(document.getElementById('email'))
  if (style && style.backgroundColor !== inputBackgroundNormalState) {
    this.inputAutofilledByBrowser = true
  }

我的模板的 inputBackgroundNormalState 是 'rgb(255, 255, 255)'。

因此,基本上,当浏览器应用自动完成功能时,它们往往会通过在输入上应用不同的(烦人的)黄色来指示输入是自动填充的。

编辑:这适用于每个浏览器

【讨论】:

  • 好主意!
  • 这在 Mozilla 上不起作用,因为背景颜色是通过过滤器应用的,背景颜色仍然是默认的 rgb(255, 255, 255)
【解决方案5】:

对于谷歌浏览器自动完成,这对我有用:

if ($("#textbox").is(":-webkit-autofill")) 
{    
    // the value in the input field of the form was filled in with google chrome autocomplete
}

【讨论】:

  • 它也对我有用。我尝试了数百种解决方案,但没有一种能奏效。非常感谢,节省了我的时间和我寻找解决方案的所有时间。
  • 这种方法会引发错误:“语法错误,无法识别的表达式:不支持的伪:-webkit-autofill”在其他浏览器上(我在 Firefox 上试过)
  • 不适用于 chrome 以及 2020 版,也会抛出错误无法识别的表达式:不支持的伪:-webkit-autofill
【解决方案6】:

以防万一有人正在寻找解决方案(就像我今天一样),要监听浏览器自动填充更改,这是我构建的自定义 jquery 方法,只是为了在添加更改监听器时简化过程输入:

    $.fn.allchange = function (callback) {
        var me = this;
        var last = "";
        var infunc = function () {
            var text = $(me).val();
            if (text != last) {
                last = text;
                callback();
            }
            setTimeout(infunc, 100);
        }
        setTimeout(infunc, 100);
    };

你可以这样称呼它:

$("#myInput").allchange(function () {
    alert("change!");
});

【讨论】:

  • 出于某种原因,此代码无法用于页面重定向(当我注销应用程序并重定向到发生自动填充的登录页面时)。虽然它确实适用于页面刷新。
  • 看起来很像移动电池消耗器:/
  • @StefanFisk - 并非如此。在浏览器页面的 JS 级别设置一个简单的重复计时器不足以影响您的电池,因为在大多数网页中都发生了很多事情......你真的认为 google.com不设置循环计时器?如果我可以简单地用 JS 编写一个耗尽用户电池的网页,那将是一个多么大的电源管理缺陷......
【解决方案7】:

我也遇到了同样的问题,标签没有检测到自动填充,并且填充文本时移动标签的动画重叠,这个解决方案对我有用。

input:-webkit-autofill ~ label {
    top:-20px;
} 

【讨论】:

  • 这很有帮助。
  • 正是我需要的:)
  • 这个答案很旧,但它仍然很好用。
【解决方案8】:

不幸的是,我发现检查此跨浏览器的唯一可靠方法是轮询输入。为了使其响应也听事件。 Chrome 已开始从需要 hack 的 javascript 中隐藏自动填充值。

  • 每半秒到三分之一秒轮询一次(在大多数情况下不需要即时)
  • 使用 JQuery 触发更改事件,然后在侦听更改事件的函数中执行您的逻辑。
  • 为 Chrome 隐藏的自动填充密码值添加修复程序。

    $(document).ready(function () {
        $('#inputID').change(YOURFUNCTIONNAME);
        $('#inputID').keypress(YOURFUNCTIONNAME);
        $('#inputID').keyup(YOURFUNCTIONNAME);
        $('#inputID').blur(YOURFUNCTIONNAME);
        $('#inputID').focusin(YOURFUNCTIONNAME);
        $('#inputID').focusout(YOURFUNCTIONNAME);
        $('#inputID').on('input', YOURFUNCTIONNAME);
        $('#inputID').on('textInput', YOURFUNCTIONNAME);
        $('#inputID').on('reset', YOURFUNCTIONNAME);
    
        window.setInterval(function() {
            var hasValue = $("#inputID").val().length > 0;//Normal
            if(!hasValue){
                hasValue = $("#inputID:-webkit-autofill").length > 0;//Chrome
            }
    
            if (hasValue) {
                $('#inputID').trigger('change');
            }
        }, 333);
    });
    

【讨论】:

  • 我的问题是使用attr('value') 而不是val()。与val() 不同,attr('value') 不包含自动填充值 (Firefox)!
【解决方案9】:

在 github 上有一个新的 polyfill 组件来解决这个问题。看看autofill-event。只需要凉亭安装它,瞧,自动填充按预期工作。

bower install autofill-event

【讨论】:

  • 这对 jQuery 自定义表单非常有效。我刚把它放进去,我的自定义选择列表与自动填充配合得很好。
【解决方案10】:

我的解决方案:

像往常一样收听change 事件,并在加载 DOM 内容时执行以下操作:

setTimeout(function() {
    $('input').each(function() {
        var elem = $(this);
        if (elem.val()) elem.change();
    })
}, 250);

这将在用户有机会编辑之前触发所有非空字段的更改事件。

【讨论】:

  • 完美。我发现第一个使用 Chrome 的解决方案!
  • 真的@RidIculous 一些解决方案可以多么简单。
  • 但 elem.val() 为 chrome 中的自动填充密码字段返回空字符串:(
  • @Hemant_Negi Chrome 不会调度 change 事件吗?如果我错了纠正我。我正在使用 LastPass,我懒得禁用它,看看它是否也能正常工作。
  • 是的 chrome 调度更改事件,但是当我尝试检索它返回空的值时。
【解决方案11】:

我正在寻找类似的东西。仅限 Chrome ......在我的情况下,包装器 div 需要知道输入字段是否被自动填充。所以我可以给它额外的css,就像Chrome在自动填充输入字段时所做的那样。通过查看上面的所有答案,我的组合解决方案如下:

/* 
 * make a function to use it in multiple places
 */
var checkAutoFill = function(){
    $('input:-webkit-autofill').each(function(){
        $(this).closest('.input-wrapper').addClass('autofilled');
    });
}

/* 
 * Put it on the 'input' event 
 * (happens on every change in an input field)
 */
$('html').on('input', function() {
    $('.input-wrapper').removeClass('autofilled');
    checkAutoFill();
});

/*
 * trigger it also inside a timeOut event 
 * (happens after chrome auto-filled fields on page-load)
 */
setTimeout(function(){ 
    checkAutoFill();
}, 0);

这个工作的html是

<div class="input-wrapper">
    <input type="text" name="firstname">
</div>

【讨论】:

    【解决方案12】:

    这是来自 Klarna UI 团队的 CSS 解决方案。在这里查看他们很好的实现resource

    对我来说很好。

    input:-webkit-autofill {
      animation-name: onAutoFillStart;
      transition: background-color 50000s ease-in-out 0s;
    }
    input:not(:-webkit-autofill) {
      animation-name: onAutoFillCancel;
    }
    

    【讨论】:

      【解决方案13】:

      我知道这是一个旧线程,但我可以想象很多人会在这里找到解决方案。

      为此,您可以检查输入是否具有以下值:

      $(function() {
          setTimeout(function() {
              if ($("#inputID").val().length > 0) {
                  // YOUR CODE
              }
          }, 100);
      });
      

      我自己使用它来检查我的登录表单中的值,当它加载以启用提交按钮时。 该代码是为 jQuery 编写的,但如果需要,可以轻松更改。

      【讨论】:

      • 如果您将第三行更新为($("#inputID:-webkit-autofill").val().length &gt; 0) {,此代码对我来说非常有用
      【解决方案14】:

      在 chrome 上,您可以通过为自动填充元素设置特殊的 css 规则来检测自动填充字段,然后使用 javascript 检查元素是否应用了该规则。

      例子:

      CSS

      input:-webkit-autofill {
        -webkit-box-shadow: 0 0 0 30px white inset;
      }
      

      JavaScript

        let css = $("#selector").css("box-shadow")
        if (css.match(/inset/))
          console.log("autofilled:", $("#selector"))
      

      【讨论】:

        【解决方案15】:

        这是带有 webkit 渲染引擎的浏览器的解决方案。 当表单被自动填充时,输入将获得伪类 :-webkit-autofill-(例如 input:-webkit-autofill {...})。所以这是你必须通过 JavaScript 检查的标识符。

        一些测试表格的解决方案:

        <form action="#" method="POST" class="js-filled_check">
        
            <fieldset>
        
                <label for="test_username">Test username:</label>
                <input type="text" id="test_username" name="test_username" value="">
        
                <label for="test_password">Test password:</label>
                <input type="password" id="test_password" name="test_password" value="">
        
                <button type="submit" name="test_submit">Test submit</button>
        
            </fieldset>
        
        </form>
        

        还有 javascript:

        $(document).ready(function() {
        
            setTimeout(function() {
        
                $(".js-filled_check input:not([type=submit])").each(function (i, element) {
        
                    var el = $(this),
                        autofilled = (el.is("*:-webkit-autofill")) ? el.addClass('auto_filled') : false;
        
                    console.log("element: " + el.attr("id") + " // " + "autofilled: " + (el.is("*:-webkit-autofill")));
        
                });
        
            }, 200);
        
        });
        

        页面加载时的问题是获取密码值,甚至长度。这是因为浏览器的安全性。还有超时,这是因为浏览器会在一段时间后填写表单。

        此代码会将类 auto_filled 添加到已填充的输入中。另外,我尝试检查输入类型密码值或长度,但它在页面上发生某些事件后才起作用。所以我尝试触发一些事件,但没有成功。现在这是我的解决方案。 享受!

        【讨论】:

        • 这是最新的答案。
        • 我尝试了这个解决方案,对我来说效果很好。非常感谢。
        【解决方案16】:

        我有这个问题的完美解决方案试试这个代码 sn-p。
        Demo is here

        function ModernForm() {
            var modernInputElement = $('.js_modern_input');
        
            function recheckAllInput() {
                modernInputElement.each(function() {
                    if ($(this).val() !== '') {
                        $(this).parent().find('label').addClass('focus');
                    }
                });
            }
        
            modernInputElement.on('click', function() {
                $(this).parent().find('label').addClass('focus');
            });
            modernInputElement.on('blur', function() {
                if ($(this).val() === '') {
                    $(this).parent().find('label').removeClass('focus');
                } else {
                    recheckAllInput();
                }
            });
        }
        
        ModernForm();
        .form_sec {
          padding: 30px;
        }
        .form_sec .form_input_wrap {
          position: relative;
        }
        .form_sec .form_input_wrap label {
          position: absolute;
          top: 25px;
          left: 15px;
          font-size: 16px;
          font-weight: 600;
          z-index: 1;
          color: #333;
          -webkit-transition: all ease-in-out 0.35s;
          -moz-transition: all ease-in-out 0.35s;
          -ms-transition: all ease-in-out 0.35s;
          -o-transition: all ease-in-out 0.35s;
          transition: all ease-in-out 0.35s;
        }
        .form_sec .form_input_wrap label.focus {
          top: 5px;
          color: #a7a9ab;
          font-weight: 300;
          -webkit-transition: all ease-in-out 0.35s;
          -moz-transition: all ease-in-out 0.35s;
          -ms-transition: all ease-in-out 0.35s;
          -o-transition: all ease-in-out 0.35s;
          transition: all ease-in-out 0.35s;
        }
        .form_sec .form_input {
          width: 100%;
          font-size: 16px;
          font-weight: 600;
          color: #333;
          border: none;
          border-bottom: 2px solid #d3d4d5;
          padding: 30px 0 5px 0;
          outline: none;
        }
        .form_sec .form_input.err {
          border-bottom-color: #888;
        }
        .form_sec .cta_login {
          border: 1px solid #ec1940;
          border-radius: 2px;
          background-color: #ec1940;
          font-size: 14px;
          font-weight: 500;
          text-align: center;
          color: #ffffff;
          padding: 15px 40px;
          margin-top: 30px;
          display: inline-block;
        }
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <form class="form_sec">
            <div class="row clearfix">
                <div class="form-group col-lg-6 col-md-6 form_input_wrap">
                    <label>
                        Full Name
                    </label>
                    <input type="text" name="name" id="name" class="form_input js_modern_input">
                </div>
            </div>
            <div class="row clearfix">
                <div class="form-group form_input_wrap col-lg-6 col-md-6">
                    <label>
                        Emaill
                    </label>
                    <input type="email" name="email" class="form_input js_modern_input">
                </div>
            </div>
            <div class="row clearfix">
                <div class="form-group form_input_wrap col-lg-12 col-md-12">
                    <label>
                        Address Line 1
                    </label>
                    <input type="text" name="address" class="form_input js_modern_input">
                </div>
            </div>
            <div class="row clearfix">
                <div class="form-group col-lg-6 col-md-6 form_input_wrap">
                    <label>
                        City
                    </label>
                    <input type="text" name="city" class="form_input js_modern_input">
                </div>
                <div class="form-group col-lg-6 col-md-6 form_input_wrap">
                    <label>
                        State
                    </label>
                    <input type="text" name="state" class="form_input js_modern_input">
                </div>
            </div>
            <div class="row clearfix">
                <div class="form-group col-lg-6 col-md-6 form_input_wrap">
                    <label>
                        Country
                    </label>
                    <input type="text" name="country" class="form_input js_modern_input">
                </div>
                <div class="form-group col-lg-4 col-md-4 form_input_wrap">
                    <label>
                        Pin
                    </label>
                    <input type="text" name="pincode" class="form_input js_modern_input">
                </div>
            </div>
            <div class="row cta_sec">
                <div class="col-lg-12">
                    <button type="submit" class="cta_login">Submit</button>
                </div>
            </div>
        </form>

        【讨论】:

          【解决方案17】:

          在 Chrome 和 Edge (2020) 中检查 :-webkit-autofill 会告诉您输入已被填充。但是,在用户以某种方式与页面交互之前,您的 JavaScript 无法获取输入中的值。

          使用$('x').focus()$('x').blur() 或在代码中触发鼠标事件都无济于事。

          https://stackoverflow.com/a/35783761/32429

          【讨论】:

          • 在 Firefox 86 中工作,尽管 MDNcaniuse 另有建议。
          【解决方案18】:

          在 2020 年,这就是在 chrome 中对我有用的方法:

          // wait 0.1 sec to execute action after detecting autofill
          // check if input username is autofilled by browser
          // enable "login" button for click to submit form
           $(window).on("load", function(){
                 setTimeout(function(){
          
                     if ($("#UserName").is("input:-webkit-autofill")) 
                     $("#loginbtn").prop('disabled', false); 
          
                }, 100);
           });
          

          【讨论】:

            【解决方案19】:

            我用这个解决方案来解决同样的问题。

            HTML 代码应改为:

            <input type="text" name="username" />
            <input type="text" name="password" id="txt_password" />
            

            并且jQuery代码应该在document.ready:

            $('#txt_password').focus(function(){
                $(this).attr('type','password');
            });
            

            【讨论】:

              【解决方案20】:

              对于正在寻找 2020 年纯 JS 解决方案来检测自动填充的任何人,都可以。

              请原谅标签错误,不能让它很好地放在 SO

                  //Chose the element you want to select - in this case input
                  var autofill = document.getElementsByTagName('input');
                  for (var i = 0; i < autofill.length; i++) {
                    //Wrap this in a try/catch because non webkit browsers will log errors on this pseudo element
                    try{
                      if (autofill[i].matches(':-webkit-autofill')) {
                          //Do whatever you like with each autofilled element
                      }
                    }
                    catch(error){
                      return(false);
                    }
                   }
              

              【讨论】:

                【解决方案21】:

                我花了几个小时解决了在首页加载时检测自动填充输入的问题(没有采取任何用户操作)并找到了适用于 Chrome、Opera、Edge 和 FF 的理想解决方案

                在 Chrome、Opera 上,Edge 问题已经很好解决了

                通过使用伪类input:-webkit-autofill 搜索元素并执行所需的操作(在我的情况下,我正在更改输入包装类以使用浮动标签模式更改标签位置)。

                问题出在 Firefox 上

                因为 FF 没有这样的伪类或类似的类(正如许多人建议的“:-moz-autofill”),只需搜索 DOM 即可看到。您也找不到输入的黄色背景。唯一的原因是浏览器通过更改过滤器属性添加了这种黄色:

                input:-moz-autofill, input:-moz-autofill-preview { filter: grayscale(21%) brightness(88%) contrast(161%) invert(10%) sepia(40%) saturate(206%); }

                因此,对于 Firefox,您必须首先搜索所有输入并获取其计算样式,然后与浏览器设置中硬编码的此过滤器样式进行比较。我真的不知道他们为什么不使用简单的背景颜色,而是使用那个奇怪的滤镜!?他们让生活变得更艰难;)

                这是我的代码在我的网站 (https://my.oodo.pl/en/modules/register/login.php) 上的工作原理:

                <script type="text/javascript">
                /* 
                 * this is my main function
                 */
                var checkAutoFill = function(){
                    /*first we detect if we have FF or other browsers*/
                    var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
                    if (!isFirefox) {
                        $('input:-webkit-autofill').each(function(){
                        /*here i have code that adds "focused" class to my input wrapper and changes 
                        info instatus div. U can do what u want*/
                        $(this).closest('.field-wrapper').addClass('focused');
                        document.getElementById("status").innerHTML = "Your browser autofilled form";
                        });
                    }
                    if (isFirefox) {
                        $('input').each(function(){
                        var bckgrnd = window.getComputedStyle(document.getElementById(this.id), null).getPropertyValue("background-image");
                        if (bckgrnd === 'linear-gradient(rgba(255, 249, 145, 0.5), rgba(255, 249, 145, 0.5))') {
                        /*if our input has that filter property customized by browserr with yellow background i do as above (change input wrapper class and change status info. U can add your code here)*/
                        $(this).closest('.field-wrapper').addClass('focused');
                        document.getElementById("status").innerHTML = "Your Browser autofilled form";
                        }
                        })
                    }
                }
                /*im runing that function at load time and two times more at 0.5s and 1s delay because not all browsers apply that style imediately (Opera does after ~300ms and so Edge, Chrome is fastest and do it at first function run)*/
                checkAutoFill();
                setTimeout(function(){ 
                checkAutoFill();
                }, 500);
                setTimeout(function(){ 
                checkAutoFill();
                }, 1000);
                })
                </script>
                

                我在这里手动编辑了上面的代码,以扔掉一些对你不重要的垃圾。如果它不适合你,那么粘贴到你的 IDE 并仔细检查语法;)当然添加一些调试警报或控制台日志并自定义。

                【讨论】:

                • 在新版本的 FF 中,他们更改了自动填充输入的样式。现在他们使用 linear-gradient(rgba(255, 249, 145, 0.5), rgba(255, 249, 145, 0.5)) 作为背景图像的属性。我更改了代码。
                【解决方案22】:

                我在用户名上使用了 blur 事件来检查 pwd 字段是否已自动填充。

                 $('#userNameTextBox').blur(function () {
                        if ($('#userNameTextBox').val() == "") {
                            $('#userNameTextBox').val("User Name");
                        }
                        if ($('#passwordTextBox').val() != "") {
                            $('#passwordTextBoxClear').hide(); // textbox with "Password" text in it
                            $('#passwordTextBox').show();
                        }
                    });
                

                这适用于 IE,应该适用于所有其他浏览器(我只检查过 IE)

                【讨论】:

                • @ChrisN 我确实用 IE 测试了我的解决方案,浏览器处理 javascsript 事件的方式不同。我的解决方案简单易读,适用于较难编写代码的浏览器之一。
                • 我最终得到了相同的解决方案:blur 事件。我对changeblur 事件应用了相同的功能,效果很好。无需额外库的简单解决方案。
                【解决方案23】:

                我遇到了同样的问题,我已经写了这个解决方案。

                页面加载时,它开始轮询每个输入字段(我设置了 10 秒,但您可以调整此值)。
                10 秒后,它停止轮询每个输入字段,并且仅开始轮询焦点输入(如果有)。 当你模糊输入时它会停止,如果你聚焦一个,它会再次启动。

                通过这种方式,您仅在真正需要时才进行轮询,并且仅在有效输入时进行。

                // This part of code will detect autofill when the page is loading (username and password inputs for example)
                var loading = setInterval(function() {
                    $("input").each(function() {
                        if ($(this).val() !== $(this).attr("value")) {
                            $(this).trigger("change");
                        }
                    });
                }, 100);
                // After 10 seconds we are quite sure all the needed inputs are autofilled then we can stop checking them
                setTimeout(function() {
                    clearInterval(loading);
                }, 10000);
                // Now we just listen on the focused inputs (because user can select from the autofill dropdown only when the input has focus)
                var focused;
                $(document)
                .on("focus", "input", function() {
                    var $this = $(this);
                    focused = setInterval(function() {
                        if ($this.val() !== $this.attr("value")) {
                            $this.trigger("change");
                        }
                    }, 100);
                })
                .on("blur", "input", function() {
                    clearInterval(focused);
                });
                

                当您自动插入多个值时,它不能很好地工作,但可以调整它以查找当前表单上的每个输入。

                类似:

                // This part of code will detect autofill when the page is loading (username and password inputs for example)
                var loading = setInterval(function() {
                    $("input").each(function() {
                        if ($(this).val() !== $(this).attr("value")) {
                            $(this).trigger("change");
                        }
                    });
                }, 100);
                // After 10 seconds we are quite sure all the needed inputs are autofilled then we can stop checking them
                setTimeout(function() {
                    clearInterval(loading);
                }, 10000);
                // Now we just listen on inputs of the focused form
                var focused;
                $(document)
                .on("focus", "input", function() {
                    var $inputs = $(this).parents("form").find("input");
                    focused = setInterval(function() {
                        $inputs.each(function() {
                            if ($(this).val() !== $(this).attr("value")) {
                                $(this).trigger("change");
                            }
                        });
                    }, 100);
                })
                .on("blur", "input", function() {
                    clearInterval(focused);
                });
                

                【讨论】:

                  【解决方案24】:

                  如果您只想检测是否使用了自动填充,而不是准确检测何时以及使用了哪个字段自动填充,您可以简单地添加一个将自动填充的隐藏元素,然后检查这是否包含任何值。我知道这可能不是很多人感兴趣的。将输入字段设置为负的 tabIndex 和屏幕外的绝对坐标。重要的是输入与输入的其余部分属于同一形式。您必须使用将由自动填充选择的名称(例如“secondname”)。

                  var autofilldetect = document.createElement('input');
                  autofilldetect.style.position = 'absolute';
                  autofilldetect.style.top = '-100em';
                  autofilldetect.style.left = '-100em';
                  autofilldetect.type = 'text';
                  autofilldetect.name = 'secondname';
                  autofilldetect.tabIndex = '-1';
                  

                  将此输入附加到表单并在表单提交时检查其值。

                  【讨论】:

                    【解决方案25】:

                    确实似乎是一个不依赖轮询的解决方案(至少对于 Chrome)。这几乎是骇人听闻的,但我确实认为比全球民意调查要好一些。

                    考虑以下场景:

                    1. 用户开始填写字段1

                    2. 用户选择一个自动填充字段 2 和字段 3 的自动完成建议

                    解决方案:在所有字段上注册一个 onblur,通过以下 jQuery sn-p $(':-webkit-autofill') 检查是否存在自动填充字段

                    这不会立即生效,因为它会延迟到用户模糊 field1,但它不依赖于全局轮询,因此 IMO,这是一个更好的解决方案。

                    也就是说,由于按回车键可以提交表单,因此您可能还需要相应的 onkeypress 处理程序。

                    或者,您可以使用全局轮询来检查 $(':-webkit-autofill')

                    【讨论】:

                      【解决方案26】:

                      根据我的个人经验,下面的代码在 firefox IE 和 safari 上运行良好,但在 chrome 中选择自动完成时效果不佳。

                      function check(){
                      clearTimeout(timeObj);
                       timeObj = setTimeout(function(){
                         if($('#email').val()){
                          //do something
                         }
                       },1500);
                      }
                      
                      $('#email').bind('focus change blur',function(){
                       check();
                      });
                      

                      下面的代码效果更好,因为它会在用户每次点击输入字段时触发,从那里您可以检查输入字段是否为空。

                      $('#email').bind('click', function(){
                       check();
                      });
                      

                      【讨论】:

                        【解决方案27】:

                        我在 chrome 上成功了:

                            setTimeout(
                               function(){
                                  $("#input_password").focus();
                                  $("#input_username").focus();
                                  console.log($("#input_username").val());
                                  console.log($("#input_password").val());
                               }
                            ,500);
                        

                        【讨论】:

                        • 不确定 Chrome 自动填充何时运行,但在 $('input, select').on('focusin', function(evt) {...});我已经收到所有字段的自动填充值。
                        • 可能是新版本?
                        【解决方案28】:

                        我的解决办法是:

                            $.fn.onAutoFillEvent = function (callback) {
                                var el = $(this),
                                    lastText = "",
                                    maxCheckCount = 10,
                                    checkCount = 0;
                        
                                (function infunc() {
                                    var text = el.val();
                        
                                    if (text != lastText) {
                                        lastText = text;
                                        callback(el);
                                    }
                                    if (checkCount > maxCheckCount) {
                                        return false;
                                    }
                                    checkCount++;
                                    setTimeout(infunc, 100);
                                }());
                            };
                        
                          $(".group > input").each(function (i, element) {
                              var el = $(element);
                        
                              el.onAutoFillEvent(
                                  function () {
                                      el.addClass('used');
                                  }
                              );
                          });
                        

                        【讨论】:

                        • 对您的解决方案的解释会有所帮助
                        • 我认为很明显。所以基本上想法是检查输入字段的值几次。在当前实现中,它是 10 次,延迟为 100 毫秒。因此,当浏览器在第二个 10*1000=1sec 期间填充自动填充值时,将调用传递给自动填充的回调。在当前示例中,它只是添加了一个类。如果您还有更多问题,请不要犹豫,直接问:)。
                        【解决方案29】:

                        经过研究,问题是 webkit 浏览器不会在自动完成时触发更改事件。我的解决方案是自己获取webkit添加的自动填充类并触发更改事件。

                        setTimeout(function() {
                         if($('input:-webkit-autofill').length > 0) {
                           //do some stuff
                         }
                        },300)
                        

                        这里是铬问题的链接。 https://bugs.chromium.org/p/chromium/issues/detail?id=636425

                        【讨论】:

                          【解决方案30】:

                          我很难在 Firefox 中检测到自动填充。这是唯一对我有用的解决方案:

                          Demo

                          HTML:

                          <div class="inputFields">
                             <div class="f_o">
                                <div class="field_set">
                                  <label class="phold">User</label>
                                  <input type="tel" class="form_field " autocomplete="off" value="" maxlength="50">
                                </div>
                             </div>
                             <div class="f_o">
                                <div class="field_set">
                                   <label class="phold">Password</label>
                                   <input type="password" class="form_field " autocomplete="off" value="" maxlength="50">
                                </div>
                             </div>
                          </div>
                          

                          CSS:

                          /* Detect autofill for Chrome */
                          .inputFields input:-webkit-autofill {
                              animation-name: onAutoFillStart;
                              transition: background-color 50000s ease-in-out 0s;
                          }
                          .inputFields input:not(:-webkit-autofill) {
                              animation-name: onAutoFillCancel;
                          }
                          
                          @keyframes onAutoFillStart {
                          }
                          
                          @keyframes onAutoFillCancel {
                          }
                          .inputFields {
                            max-width: 414px;
                          }
                          
                          .field_set .phold{
                            display: inline-block;
                            position: absolute;
                            font-size: 14px;
                            color: #848484;
                            -webkit-transform: translate3d(0,8px,0);
                            -ms-transform: translate3d(0,8px,0);
                            transform: translate3d(0,8px,0);
                            -webkit-transition: all 200ms ease-out;
                            transition: all 200ms ease-out;
                            background-color: transparent;
                            -webkit-backface-visibility: hidden;
                            backface-visibility: hidden;
                            margin-left: 8px;
                            z-index: 1;
                            left: 0;
                            pointer-events: none;
                          }
                          
                          .field_set .phold_active {
                             font-size: 12px;
                             -webkit-transform: translate3d(0,-8px,0);
                            -ms-transform: translate3d(0,-8px,0);
                            transform: translate3d(0,-8px,0);
                            background-color: #FFF;
                            padding-left: 3px;
                            padding-right: 3px;
                          }
                          
                          .field_set input[type='text'], .field_set select, .field_set input[type='tel'], .field_set input[type='password'] {
                              height: 36px;
                          }
                          
                          .field_set input[type='text'], .field_set input[type='tel'], .field_set input[type='password'], .field_set select, .field_set textarea {
                              box-sizing: border-box;
                              width: 100%;
                              padding: 5px;
                              -webkit-appearance: none;
                              -moz-appearance: none;
                              appearance: none;
                              border: 1px solid #ababab;
                              border-radius: 0;
                          }
                          
                          .field_set {
                              margin-bottom: 10px;
                              position: relative;
                          }
                          
                          .inputFields .f_o {
                              width: 100%;
                              line-height: 1.42857143;
                              float: none;
                          }
                          

                          JavaScript:

                              // detect auto-fill when page is loading
                            $(window).on('load', function() {
                              // for sign in forms when the user name and password are filled by browser
                              getAutofill('.inputFields');
                            });
                          
                            function getAutofill(parentClass) {
                              if ($(parentClass + ' .form_field').length > 0) {    
                                var formInput = $(parentClass + ' .form_field');
                                formInput.each(function(){   
                                  // for Chrome:  $(this).css('animation-name') == 'onAutoFillStart'
                                  // for Firefox: $(this).val() != ''
                                  if ($(this).css('animation-name') == 'onAutoFillStart' || $(this).val() != '') {
                                    $(this).siblings('.phold').addClass('phold_active');
                                  } else {
                                    $(this).siblings('.phold').removeClass('phold_active');
                                  }
                                });
                              }
                            } 
                          
                            $(document).ready(function(){
                          
                              $(document).on('click','.phold',function(){
                                $(this).siblings('input, textarea').focus();
                              });
                              $(document).on('focus','.form_field', function(){
                                $(this).siblings('.phold').addClass('phold_active');
                              });
                          
                              // blur for Chrome and change for Firefox
                              $(document).on('blur change','.form_field', function(){
                                var $this = $(this);
                                if ($this.val().length == 0) {        
                                  $(this).siblings('.phold').removeClass('phold_active');
                                } else {
                                  $(this).siblings('.phold').addClass('phold_active');
                                }
                              });
                          
                              // case when form is reloaded due to errors
                              if ($('.form_field').length > 0) {
                                var formInput = $('.form_field');
                                formInput.each(function(){
                                  if ($(this).val() != '') {
                                    $(this).siblings('.phold').addClass('phold_active');
                                  } else {
                                    $(this).siblings('.phold').removeClass('phold_active');
                                  }
                                });
                              }
                          
                            }); 
                          

                          对于 Chrome,我使用:if ($(this).css('animation-name') == 'onAutoFillStart')

                          对于 Firefox:if ($(this).val() != '')

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 2020-01-08
                            • 2012-05-23
                            • 2015-02-18
                            • 2015-11-13
                            • 2013-04-04
                            相关资源
                            最近更新 更多