Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 检测浏览器自动填充_Javascript_Jquery_Events_Event Handling_Autofill - Fatal编程技术网

Javascript 检测浏览器自动填充

Javascript 检测浏览器自动填充,javascript,jquery,events,event-handling,autofill,Javascript,Jquery,Events,Event Handling,Autofill,如何判断浏览器是否自动填充了文本框?特别是用户名和密码框,可以自动填充页面加载 我的第一个问题是在页面加载序列中何时发生这种情况?是在document.ready之前还是之后 其次,我如何使用逻辑来确定是否发生了这种情况?这并不是说我想阻止这件事发生,只是想把它和事件联系起来。最好是这样: if (autoFilled == true) { } else { } $("#myInput").allchange(function () { alert("change!"); });

如何判断浏览器是否自动填充了文本框?特别是用户名和密码框,可以自动填充页面加载

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

其次,我如何使用逻辑来确定是否发生了这种情况?这并不是说我想阻止这件事发生,只是想把它和事件联系起来。最好是这样:

if (autoFilled == true) {

} else {

}
$("#myInput").allchange(function () {
    alert("change!");
});
如果可能的话,我希望看到JSFIDLE显示您的答案

可能的重复项


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

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

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

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

    • Firefox4、IE7和IE8不发送更改事件
    • Safari 5和Chrome 9会发送更改事件
    • 对于其他表单字段:

    • IE 7和IE 8不发送更改事件
    • 当用户从建议列表中选择一个值时,Firefox4会发送change事件,并将选项卡移出该字段
    • Chrome 9不发送更改事件
    • Safari 5会发送更改事件
最好的选择是在表单中使用
autocomplete=“off”
禁用表单的自动完成功能,或者定期轮询以查看表单是否已填写

有关是否在document.ready.ready上或之前填写的问题,请根据浏览器的不同,甚至版本的不同而有所不同。仅当您选择用户名/密码字段时,才填写用户名/密码字段。因此,如果您试图附加到任何事件,那么总的来说,您将有一个非常混乱的代码


你可以很好地阅读这篇文章,我知道这是一篇老文章,但我可以想象很多人来这里寻找解决方案

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

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

github上有一个新的polyfill组件来解决这个问题。看一看。只需要bower安装它,瞧,autofill就可以按预期工作了

bower install autofill-event

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

不幸的是,我发现检查跨浏览器的唯一可靠方法是轮询输入。为了使它更具响应性,还需要倾听事件。 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);
    });
    

为了防止有人正在寻找解决方案(就像我今天一样)来侦听浏览器自动填充更改,我构建了一个自定义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);
    };
你可以这样称呼它:

if (autoFilled == true) {

} else {

}
$("#myInput").allchange(function () {
    alert("change!");
});
我的解决方案:

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

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

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

我使用此解决方案解决了同样的问题

HTML代码应更改为:

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

我也有同样的问题,我写了这个解决方案

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

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

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

似乎有一种解决方案不依赖轮询(至少对于Chrome)。这几乎是一样的粗俗,但我确实认为这比全球民调稍微好一点

考虑以下场景:

  • 用户开始填写字段1

  • 用户选择自动完成建议,该建议自动填充字段2和字段3

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

    这不会是立即的,因为它会被延迟,直到用户模糊字段1,但它不依赖于全局轮询,所以在我看来,这是一个更好的解决方案

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

    或者,您可以使用全局
    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';
    
    if ($("#textbox").is(":-webkit-autofill")) 
    {    
        // the value in the input field of the form was filled in with google chrome autocomplete
    }
    
    $('#email').on('blur input', function() {
        ....
    });
    
    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();
    });
    
        setTimeout(
           function(){
              $("#input_password").focus();
              $("#input_username").focus();
              console.log($("#input_username").val());
              console.log($("#input_password").val());
           }
        ,500);
    
    input:-webkit-autofill {
      -webkit-box-shadow: 0 0 0 30px white inset;
    }
    
      let css = $("#selector").css("box-shadow")
      if (css.match(/inset/))
        console.log("autofilled:", $("#selector"))
    
        $.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');
              }
          );
      });
    
    setTimeout(function() {
     if($('input:-webkit-autofill').length > 0) {
       //do some stuff
     }
    },300)
    
    <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>
    
    $(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);
    
    });
    
    input:-webkit-autofill ~ label {
        top:-20px;
    } 
    
    let style = window.getComputedStyle(document.getElementById('email'))
      if (style && style.backgroundColor !== inputBackgroundNormalState) {
        this.inputAutofilledByBrowser = true
      }
    
    /* 
     * 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);
    
    <div class="input-wrapper">
        <input type="text" name="firstname">
    </div>
    
    input:-webkit-autofill {
      animation-name: onAutoFillStart;
      transition: background-color 50000s ease-in-out 0s;
    }
    input:not(:-webkit-autofill) {
      animation-name: onAutoFillCancel;
    }
    
    <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>
    
    /* 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;
    }
    
        // 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');
            }
          });
        }
    
      }); 
    
    <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("filter");
            if (bckgrnd === 'grayscale(0.21) brightness(0.88) contrast(1.61) invert(0.1) sepia(0.4) saturate(2.06)') {
            /*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>
    
    // 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);
     });
    
    $('selector').on('keyup', aFunction);
    // If tab is active, auto focus for trigger event keyup, blur, change...
    // for inputs has been autofill
    $(window).on('load', () => {
      if (!document.hidden) {
        window.focus();
      }
    })