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

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

其次,我如何使用逻辑来找出是否发生了这种情况?这不是我想阻止这种情况发生,只是挂钩到事件。最好是这样的:

if (autoFilled == true) {

} else {

}

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

可能重复

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

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

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


当前回答

我的解决方案是:

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

其他回答

下面是来自Klarna UI团队的CSS解决方案。参见它们的出色实现

对我来说没问题。

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

例如,为了检测电子邮件,我尝试了“on change”和突变观察者,但都不起作用。setInterval与LinkedIn自动填充一起工作得很好(不透露我所有的代码,但你知道的),如果你在这里添加额外的条件来降低AJAX的速度,它与后端一起工作得很好。如果表单字段没有变化,比如他们没有输入来编辑他们的电子邮件,lastEmail会阻止毫无意义的AJAX ping。

// lastEmail needs scope outside of setInterval for persistence.
var lastEmail = 'nobody';
window.setInterval(function() { // Auto-fill detection is hard.
    var theEmail = $("#email-input").val();
    if (
        ( theEmail.includes("@") ) &&
        ( theEmail != lastEmail )
    ) {
        lastEmail = theEmail;
        // Do some AJAX
    }
}, 1000); // Check the field every 1 second

这是一个解决方案的浏览器与webkit渲染引擎。 当表单被自动填充时,输入将获得伪类:-webkit-autofill- (f.e. 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添加到填充的输入中。此外,我尝试检查输入类型的密码值或长度,但它只是在页面上发生的一些事件后工作。所以我试图触发一些事件,但没有成功。现在这是我的解。 享受吧!

除了其他答案,我喜欢添加这个帮助函数,它可以防止脚本错误,你可以使用例如在DOMContentLoaded或onload(与setTimeout >=500一起,因为有一些延迟,直到浏览器自动填充),在输入元素上的onchange或表单上的onsubmit:

function isAutofilled(element) {
  return [":autofill", ":-webkit-autofill", ":-moz-autofill"].some((selector) => {
    try {
      return element.matches(selector);
    } catch {
      return false;
    }
  });
}

我很难发现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() != ")