web-dev-qa-db-ja.com

ブラウザーの自動入力の検出

ブラウザがテキストボックスを自動入力したかどうかをどのように確認しますか?特に、ページの読み込み時に自動入力されるユーザー名とパスワードのボックスを使用します。

私の最初の質問は、ページロードシーケンスでこれがいつ発生するのかということです。 document.readyの前または後ですか?

次に、ロジックを使用して、これが発生したかどうかを確認するにはどうすればよいですか?これが発生するのを止めたいわけではなく、イベントにフックするだけです。できれば次のようなもの:

if (autoFilled == true) {

} else {

}

可能であれば、私はあなたの答えを示しているjsfiddleを見たいです。

可能性のある重複

ブラウザパスワードの自動入力のDOMイベント?

ブラウザーの自動入力とJavascriptトリガーイベント

-これらの質問はどちらも実際にトリガーされるイベントを説明するものではなく、テキストボックスを継続的に再確認するだけです(パフォーマンスには向いていません!)。

141
Undefined

問題は、オートフィルがブラウザごとに異なる方法で処理されることです。 changeイベントをディスパッチするものも、しないものもあります。そのため、ブラウザが入力フィールドをオートコンプリートするときにトリガーされるイベントにフックすることはほとんど不可能です。

  • さまざまなブラウザーのイベントトリガーを変更します。

    • ユーザー名/パスワードフィールドの場合:

      1. Firefox 4、IE 7、およびIE 8はchangeイベントをディスパッチしません。
      2. Safari 5およびChrome 9はchangeイベントをディスパッチします。
    • 他のフォームフィールドの場合:

      1. IE 7およびIE 8は、変更イベントをディスパッチしません。
      2. Firefox 4は、ユーザーが提案のリストから値を選択し、フィールドからタブで移動すると、change changeイベントをディスパッチします。
      3. Chrome 9はchangeイベントを送出しません。
      4. Safari 5はchangeイベントを送出します。

最適なオプションは、フォームでautocomplete="off"を使用してフォームのオートコンプリートを無効にするか、定期的にポーリングして入力が完了したかどうかを確認することです。

Document.readyの前または前に記入するかどうかについての質問については、ブラウザーごとに、さらにはバージョンごとに異なります。ユーザー名/パスワードフィールドの場合、ユーザー名を選択した場合のみパスワードフィールドが入力されます。したがって、イベントにアタッチしようとすると、非常に複雑なコードになります。

これをよく読むことができます HERE

113
afrin216

WebKitブラウザーのソリューション

:-webkit-autofillCSS擬似クラスのMDNドキュメントから:

:-webkit-autofill CSS擬似クラスは、要素の値がブラウザーによって自動入力されるときに一致します

<input>edになったら、目的の:-webkit-autofill要素にvoidtransitioncssルールを定義できます。 JSはanimationstartイベントにフックできます。

Klarna UI チームの功績。ここでのニース実装を参照してください。

54
Lev Kazakov

誰かが(今日と同じように)解決策を探している場合、ブラウザーの自動入力の変更を聞くために、変更リスナーを入力に追加するときにプロセスを単純化するために、私が作成したカスタム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);
    };

次のように呼び出すことができます。

$("#myInput").allchange(function () {
    alert("change!");
});
15
LcSalazar

これは、最新のFirefox、Chrome、およびEdgeで機能します。

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

Google chromeオートコンプリートの場合、これは私のために働いた:

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

残念ながら、このクロスブラウザをチェックするために私が見つけた唯一の信頼できる方法は、入力をポーリングすることです。レスポンシブにするには、イベントもリッスンします。 Chromeは、ハックが必要なjavascriptから自動入力値を非表示にし始めました。

  • 半分から3分の1秒ごとにポーリングします(ほとんどの場合、インスタントである必要はありません)
  • 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);
    });
    
7
Bucket

私はこの問題について多くのことを読んでいて、私を助けてくれる非常に迅速な回避策を提供したかったのです。

let style = window.getComputedStyle(document.getElementById('email'))
  if (style && style.backgroundColor !== inputBackgroundNormalState) {
    this.inputAutofilledByBrowser = true
  }

ここで、テンプレートのinputBackgroundNormalStateは 'rgb(255、255、255)'です。

そのため、基本的にブラウザがオートコンプリートを適用する場合、入力に別の(迷惑な)黄色を適用することで入力が自動入力されることを示す傾向があります。

編集:すべてのブラウザで機能します

7
DrNio

Githubでこの問題に対処するための新しいポリフィルコンポーネントがあります。 autofill-event をご覧ください。それをインストールして、ボイラーするだけで、オートフィルは期待どおりに機能します。

bower install autofill-event
6
David

私は同様のものを探していました。 Chromeのみ...私の場合、ラッパーdivは入力フィールドが自動入力されたかどうかを知る必要がありました。そのため、入力フィールドで自動入力するときにChromeが行うように、追加のcssを指定できます。上記のすべての答えを見ると、私が結合したソリューションは次のようになりました。

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

これが機能するためのhtmlは

<div class="input-wrapper">
    <input type="text" name="firstname">
</div>
4
Julesezaar

私の解決策:

通常どおりchangeイベントをリッスンし、DOMコンテンツのロード時にこれを行います。

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

これにより、ユーザーが編集する前に空ではないすべてのフィールドの変更イベントが発生します。

4
Camilo Martin

また、ラベルがオートフィルを検出しないという同じ問題に直面し、テキストを埋めるときにラベルを移動するためのアニメーションが重なっていたため、この解決策がうまくいきました。

input:-webkit-autofill ~ label {
    top:-20px;
} 
3
st0495

クロムでは、オートフィルされた要素に特別な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"))
2
Pietro Coelho

この質問には完璧な解決策があります。このコードスニペットを試してください。
デモはこちら

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>
2
Suresh Pattu

私はこれが古いスレッドであることを知っていますが、多くの人がこれに対する解決策を見つけるためにここに来ると想像できます。

これを行うには、次のコマンドを使用して、入力に値があるかどうかを確認できます。

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

私はこれを使用して、送信ボタンを有効にするためにロードされたときにログインフォームの値をチェックします。コードはjQuery用に作成されていますが、必要に応じて簡単に変更できます。

2
S.Lund

同じ問題に対してこのソリューションを使用しました。

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');
});
1
amir2h

これは、webkit render engineを使用するブラウザーのソリューションです。フォームが自動入力されると、入力は擬似クラス:-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);

});

ページがロードされるときの問題は、パスワードの値、さらには長さを取得することです。これは、ブラウザのセキュリティが原因です。また、timeoutは、ブラウザが一定の時間シーケンスの後にフォームに入力するためです。

このコードは、クラスauto_filledを入力に追加します。また、入力タイプのパスワード値または長さを確認しようとしましたが、ページで何らかのイベントが発生した直後に機能しました。そのため、イベントをトリガーしようとしましたが、成功しませんでした。今のところ、これが私の解決策です。楽しい!

1
Adam Šipický

Klarna UIチームから取ったCSSソリューションを次に示します。こちらのニースの実装をご覧ください resource

私には問題ありません。

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

私は同じ問題を抱えていて、この解決策を書きました。

ページの読み込み時にすべての入力フィールドでポーリングを開始します(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);
});
0
Fez Vrasta

私の個人的な経験から、以下のコードはfirefox IEとsafariでうまく機能しますが、クロムでオートコンプリートを選択するのにはあまりうまくいきません。

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();
});
0
roger

私の解決策は次のとおりです。

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

調査後の問題は、Webkitブラウザーがオートコンプリート時に変更イベントを発生させないことです。私の解決策は、Webkitが追加し、自分で変更イベントをトリガーする自動入力クラスを取得することでした。

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

クロムの問題へのリンクはこちらです。 https://bugs.chromium.org/p/chromium/issues/detail?id=636425

0
Cvetan Himchev

いつどのフィールドに自動入力が使用されたかを正確に検出するのではなく、自動入力が使用されたかどうかのみを検出したい場合は、自動入力される非表示要素を追加してから、任意の値が含まれます。これは多くの人が興味を持っているものではないかもしれないことを理解しています。負のtabIndexと画面から十分に離れた絶対座標を入力フィールドに設定します。入力が残りの入力と同じフォームの一部であることが重要です。自動入力によって取得される名前(「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';

この入力をフォームに追加し、フォーム送信時にその値を確認します。

0
bornSwift

私はchromeで成功しました:

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

ユーザー名にblurイベントを使用して、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のみをチェックしました)

0

doesは、ポーリングに依存しない(少なくともChromeの場合)これに対する解決策のようです。それはほとんどハックのようですが、グローバルなポーリングよりもわずかに優れていると思います。

次のシナリオを検討してください。

  1. ユーザーがfield1の入力を開始します

  2. ユーザーがfield2とfield3を自動入力するオートコンプリート候補を選択します

解決策:次のjQueryスニペット$( ':-webkit-autofill')を介して自動入力フィールドの存在をチェックするすべてのフィールドにonblurを登録します

これは、ユーザーがfield1を曖昧にするまで遅延されるため、すぐには実行されませんが、グローバルポーリングに依存しないため、IMOはより良いソリューションです。

ただし、Enterキーを押すとフォームを送信できるため、onkeypressに対応するハンドラーも必要になる場合があります。

または、グローバルポーリングを使用して$( ':-webkit-autofill')を確認できます

0
Dan D