检测浏览器自动填充

你怎么知道浏览器是否有自动填充文本框? 特别是用户名和密码框自动填充页面加载。

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

其次,我怎样才能用逻辑来判断这是否发生? 它不是我想阻止这种事情发生,只是勾起了事件。 最好是这样的:

if (autoFilled == true) { } else { } 

如果可能的话,我很乐意看到一个jsfiddle显示你的答案。

可能的重复

浏览器密码自动填充的DOM事件?

浏览器自动填充和Javascript触发的事件

– 这些问题都不能真正解释什么事件被触发,他们只是不断地重新检查文本框(不好performance!)。

问题是自动填充由不同的浏览器处理不同。 有些派遣变革事件,有些则不。 所以当浏览器自动完成一个input字段时,几乎不可能挂接到触发的事件。

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

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

      1. Firefox 4,IE 7和IE 8不会分派更改事件。
      2. Safari 5和Chrome 9发送更改事件。
    • 对于其他表单字段:

      1. IE 7和IE 8不派遣更改事件。
      2. 当用户从build议列表中select一个值并将其从列表中选出时,Firefox 4确实会发送change change事件。
      3. Chrome 9不会发送更改事件。
      4. Safari 5发送更改事件。

您最好的select是在表单中使用autocomplete="off"禁用表单的autocomplete="off" ,或者定期轮询以查看其填充内容。

对于您是否在document.ready之前填充的问题,它会因浏览器而异,甚至不同版本。 只有当您select用户名密码字段填写时,才能input用户名/密码字段。 因此,如果您尝试附加到任何事件,那么总是会有一个非常混乱的代码。

你可以在这里有一个很好的阅读

WebKit浏览器的解决scheme

从MDN文档:-webkit-autofill CSS伪类:

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

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

对Klarna UI团队感谢信 。 在这里看到他们很好的实现

  • CSS规则
  • JS钩子

为了防止有人正在寻找解决scheme(就像我今天一样),为了听取浏览器自动填充更改,下面是我构build的自定义jquery方法,以简化向input添加更改侦听器的过程:

  $.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!"); }); 

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

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

不幸的是,我发现检查这个跨浏览器的唯一可靠的方式是轮询input。 为了使其反应也听事件。 Chrome已经开始从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); }); 

对于谷歌铬自动完成,这对我工作:

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

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

 bower install autofill-event 

我的解决scheme

按照正常方式收听change事件,然后在DOM内容加载上执行以下操作:

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

这将在用户有机会编辑它们之前触发所有非空的字段的变化事件。

我有这个问题的完美解决scheme尝试此代码段。
演示在这里

 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> 

我知道这是一个古老的线程,但我可以想象许多来这里find一个解决scheme。

要做到这一点,你可以检查input是否有价值:

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

我自己使用它来检查我的login表单中的值,当它加载启用提交button。 该代码是为jQuery制作的,但是如果需要的话很容易改变。

我使用这个解决scheme相同的问题。

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

});

在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")) 

我使用用户名上的模糊事件来检查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浏览器)

我有同样的问题,我写了这个解决scheme。

当页面加载时,它会在每个input字段开始轮询(我已经设置了10秒,但可以调整此值)。
10秒后,它停止对每个input字段的轮询,并且仅在焦点input(如果有的话)上开始轮询。 当模糊input时它会停止,如果您重点input,则会再次启动。

通过这种方式,只在真正需要的时候进行轮询,而只在有效的input时轮询

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

如果您自动插入多个值,则效果不佳,但可以调整当前表单上的每个input。

就像是:

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

如果您只想检测是否使用了自动填充function,而不是完全检测何时和使用了哪个字段自动填充function,则可以简单地添加一个将自动填充的隐藏元素,然后检查是否包含任何值。 我明白,这可能不是许多人感兴趣的。设置input字段负TabIndex和绝对坐标远离屏幕。 input是与input的其余部分相同forms的一部分是重要的。 您必须使用由自动填充(例如“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'; 

将此input附加到表单上,并在表单提交中检查其值。

似乎有一个解决scheme,这不依赖于轮询(至less对于Chrome)。 这几乎是一件骇人听闻的事情,但我认为比全球投票更好一些。

考虑以下情况:

  1. 用户开始填写field1

  2. 用户select一个自动填充build议,它会自动填充field2和field3

解决scheme:在所有通过以下jQuery片段$(': – webkit-autofill')检查是否存在自动填充字段的字段上注册一个onblur

这不会是直接的,因为它会延迟到用户模糊字段1,但它不依赖于全局轮询,所以IMO是一个更好的解决scheme。

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

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

尝试在CSS中

input:-webkit-autofill { border-color: #9B9FC4 !important; }

从我个人的经验来看,下面的代码适用于Firefox和Safari浏览器,但是在Chrome浏览器中select自动完成function时效果不佳。

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

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

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

我用Chrome成功了:

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

我的解决scheme是:

  $.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'); } ); }); 

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

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

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