检测浏览器自动填充

Posted

技术标签:

【中文标题】检测浏览器自动填充【英文标题】:Detecting Browser Autofill 【发布时间】:2012-07-29 09:20:06 【问题描述】:

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

我的第一个问题是这在页面加载序列中什么时候发生?是在 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 我,所以我可以在感谢中投票。 【参考方案1】:

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

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

对于用户名/密码字段:

    Firefox 4、IE 7 和 IE 8 不调度更改事件。 Safari 5 和 Chrome 9 会调度 change 事件。

对于其他表单域:

    IE 7 和 IE 8 不调度更改事件。 当用户从建议列表中选择一个值并从字段中跳出标签时,Firefox 4 会调度 change change 事件。 Chrome 9 不会调度更改事件。 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 团队。在这里查看他们很好的实现:

CSS rules JS hook

【讨论】:

这是迄今为止最好的解决方案!在这里向列夫致敬。感谢您分享 Klarna UI 的解决方案……在我找到这个之前,没有其他任何东西对我有用。救生员! 除了CSS规则,这里github.com/klarna/ui/blob/v4.10.0/Field/styles.scss#L181-L189的关键帧也是需要的 这对我来说完美无缺!需要稍微玩弄一下才能找出确切的方法。感谢 Klarna 团队 可能是因为这个答案很久以前了,但是这个解决方案和 Klarna 的代码对我不起作用,因为我不得不将钩子改为“transitionstart”而不是“animationstart” . ***.com/a/41530600 需要在css动画中添加过渡时间-duration: 0.001s - 否则事件不会在chrome中触发【参考方案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】:

我的解决方案:

像往常一样收听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 调度更改事件,但是当我尝试检索它返回空的值时。【参考方案10】:

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

bower install autofill-event

【讨论】:

这对 jQuery 自定义表单非常有效。我刚把它放进去,我的自定义选择列表与自动填充配合得很好。【参考方案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://***.com/a/35783761/32429

【讨论】:

在 Firefox 86 中工作,尽管 MDN 和 caniuse 另有建议。【参考方案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】:

我花了几个小时解决了在首页加载时检测自动填充输入的问题(没有采取任何用户操作)并找到了适用于 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)) 作为背景图像的属性。我更改了代码。【参考方案20】:

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

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');
);

【讨论】:

【参考方案21】:

对于正在寻找 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);
      
     

【讨论】:

【参考方案22】:

有一个技巧可以理解浏览器是否填充输入(布尔值):

const inputEl = inputRef.current; // select the el with any way, here is ReactJs ref
let hasValue;
try 
  hasValue = inputRef.current.matches(':autofill');
 catch (err) 
  try 
    hasValue = inputRef.current.matches(':-webkit-autofill');
   catch (er) 
    hasValue = false;
  


// hasValue (boolean) is ready

在最后一个花括号之后,hasValue 就可以使用了。您能够检测到浏览器自动填充是否发生。

【讨论】:

【参考方案23】:

我在用户名上使用了 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 事件应用了相同的功能,效果很好。无需额外库的简单解决方案。【参考方案24】:

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

页面加载时,它开始轮询每个输入字段(我设置了 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);
);

【讨论】:

【参考方案25】:

如果您只想检测是否使用了自动填充,而不是准确检测何时以及使用了哪个字段自动填充,您可以简单地添加一个将自动填充的隐藏元素,然后检查这是否包含任何值。我知道这可能不是很多人感兴趣的。将输入字段设置为负的 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';

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

【讨论】:

【参考方案26】:

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

考虑以下场景:

    用户开始填写字段1

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

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

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

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

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

【讨论】:

【参考方案27】:

根据我的个人经验,以下代码适用于 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();
);

【讨论】:

【参考方案28】:

我在 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) ...);我已经收到所有字段的自动填充值。 可能是新版本?【参考方案29】:

我的解决办法是:

    $.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 期间填充自动填充值时,将调用传递给自动填充的回调。在当前示例中,它只是添加了一个类。如果您还有更多问题,请不要犹豫,直接问:)。【参考方案30】:

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

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

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

【讨论】:

以上是关于检测浏览器自动填充的主要内容,如果未能解决你的问题,请参考以下文章

检测自动填充和停止对焦

检测浏览器自动填充

检测 Edge 浏览器的自动填充

解决Google浏览器保存密码自动填充

强制 Chrome 自动填充使用启发式类型?

谷歌自动填充问题???