Home » Javascript » Detecting Browser Autofill

Detecting Browser Autofill

Posted by: admin November 30, 2017 Leave a comment

Questions:

How do you tell if a browser has auto filled a text-box? Especially with username & password boxes that autofill around page load.

My first question is when does this occur in the page load sequence? Is it before or after document.ready?

Secondly how can I use logic to find out if this occurred? Its not that i want to stop this from occurring, just hook into the event. Preferably something like this:

if (autoFilled == true) {

} else {

}

If possible I would love to see a jsfiddle showing your answer.

Possible duplicates

DOM event for browser password autofill?

Browser Autofill and Javascript triggered events

–Both these questions don’t really explain what events are triggered, they just continuously recheck the text-box (not good for performance!).

Answers:

The problem is autofill is handled differently by different browsers. Some dispatch the change event, some don’t. So it is almost impossible to hook onto an event which is triggered when browser autocompletes an input field.

  • Change event trigger for different browsers:

    • For username/password fields:

      1. Firefox 4, IE 7, and IE 8 don’t dispatch the change event.
      2. Safari 5 and Chrome 9 do dispatch the change event.
    • For other form fields:

      1. IE 7 and IE 8 don’t dispatch the change event.
      2. Firefox 4 does dispatch the change change event when users select a value from a list of suggestions and tab out of the field.
      3. Chrome 9 does not dispatch the change event.
      4. Safari 5 does dispatch the change event.

You best options are to either disable autocomplete for a form using autocomplete="off" in your form or poll at regular interval to see if its filled.

For your question on whether it is filled on or before document.ready again it varies from browser to browser and even version to version. For username/password fields only when you select a username password field is filled. So altogether you would have a very messy code if you try to attach to any event.

You can have a good read on this HERE

Questions:
Answers:

Solution for WebKit browsers

From the MDN docs for the :-webkit-autofill CSS pseudo-class:

The :-webkit-autofill CSS pseudo-class matches when an element has its value autofilled by the browser

We can define a void transition css rule on the desired <input> element once it is :-webkit-autofilled. JS will then be able to hook onto the animationstart event.

Credits to the Klarna UI team. See their nice implementation here:

Questions:
Answers:

Just in case someone is looking for a solution (just as I was today), to listen to a browser autofill change, here’s a custom jquery method that I’ve built, just to simplify the proccess when adding a change listener to an input:

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

You can call it like this:

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

Questions:
Answers:

This works for me in the latest Firefox, Chrome, and Edge:

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

Questions:
Answers:

Unfortunately the only reliable way i have found to check this cross browser is to poll the input. To make it responsive also listen to events.
Chrome has started hiding auto fill values from javascript which needs a hack.

  • Poll every half to third of a second ( Does not need to be instant in most cases )
  • Trigger the change event using JQuery then do your logic in a function listening to the change event.
  • Add a fix for Chrome hidden autofill password values.

    $(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);
    });
    
Questions:
Answers:

For google chrome autocomplete, this worked for me:

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

Questions:
Answers:

There is a new polyfill component to address this issue on github. Have a look at autofill-event. Just need to bower install it and voilà, autofill works as expected.

bower install autofill-event

Questions:
Answers:

My solution:

Listen to change events as you would normally, and on the DOM content load, do this:

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

This will fire the change events for all the fields that aren’t empty before the user had a chance to edit them.

Questions:
Answers:

I have perfect solution for this question try this code snippet.
Demo is here

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>

Questions:
Answers:

I know this is an old thread but I can imagine many comes to find a solution to this here.

To do this, you can check if the input(s) has value(s) with:

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

I use this myself to check for values in my login form when it’s loaded to enable the submit button.
The code is made for jQuery but is easy to change if needed.

Questions:
Answers:

i use this solution for same problem.

html code should change to this :

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

and then jQuery code can be in document.ready :

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

});

Questions:
Answers:

On chrome, you can detect autofill fields by settings a special css rule for autofilled elements, and then checking with javascript if the element has that rule applied.

Example:

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

Questions:
Answers:

I used the blur event on the username to check if the pwd field had been auto-filled.

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

This works for IE, and should work for all other browsers (I’ve only checked IE)

Questions:
Answers:

I had the same problem and I’ve written this solution.

It starts polling on every input field when the page is loading (I’ve set 10 seconds but you can tune this value).
After 10 seconds it stop polling on every input field and it starts polling only on the focused input (if one).
It stops when you blur the input and again starts if you focus one.

In this way you poll only when really needed and only on a valid input.

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

It does not work quite well when you have multiple values inserted automatically, but it could be tweaked looking for every input on the current form.

Something like:

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

Questions:
Answers:

If you only want to detect whether auto-fill has been used or not, rather than detecting exactly when and to which field auto-fill has been used, you can simply add a hidden element that will be auto-filled and then check whether this contains any value. I understand that this may not be what many people are interested in. Set the input field with a negative tabIndex and with absolute coordinates well off the screen. It’s important that the input is part of the same form as the rest of the input. You must use a name that will be picked up by Auto-fill (ex. “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';

Append this input to the form and check its value on form submit.

Questions:
Answers:

There does appear to be a solution to this that does not rely on polling (at least for Chrome). It is almost as hackish, but I do think is marginally better than global polling.

Consider the following scenario:

  1. User starts to fill out field1

  2. User selects an autocomplete suggestion which autofills field2 and field3

Solution: Register an onblur on all fields that checks for the presence of auto-filled fields via the following jQuery snippet $(‘:-webkit-autofill’)

This won’t be immediate since it will be delayed until the user blurs field1 but it doesn’t rely on global polling so IMO, it is a better solution.

That said, since hitting the enter key can submit a form, you may also need a corresponding handler for onkeypress.

Alternately, you can use global polling to check $(‘:-webkit-autofill’)

Questions:
Answers:

try in CSS

input:-webkit-autofill {
border-color: #9B9FC4 !important;
}

Questions:
Answers:

From my personal experience, the below code works well with firefox IE and safari, but isn’t working very well at picking autocomplete in chrome.

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

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

Below code works better, because it will trigger each time when user clicks on the input field and from there you can check either the input field is empty or not.

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

Questions:
Answers:

I succeeded on chrome with :

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

Questions:
Answers:

My solution is:

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

Questions:
Answers:

After research the issue is that webkit browsers does not fire change event on autocomplete. My solution was to get the autofill class that webkit adds and trigger change event by myself.

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

Here is a link for the issue in chromium. https://bugs.chromium.org/p/chromium/issues/detail?id=636425