it-swarm.com.de

Erkennen von Browser-Autofill

Wie können Sie feststellen, ob ein Browser ein Textfeld automatisch ausgefüllt hat? Besonders bei Benutzernamen und Kennwortfeldern, die sich automatisch beim Laden der Seite befinden.

Meine erste Frage ist, wann dies in der Reihenfolge beim Laden der Seite auftritt. Ist es vor oder nach document.ready?

Zweitens, wie kann ich mithilfe von Logik herausfinden, ob dies aufgetreten ist? Es ist nicht so, dass ich verhindern möchte, dass dies geschieht. Hängen Sie sich einfach in das Ereignis ein. Am besten so etwas:

if (autoFilled == true) {

} else {

}

Wenn möglich würde ich gerne ein Jsfiddle sehen, das Ihre Antwort zeigt.

Mögliche Duplikate

DOM-Ereignis für automatisches Ausfüllen des Browserkennworts?

Browser-Autofill und Javascript-ausgelöste Ereignisse

- Beide Fragen erklären nicht wirklich, welche Ereignisse ausgelöst werden, sie überprüfen nur ständig das Textfeld (nicht gut für die Leistung!).

132
Undefined

Das Problem ist, dass das automatische Ausfüllen von Browsern unterschiedlich ist. Einige senden das Änderungsereignis aus, andere nicht. Daher ist es fast unmöglich, sich auf ein Ereignis zu stützen, das ausgelöst wird, wenn der Browser ein Eingabefeld automatisch ausfüllt.

  • Ändern Sie den Ereignisauslöser für verschiedene Browser:

    • Für Benutzername/Passwort-Felder:

      1. Firefox 4, IE 7 und IE 8 lösen das Änderungsereignis nicht aus.
      2. Safari 5 und Chrome 9 lösen das Änderungsereignis aus.
    • Für andere Formularfelder:

      1. IE 7 und IE 8 lösen das Änderungsereignis nicht aus.
      2. Firefox 4 löst das Änderungsereignis aus, wenn Benutzer einen Wert aus einer Liste von Vorschlägen und Registerkarten außerhalb des Felds auswählen.
      3. Chrome 9 löst das Änderungsereignis nicht aus.
      4. Safari 5 löst das Änderungsereignis aus.

Die beste Option besteht darin, die automatische Vervollständigung eines Formulars mithilfe von autocomplete="off" in Ihrem Formular zu deaktivieren oder in regelmäßigen Abständen eine Abfrage durchzuführen, um zu sehen, ob das Formular ausgefüllt ist.

Für Ihre Frage, ob es auf oder vor document.ready ausgefüllt ist, variiert es von Browser zu Browser und sogar von Version zu Version. Bei Benutzernamen/Passwortfeldern nur, wenn Sie ein Benutzername auswählen. Das Passwortfeld ist ausgefüllt. Insgesamt hätten Sie also einen sehr chaotischen Code, wenn Sie versuchen, an ein Ereignis anzuhängen.

Sie können dies HIER gut lesen.

110
afrin216

Lösung für WebKit-Browser

Aus den MDN-Dokumenten für die : -webkit-autofill CSS-Pseudoklasse: 

Die: -webkit-autofill CSS-Pseudoklasse stimmt überein, wenn der Wert eines Elements vom Browser automatisch ausgefüllt wird

Wir können eine void Übergang css-Regel für das gewünschte <input>-Element definieren, sobald es :-webkit-autofilled ist. JS kann sich dann mit dem Ereignis animationstart verbinden.

Credits an das Klarna UI Team. Sehen Sie die Nice-Implementierung hier:

44
Lev Kazakov

Für den Fall, dass jemand nach einer Lösung sucht (genauso wie ich es heute war), um eine Browser-Autofill-Änderung anzuhören, habe ich hier eine benutzerdefinierte Jquery-Methode entwickelt, die den Prozess vereinfacht, wenn Sie einem Eingang einen Änderungslistener hinzufügen:

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

Man kann es so nennen:

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

Dies funktioniert für mich im neuesten Firefox, Chrome und Edge:

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

Für Google Chrome-Autovervollständigung funktionierte dies für mich:

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

Leider ist der einzige zuverlässige Weg, diesen Browser zu überprüfen, das Abfragen der Eingabe. Damit es ansprechbar ist, hören Sie auch auf Ereignisse. Chrome hat begonnen, die Werte für das automatische Ausfüllen vor Javascript zu verbergen, für das ein Hack erforderlich ist.

  • Umfrage jede halbe bis dritte Sekunde (muss in den meisten Fällen nicht sofort sein)
  • Lösen Sie das Änderungsereignis mit JQuery aus und führen Sie dann Ihre Logik in einer Funktion aus, die auf das Änderungsereignis wartet.
  • Fügen Sie ein Update für versteckte Werte für das automatische Ausfüllen von Chrome-Werten hinzu.

    $(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

Ich habe viel über dieses Problem gelesen und wollte eine sehr schnelle Abhilfe schaffen, die mir half.

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

dabei ist inputBackgroundNormalState für meine Vorlage 'rgb (255, 255, 255)'.

Wenn Browser also die automatische Vervollständigung anwenden, neigen sie dazu, anzuzeigen, dass die Eingabe automatisch gefüllt wird, indem eine andere (störende) gelbe Farbe auf die Eingabe angewendet wird.

Bearbeiten: es funktioniert für jeden Browser 

7
DrNio

Es gibt eine neue Polyfill-Komponente, um dieses Problem auf Github zu beheben. Werfen Sie einen Blick auf autofill-event . Sie müssen nur installieren und voilà, Autofill funktioniert wie erwartet.

bower install autofill-event
6
David

Ich habe nach einer ähnlichen Sache gesucht. Nur Chrome ... In meinem Fall musste der Wrapper div wissen, ob das Eingabefeld automatisch gefüllt wurde. Ich könnte es also extra css geben, genau wie Chrome es im Eingabefeld tut, wenn es automatisch gefüllt wird. Als ich alle Antworten oben sah, war meine kombinierte Lösung die folgende:

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

Die HTML-Datei für diese Funktion wäre

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

Meine Lösung:

Hören Sie sich change-Ereignisse wie gewohnt an. Führen Sie beim Laden des DOM-Inhalts Folgendes aus:

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

Dadurch werden die Änderungsereignisse für alle Felder ausgelöst, die nicht leer sind, bevor der Benutzer sie bearbeiten konnte.

4
Camilo Martin

Auf Chrome können Sie Felder zum automatischen Ausfüllen erkennen, indem Sie eine spezielle CSS-Regel für automatisch gefüllte Elemente festlegen und anschließend mit Javascript überprüfen, ob das Element diese Regel angewendet hat.

Beispiel:

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

Ich habe die perfekte Lösung für diese Frage, probieren Sie dieses Code-Snippet aus.
Demo ist da

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

Ich habe diese Lösung für dasselbe Problem verwendet.

Der HTML-Code sollte sich folgendermaßen ändern: 

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

und jQuery-Code sollte in document.ready sein:

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

Ich weiß, dass dies ein alter Thread ist, aber ich kann mir vorstellen, dass viele hierher eine Lösung finden.

Um dies zu tun, können Sie überprüfen, ob die Eingänge einen oder mehrere Werte haben:

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

Ich benutze dies selbst, um in meinem Anmeldeformular nach Werten zu suchen, wenn es geladen ist, um die Senden-Schaltfläche zu aktivieren. Der Code ist für jQuery gedacht, kann aber bei Bedarf leicht geändert werden.

1
S.Lund

Ich hatte auch das gleiche Problem, dass das Label kein automatisches Ausfüllen von Filmen erkannte und die Animation zum Verschieben des Labels auf dem Fülltext überlappte. Diese Lösung funktionierte für mich.

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

Ich hatte das gleiche Problem und habe diese Lösung geschrieben.

Beim Abruf der Seite werden alle Eingabefelder abgefragt (ich habe 10 Sekunden eingestellt, aber Sie können diesen Wert einstellen).
Nach 10 Sekunden stoppt das Abfragen jedes Eingabefelds und es beginnt nur das Abfragen der fokussierten Eingabe (falls vorhanden) . Es stoppt, wenn Sie die Eingabe verwischen, und startet erneut, wenn Sie eine Fokussierung vornehmen.

Auf diese Weise können Sie nur abfragen, wenn sie wirklich benötigt werden und nur bei einer gültigen Eingabe.

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

Es funktioniert nicht ganz gut, wenn Sie mehrere Werte automatisch eingefügt haben. Es könnte jedoch die Suche nach jeder Eingabe im aktuellen Formular verbessert werden.

So etwas wie:

// 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

Aus meiner persönlichen Erfahrung funktioniert der unten stehende Code gut mit Firefox IE und Safari, funktioniert aber nicht sehr gut bei der Auswahl von Autocomplete in Chrom.

function check(){
clearTimeout(timeObj);
 timeObj = setTimeout(function(){
   if($('#email').val()){
    //do something
   }
 },1500);
}

$('#email').bind('focus change blur',function(){
 check();
});

Der folgende Code funktioniert besser, da er jedes Mal ausgelöst wird, wenn der Benutzer auf das Eingabefeld klickt. Von dort aus können Sie überprüfen, ob das Eingabefeld leer ist oder nicht. 

$('#email').bind('click', function(){
 check();
});
0
roger

Meine Lösung ist:

    $.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

Nach Recherchen besteht das Problem, dass Webkit-Browser das Änderungsereignis bei der automatischen Vervollständigung nicht auslösen. Meine Lösung bestand darin, die von Webkit hinzugefügte Autofill-Klasse zu erhalten und ein Änderungsereignis auszulösen.

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

Hier ist ein Link zum Thema Chrom. https://bugs.chromium.org/p/chromium/issues/detail?id=636425

0
Cvetan Himchev

Wenn Sie nur feststellen möchten, ob das automatische Ausfüllen verwendet wurde oder nicht, anstatt genau zu wissen, wann und in welchem ​​Feld das automatische Ausfüllen verwendet wurde, können Sie einfach ein ausgeblendetes Element hinzufügen, das automatisch gefüllt wird, und dann prüfen, ob dies geschieht enthält einen beliebigen Wert. Ich verstehe, dass dies möglicherweise nicht das ist, was viele Leute interessieren. Stellen Sie das Eingabefeld mit einem negativen TabIndex und mit absoluten Koordinaten gut außerhalb des Bildschirms ein. Es ist wichtig, dass die Eingabe Teil des gleichen Formulars ist wie der Rest der Eingabe. Sie müssen einen Namen verwenden, der von Auto-fill (zB "secondname") abgerufen wird.

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';

Hängen Sie diese Eingabe an das Formular an und überprüfen Sie den Wert beim Senden des Formulars.

0
bornSwift

Ich habe es mit Chrome geschafft mit:

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

Ich habe das Unschärfe-Ereignis für den Benutzernamen verwendet, um zu überprüfen, ob das Feld "pwd" automatisch ausgefüllt wurde.

 $('#userNameTextBox').blur(function () {
        if ($('#userNameTextBox').val() == "") {
            $('#userNameTextBox').val("User Name");
        }
        if ($('#passwordTextBox').val() != "") {
            $('#passwordTextBoxClear').hide(); // textbox with "Password" text in it
            $('#passwordTextBox').show();
        }
    });

Dies funktioniert für IE und sollte für alle anderen Browser funktionieren (ich habe nur IE geprüft)

0

Dies ist eine Lösung für Browser mit webkit render engine ..__ Wenn das Formular automatisch ausgefüllt wird, erhalten die Eingaben die Pseudoklasse: -webkit-autofill- (zB Eingabe: -webkit-autofill {.. .}). Dies ist also die Kennung, die Sie über JavaScript überprüfen müssen.

Lösung mit einigen Testformularen:

<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>

Und 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);

});

Problem beim Laden der Seite ist Passwortwert, auch Länge. Dies liegt an der Sicherheit des Browsers. Auch das timeout ist darauf zurückzuführen, dass der Browser das Formular nach einiger Zeit ausfüllt. 

Dieser Code fügt den gefüllten Eingaben die Klasse auto_filled hinzu. Ich habe auch versucht, den Eingabetypkennwortwert oder die Länge zu überprüfen, aber es hat funktioniert, nachdem ein Ereignis auf der Seite aufgetreten ist. Also habe ich versucht, ein Ereignis auszulösen, aber ohne Erfolg. Für jetzt ist dies meine Lösung . Viel Spaß! 

0
Adam Šipický

Hier ist die CSS-Lösung vom Klarna UI-Team. Sehen Sie ihre Nice-Implementierung hier resource

Funktioniert gut für mich.

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

Does scheint eine Lösung dafür zu sein, die nicht auf Abfragen angewiesen ist (zumindest für Chrome). Es ist fast so hackig, aber ich denke, ist geringfügig besser als die globale Umfrage.

Stellen Sie sich das folgende Szenario vor:

  1. Der Benutzer fängt an, Feld1 auszufüllen

  2. Der Benutzer wählt einen Vorschlag für die automatische Vervollständigung aus, der die Felder field2 und field3 automatisch ausfüllt

Lösung: Registrieren Sie eine Onblur-Funktion für alle Felder, die mithilfe des folgenden jQuery-Snippets $ (': - webkit-autofill') das Vorhandensein von automatisch ausgefüllten Feldern prüft.

Dies ist nicht unmittelbar, da es verzögert wird, bis der Benutzer field1 verwischt, aber er ist nicht auf globales Polling angewiesen. Daher ist IMO eine bessere Lösung.

Da durch Drücken der Eingabetaste ein Formular gesendet werden kann, benötigen Sie möglicherweise auch einen entsprechenden Handler für onkeypress.

Alternativ können Sie die globale Abfrage verwenden, um $ (': - webkit-autofill') zu überprüfen.

0
Dan D