检测浏览器自动填充
你怎么知道浏览器是否有自动填充文本框? 特别是用户名和密码框自动填充页面加载。
我的第一个问题是什么时候发生在页面加载序列? 在document.ready之前还是之后?
其次,我怎样才能用逻辑来判断这是否发生? 它不是我想阻止这种事情发生,只是勾起了事件。 最好是这样的:
if (autoFilled == true) { } else { }
如果可能的话,我很乐意看到一个jsfiddle显示你的答案。
可能的重复
浏览器密码自动填充的DOM事件?
浏览器自动填充和Javascript触发的事件
– 这些问题都不能真正解释什么事件被触发,他们只是不断地重新检查文本框(不好performance!)。
问题是自动填充由不同的浏览器处理不同。 有些派遣变革事件,有些则不。 所以当浏览器自动完成一个input字段时,几乎不可能挂接到触发的事件。
-
更改不同浏览器的事件触发器:
-
对于用户名/密码字段:
- Firefox 4,IE 7和IE 8不会分派更改事件。
- Safari 5和Chrome 9发送更改事件。
-
对于其他表单字段:
- IE 7和IE 8不派遣更改事件。
- 当用户从build议列表中select一个值并将其从列表中选出时,Firefox 4确实会发送change change事件。
- Chrome 9不会发送更改事件。
- 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)。 这几乎是一件骇人听闻的事情,但我认为比全球投票更好一些。
考虑以下情况:
-
用户开始填写field1
-
用户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