Wykrywanie autouzupełniania przeglądarki


165

Skąd wiesz, czy przeglądarka automatycznie wypełniła pole tekstowe? Zwłaszcza w przypadku pól nazwy użytkownika i hasła, które wypełniają się automatycznie podczas ładowania strony.

Moje pierwsze pytanie brzmi: kiedy to się dzieje w sekwencji ładowania strony? Czy to jest przed czy po dokumencie. Już?

Po drugie, jak mogę użyć logiki, aby dowiedzieć się, czy tak się stało? To nie jest tak, że chcę temu zapobiec, po prostu podłącz się do zdarzenia. Najlepiej coś takiego:

if (autoFilled == true) {

} else {

}

Jeśli to możliwe, chciałbym zobaczyć jsfiddle pokazujący twoją odpowiedź.

Możliwe duplikaty

Zdarzenie DOM dla autouzupełniania hasła przeglądarki?

Zdarzenia wyzwalane przez autouzupełnianie przeglądarki i JavaScript

- Oba te pytania tak naprawdę nie wyjaśniają, jakie zdarzenia są wyzwalane, po prostu ciągle sprawdzają pole tekstowe (nie jest to dobre dla wydajności!).


1
Sprawdzanie zajmuje kilka mikrosekund, podczas gdy interwał będzie uruchamiał sprawdzanie co około 100 milisekund ... jak to w ogóle wpłynie na wydajność? Gdyby istniało zdarzenie uruchomione przez przeglądarkę, jestem pewien, że by go użyli.
Esailija,

Rozumiem, co masz na myśli, ale to zależy od pierwszej części mojego pytania, czy JavaScript jest w ogóle świadomy zmiany, która właśnie zaszła (np. Przed document.ready)
Undefined

1
NAJLEPSZYM rozwiązaniem dla Chrome / WebKit jest użycie selektora DOM: document.querySelectorAll ('input: -webkit-autofill'); po krótkim opóźnieniu setTimeout (... kod tutaj ... 250);
ChrisN

Zasadniczo chcę automatycznie logować użytkownika, jeśli jest automatycznie wypełniany, szalenie irytujące, aby zalogować się ponownie, gdy automatycznie się wyloguje.
Muhammad Umer

@ChrisN Twój komentarz dał mi (proste) rozwiązanie. Jednak nie uważam tego za odpowiedź! Opublikuj go jako jedną osobę i pinguj, abym mógł zagłosować za nią w podziękowaniu.
Ethan Kaminski,

Odpowiedzi:


123

Problem polega na tym, że autouzupełnianie jest obsługiwane inaczej przez różne przeglądarki. Niektórzy wysyłają zdarzenie zmiany, inni nie. Dlatego prawie niemożliwe jest podpięcie się do zdarzenia, które jest wyzwalane, gdy przeglądarka automatycznie uzupełnia pole wejściowe.

  • Zmień wyzwalacz zdarzenia dla różnych przeglądarek:

    • W przypadku pól nazwy użytkownika / hasła:

      1. Firefox 4, IE 7 i IE 8 nie wywołują zdarzenia zmiany.
      2. Safari 5 i Chrome 9 wysyłają zdarzenie zmiany.
    • W przypadku innych pól formularza:

      1. IE 7 i IE 8 nie wysyłają zdarzenia zmiany.
      2. Firefox 4 wywołuje zdarzenie zmiany zmiany, gdy użytkownicy wybiorą wartość z listy sugestii i wyjdą z pola.
      3. Chrome 9 nie wysyła zdarzenia zmiany.
      4. Safari 5 wysyła zdarzenie zmiany.

Najlepszą opcją jest wyłączenie autouzupełniania dla formularza autocomplete="off"używanego w formularzu lub regularna ankieta w celu sprawdzenia, czy jest wypełniona.

W przypadku pytania o to, czy jest on wypełniony w dokumencie, czy przed nim. Już teraz różni się w zależności od przeglądarki, a nawet wersji. W przypadku pól nazwy użytkownika / hasła tylko wtedy, gdy wybierzesz nazwę użytkownika, pole hasła jest wypełnione. Więc w sumie miałbyś bardzo niechlujny kod, jeśli spróbujesz dołączyć do dowolnego wydarzenia.

Możesz dobrze przeczytać o tym TUTAJ


26
Pamiętaj, że istnieje różnica między autouzupełnianiem a autouzupełnianiem. OP odnosi się w szczególności do przeglądarek wypełniających zapisane dane logowania podczas ładowania strony.
Robbert

2
Zwykły hack to punkt odniesienia w jakiejś ważnej części strony. Zdarzenie jest wyzwalane, gdy mysz użytkownika kieruje się w stronę przycisku lub czegoś podobnego.
Bryce

1
@Bryce Osobiście wybrałbym zdarzenie „rozmycie”, ponieważ autouzupełnianie jest czymś, co dzieje się po wejściu do obszaru wprowadzania. Oczywiście nie jest to idealne rozwiązanie, ale jako rozwiązanie zastępcze dla przeglądarek wymienionych powyżej może być bardzo pomocne
JakeJ

Nie zapomnij o inputwydarzeniu. To właśnie uruchamia Chrome podczas autouzupełniania (i prawdopodobnie również autouzupełniania, jeśli Chrome to ma; zawsze wyłączam te rzeczy).
TJ Crowder,

Zobacz moją odpowiedź w jednym wierszu, jeśli chcesz tylko wiedzieć, czy wartość w polu tekstowym została wypełniona przez autouzupełnianie Google Chrome.
ThdK

71

Rozwiązanie dla przeglądarek WebKit

Z dokumentacji MDN dla pseudoklasy CSS -webkit-autofill :

Pseudo-klasa: -webkit-autofill CSS pasuje, gdy element ma swoją wartość automatycznie wypełnioną przez przeglądarkę

Możemy zdefiniować regułę css przejścia void na żądanym <input>elemencie po jego :-webkit-autofilledycji. JS będzie wtedy mógł podłączyć się doanimationstart zdarzenia.

Podziękowania dla zespołu Klarna UI . Zobacz ich fajną realizację tutaj:


1
to zdecydowanie najlepsze rozwiązanie! Uznanie dla Lew tutaj za to. Dzięki za udostępnienie rozwiązania Klarna UI ... nic innego nie działało, dopóki tego nie znalazłem. Life Saver!
Braden Rockwell Napier

1
Oprócz reguł CSS potrzebne są również klatki kluczowe tutaj github.com/klarna/ui/blob/v4.10.0/Field/styles.scss#L181-L189
user1069816

To działało bez zarzutu! Musi się trochę pobawić, aby znaleźć dokładne podejście. Dziękuję zespołowi Klarna
pritesh

18

Działa to w przypadku mnie w najnowszych przeglądarkach Firefox, Chrome i Edge:

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

6
'input'! To było dla mnie najłatwiejsze rozwiązanie, ale testowałem tylko pod kątem autouzupełniania, a nie autouzupełniania.
GreenRaccoon

rozmycie nie działa u mnie z niektórymi dodatkami z
funkcją

Wejście będzie wyzwalane przy każdym naciśnięciu klawisza. Jeśli wykonujesz połączenie z serwerem, może się ono często uruchamiać.
RiZKiT

Świetne rozwiązanie! Ta kombinacja zdarzeń rozwiązuje problem z wypełnianiem przez użytkownika i autouzupełnianiem przez przeglądarkę.
Petr Hladík

17

W przypadku autouzupełniania Google Chrome działało to dla mnie:

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

U mnie też się udało. Wypróbowałem setki rozwiązań i nikt nie działał. Dziękuję bardzo, oszczędzaj mój dzień i cały czas szukałem rozwiązania.
perozzo

4
to podejście powoduje wyświetlenie błędu: „Błąd składni, nierozpoznane wyrażenie: nieobsługiwane pseudo: -webkit-autofill” w innych przeglądarkach (próbowałem na Firefoksie)
anvita surapaneni

1
Nie działa na chrome tak dobrze, jak w 2020 r., Również zgłasza błąd nierozpoznane wyrażenie: nieobsługiwane pseudo: -webkit-autofill
Leo

15

Na wypadek, gdyby ktoś szukał rozwiązania (tak jak ja dzisiaj), aby wysłuchać zmiany autouzupełniania przeglądarki, oto niestandardowa metoda jquery, którą stworzyłem, aby uprościć proces dodawania odbiornika zmian do wejścia:

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

Możesz to nazwać tak:

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

1
Z jakiegoś powodu ten kod nie działa na przekierowaniu strony (kiedy wylogowuję się z aplikacji i jestem przekierowywany do strony logowania, gdzie następuje autouzupełnianie). Chociaż działa przy odświeżaniu strony.
VishwaKumar

1
wygląda na całkiem mobilny osuszacz baterii: /
Stefan Fisk

@StefanFisk - Naprawdę nie. Prosty powtarzający się licznik czasu ustawiony na poziomie JS strony przeglądarki nie wystarczy, aby obniżyć poziom naładowania baterii, ponieważ na większości stron internetowych dzieje się tak wiele… Naprawdę myślisz, że google.com nie ustawia żadnych powtarzających się liczników? Jaka byłaby wada w zarządzaniu energią, gdybym mógł po prostu zaprogramować w JS stronę internetową, która
wyczerpuje

15

Dużo czytałem o tym problemie i chciałem zapewnić bardzo szybkie obejście, które mi pomogło.

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

gdzie inputBackgroundNormalStatedla mojego szablonu jest „rgb (255, 255, 255)”.

Zasadniczo, gdy przeglądarki stosują autouzupełnianie, mają tendencję do wskazywania, że ​​dane wejściowe są automatycznie uzupełniane, stosując inny (irytujący) żółty kolor na wejściu.

Edycja: to działa dla każdej przeglądarki


Świetne myślenie!
moto

7

Niestety, jedynym niezawodnym sposobem sprawdzenia tej przeglądarki jest sprawdzenie danych wejściowych. Aby był responsywny, słuchaj również wydarzeń. Chrome zaczął ukrywać wartości automatycznego wypełniania przed javascriptem, który wymaga hakowania.

  • Sondaż co pół do jednej trzeciej sekundy (w większości przypadków nie musi być natychmiastowy)
  • Wywołaj zdarzenie zmiany za pomocą JQuery, a następnie wykonaj logikę w funkcji nasłuchującej zdarzenia zmiany.
  • Dodaj poprawkę dla ukrytych wartości hasła autouzupełniania 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);
    });

6

Na githubie pojawił się nowy składnik polyfill, który rozwiązuje ten problem. Spójrz na zdarzenie autouzupełniania . Wystarczy go zainstalować i voilà, autouzupełnianie działa zgodnie z oczekiwaniami.

bower install autofill-event

To działało świetnie z formularzami niestandardowymi jQuery. Właśnie go upuściłem i moje niestandardowe listy wyboru działały świetnie z autouzupełnianiem.
Chris Bloom,

6

Moje rozwiązanie:

Odsłuchaj changezdarzenia w normalny sposób, a po załadowaniu treści DOM zrób to:

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

Spowoduje to uruchomienie zdarzeń zmian dla wszystkich pól, które nie są puste, zanim użytkownik będzie mógł je edytować.


Idealny. Pierwsze rozwiązanie, które znalazłem pracując z Chrome!
Rid Iculous

3
To naprawdę @RidIculous, jak proste mogą być niektóre rozwiązania.
Camilo Martin

3
Ale elem.val () zwraca pusty ciąg dla automatycznie wypełnianych pól haseł w chrome :(
Hemant_Negi

@Hemant_Negi Czy i tak Chrome nie wysyła zdarzenia zmiany? Popraw mnie, jeśli się mylę. Używam LastPass i jestem zbyt leniwy, aby go wyłączyć, aby sprawdzić, czy działa również bez.
Camilo Martin

1
Tak, zdarzenie zmiany wysyłki chrome, ale gdy próbuję pobrać wartość, zwraca ona pustą.
Hemant_Negi

4

Napotkałem również ten sam problem, w którym etykieta nie wykryła autouzupełniania, a animacja przesuwającej się etykiety przy wypełnianiu tekstu nakładała się i to rozwiązanie działało dla mnie.

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

To jest pomocne.
rustyshackleford

Dokładnie to, czego potrzebowałem :)
Dabrule

4

Szukałem podobnej rzeczy. Tylko Chrome ... W moim przypadku opakowujący element div musiał wiedzieć, czy pole wejściowe zostało wypełnione automatycznie. Mogę więc dodać dodatkowe css, tak jak robi to Chrome w polu wejściowym, gdy automatycznie je wypełnia. Patrząc na wszystkie powyższe odpowiedzi, moje połączone rozwiązanie było następujące:

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

Kod HTML, aby to zadziałał, byłby

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

3

Wiem, że to stary wątek, ale wyobrażam sobie, że wielu przychodzi tutaj, aby znaleźć rozwiązanie tego problemu.

Aby to zrobić, możesz sprawdzić, czy dane wejściowe mają wartości za pomocą:

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

Używam tego osobiście do sprawdzania wartości w moim formularzu logowania po załadowaniu, aby włączyć przycisk przesyłania. Kod jest przeznaczony dla jQuery, ale w razie potrzeby można go łatwo zmienić.


1
Ten kod działa świetnie, jeśli zaktualizujesz trzecią linię do($("#inputID:-webkit-autofill").val().length > 0) {
Hector

3

Jest to rozwiązanie dla przeglądarek z silnikiem renderującym webkit . Gdy formularz jest wypełniany automatycznie, dane wejściowe otrzymają pseudoklasę : -webkit-autofill- (np. Input: -webkit-autofill {...}). Więc to jest identyfikator, który musisz sprawdzić za pomocą JavaScript.

Rozwiązanie z jakimś formularzem testowym:

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

I 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 podczas ładowania strony to uzyskanie wartości hasła, nawet długości. Wynika to z bezpieczeństwa przeglądarki. Również limit czasu , ponieważ przeglądarka wypełni formularz po pewnym czasie.

Ten kod doda klasę auto_filled do wypełnionych danych wejściowych. Próbowałem również sprawdzić wartość lub długość hasła wejściowego, ale zadziałało to po jakimś zdarzeniu na stronie. Próbowałem więc wywołać jakieś zdarzenie, ale bezskutecznie. Na razie to moje rozwiązanie. Cieszyć się!


Oto aktualna odpowiedź.
Ben Racicot

Wypróbowałem to rozwiązanie i bardzo dobrze mi się udało. Dziękuję Ci bardzo.
Marcus Crisostomo

2

Mam idealne rozwiązanie na to pytanie, wypróbuj ten fragment kodu.
Demo jest tutaj

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

W Chrome możesz wykryć pola autouzupełniania, ustawiając specjalną regułę css dla elementów automatycznie wypełnianych, a następnie sprawdzając za pomocą javascript, czy do elementu zastosowano tę regułę.

Przykład:

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

Oto rozwiązanie CSS zaczerpnięte z zespołu Klarna UI. Zobacz ich fajną realizację tutaj zasób

U mnie działa dobrze.

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

1

Użyłem tego rozwiązania do tego samego problemu.

Kod HTML powinien zmienić się na:

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

a kod jQuery powinien znajdować się w document.ready:

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

0

Użyłem zdarzenia rozmycia w nazwie użytkownika, aby sprawdzić, czy pole pwd zostało automatycznie wypełnione.

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

Działa to dla IE i powinno działać dla wszystkich innych przeglądarek (sprawdziłem tylko IE)


@ChrisN Testowałem swoje rozwiązanie w IE, przeglądarki inaczej obsługują zdarzenia javascsript. Moje rozwiązanie jest proste i łatwe do odczytania i jest przeznaczone dla jednej z trudniejszych przeglądarek do kodowania.
Bridget Arrington

1
W końcu otrzymuję to samo rozwiązanie: blurwydarzenie. I zastosować tę samą funkcję dla changei blurimprezy i to działało świetnie. Proste rozwiązanie bez dodatkowych bibliotek.
Paulo Sprawdź

0

Miałem ten sam problem i napisałem to rozwiązanie.

Rozpoczyna odpytywanie w każdym polu wejściowym podczas ładowania strony (ustawiłem 10 sekund, ale możesz dostroić tę wartość).
Po 10 sekundach przerywa odpytywanie w każdym polu wejściowym i rozpoczyna odpytywanie tylko na aktywnym wejściu (jeśli jest). Zatrzymuje się, gdy rozmazasz dane wejściowe i ponownie zaczyna się, gdy je wyostrzysz.

W ten sposób sondujesz tylko wtedy, gdy jest to naprawdę potrzebne i tylko na poprawnym wejściu.

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

Nie działa to całkiem dobrze, gdy masz wiele wartości wstawianych automatycznie, ale można je dostosować, szukając każdego wejścia w bieżącym formularzu.

Coś jak:

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

Jeśli chcesz tylko wykryć, czy autouzupełnianie zostało użyte, czy nie, zamiast dokładnie wykrywać, kiedy i do którego pola zostało użyte automatyczne wypełnianie, możesz po prostu dodać ukryty element, który zostanie automatycznie wypełniony, a następnie sprawdzić, czy to zawiera dowolną wartość. Rozumiem, że może to nie być coś, czym wielu ludzi jest zainteresowanych. Ustaw pole wejściowe z ujemnym tabIndex i współrzędnymi bezwzględnymi dobrze z ekranu. Ważne jest, aby dane wejściowe były częścią tego samego formularza, co reszta danych wejściowych. Musisz użyć nazwy, która zostanie przejęta przez autouzupełnianie (np. „Drugie imię”).

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

Dołącz te dane wejściowe do formularza i sprawdź jego wartość podczas przesyłania formularza.


0

Tam nie wydaje się być rozwiązaniem na to, że nie opiera się na odpytywanie (przynajmniej dla Chrome). Jest prawie tak samo hakerski, ale myślę, że jest nieznacznie lepszy niż sondaże globalne.

Rozważ następujący scenariusz:

  1. Użytkownik zaczyna wypełniać pole 1

  2. Użytkownik wybiera sugestię autouzupełniania, która automatycznie wypełnia pola 2 i 3

Rozwiązanie: zarejestruj onblur we wszystkich polach, które sprawdzają obecność pól automatycznie wypełnianych za pomocą następującego fragmentu kodu jQuery $ (': - webkit-autofill')

Nie będzie to natychmiastowe, ponieważ zostanie opóźnione do momentu rozmycia przez użytkownika pola 1, ale nie polega na globalnym odpytywaniu, więc IMO jest lepszym rozwiązaniem.

To powiedziawszy, ponieważ naciśnięcie klawisza Enter może wysłać formularz, możesz również potrzebować odpowiedniego programu obsługi dla naciśnięcia klawisza.

Alternatywnie możesz użyć globalnego odpytywania, aby sprawdzić $ (': - webkit-autofill')


0

Z mojego osobistego doświadczenia wynika, że ​​poniższy kod działa dobrze z Firefoxem IE i Safari, ale nie działa zbyt dobrze przy wybieraniu autouzupełniania w Chrome.

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

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

Poniższy kod działa lepiej, ponieważ będzie się uruchamiał za każdym razem, gdy użytkownik kliknie pole wejściowe i stamtąd możesz sprawdzić, czy pole jest puste, czy nie.

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

0

Udało mi się na chrome z:

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

Nie jestem pewien, kiedy dokładnie działa autouzupełnianie Chrome, ale w $ ('input, select'). On ('focusin', function (evt) {...}); Otrzymuję już automatycznie wypełnione wartości dla wszystkich pól.
mirek

Może nowa wersja?
Antoine O

0

Moje rozwiązanie to:

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

Wyjaśnienie twojego rozwiązania mogłoby pomóc
ton

Myślałem, że to oczywiste. Zasadniczo więc chodzi o to, aby kilkakrotnie sprawdzić wartość pola wejściowego. W obecnej implementacji jest to 10 razy z opóźnieniem 100 ms. Więc gdy w ciągu sekund 10 * 1000 = 1s przeglądarka wypełni wartość autouzupełniania, zostanie wywołane wywołanie zwrotne przekazane do autouzupełniania. W obecnym przykładzie po prostu dodaje klasę. Jeśli masz więcej pytań, nie wahaj się i po prostu zapytaj :).
Romick

0

Po przeprowadzeniu badań problem polega na tym, że przeglądarki Webkit nie uruchamiają zdarzenia zmiany podczas autouzupełniania. Moim rozwiązaniem było samodzielne pobranie klasy autouzupełniania, którą dodaje webkit i wyzwolenie zdarzenia zmiany.

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

Oto link do problemu z chromem. https://bugs.chromium.org/p/chromium/issues/detail?id=636425


0

Na przykład, aby wykryć e-mail, próbowałem „przy zmianie” i obserwatora mutacji, ale żaden z nich nie działał. setInterval działa dobrze z automatycznym wypełnianiem LinkedIn (nie ujawnia całego mojego kodu, ale masz pomysł) i działa dobrze z zapleczem, jeśli dodasz tutaj dodatkowe warunki, aby spowolnić AJAX. A jeśli nie ma zmiany w polu formularza, na przykład nie piszą, aby edytować swój e-mail, lastEmail zapobiega bezcelowym pingom AJAX.

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

0

Trudno mi było wykryć automatyczne wypełnianie w przeglądarce Firefox. To jedyne rozwiązanie, które u mnie zadziałało:

Próbny

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

  }); 

W przypadku Chrome używam: if ($(this).css('animation-name') == 'onAutoFillStart')

W przeglądarce Firefox: if ($(this).val() != '')


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.