[javascript] 檢測瀏覽器自動填充


10 Answers

WebKit瀏覽器的解決方案

從MDN文檔:-webkit-autofill CSS偽類:

當元素的值由瀏覽器自動填充時,-webkit-autofill CSS偽類匹配

一旦它是:-webkit-autofill ed,我們就可以在所需的<input>元素上定義一個void transition css規則。 然後,JS將能夠掛接到animationstart事件。

Klarna UI團隊感謝。 在這裡看到他們很好的實現

Question

你如何判斷瀏覽器是否有自動填充文本框? 特別是使用用戶名和密碼框自動填充頁面加載。

我的第一個問題是什麼時候在頁面加載序列中出現這種情況? 在document.ready之前還是之後?

其次,我該如何使用邏輯來判斷這是否發生? 它並不是說我想阻止這種事情發生,只是將事件掛鉤。 最好是這樣的:

if (autoFilled == true) {

} else {

}

如果可能的話,我很樂意看到一個jsfiddle顯示你的答案。

可能的重複

瀏覽器密碼自動填充的DOM事件?

瀏覽器自動填充和Javascript觸發事件

- 這些問題並不能真正解釋觸發什麼事件,他們只是不斷重新檢查文本框(不適合性能!)。




我的解決方案

像平常一樣收聽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" />

和jQuery代碼應該在document.ready

$('#txt_password').focus(function(){
    $(this).attr('type','password');
});



在github上有一個新的polyfill組件來解決這個問題。 看看autofill-event 。 只需安裝它即可,自動填充按預期工作。

bower install autofill-event



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



我的解決方案是:

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



似乎有一個解決方案不依賴於輪詢(至少對於Chrome來說)。 這幾乎和黑客一樣,但我認為比全球投票更好一些。

考慮以下情況:

  1. 用戶開始填寫field1

  2. 用戶選擇一個自動填充建議,它可以自動填充field2和field3

解決方案:在所有通過以下jQuery片段$(': - webkit-autofill')檢查是否存在自動填充字段的字段中註冊一個onblur

這不會是直接的,因為它會延遲到用戶模糊字段1,但它不依賴於全局輪詢,因此IMO是更好的解決方案。

也就是說,由於按Enter鍵可以提交表單,因此您可能還需要onkeypress的相應處理程序。

或者,您可以使用全局輪詢來檢查$(': - webkit-autofill')




這適用於最新的Firefox,Chrome和Edge:

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



我遇到了同樣的問題,我寫了這個解決方案。

當頁面加載時,它會在每個輸入字段開始輪詢(我已經設置了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);
});



這是帶有Webkit渲染引擎的瀏覽器的解決方案。 當表單被自動填充時,輸入將得到偽類:-webkit-autofill- (fe 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添加到填充的輸入。 此外,我試圖檢查輸入類型的密碼值或長度,但它是在頁面發生一些事件後才起作用的。 所以我試圖觸發一些事件,但沒有成功。 現在這是我的解決方案。 請享用!




從我個人的經驗來看,下面的代碼適用於Firefox和IE瀏覽器,但在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();
});



Related