Material-design-lite: Autocomplete Bug

Created on 30 Jul 2015  Â·  15Comments  Â·  Source: google/material-design-lite

Sometimes when I load my login page with the form autocompleted, it displays like this:
image

If I click anywhere on the page, it will then "fix" itself.

image

Is this a common bug with anyone else?

Most helpful comment

All 15 comments

Dirty state isn't added by auto-filled values .

I don’t think there’s a way for us to detect if the browser autofill'd values (otherwise you could sniff saved passwords from the user without him having control over that).

There isn't, events are not fired when JS (or the browser itself) modifies values so we are in the dark.

I _believe_ this is one place where ShadowDOM access and observers could help, but not entirely sure. Even if they can help, out of scope for MDL.

One way to detect autofill is as follows:

document.addEventListener('input', function(e) {
console.log('autofilled: ' + e.target.matches(':-webkit-autofill'));
});

This solution works in WebKit and Blink engines.

On Thu, 30 Jul 2015 at 12:53 Jonathan Garbee [email protected]
wrote:

There isn't, events are not fired when JS (or the browser itself) modifies
values so we are in the dark.

I _believe_ this is one place where ShadowDOM access and observers could
help, but not entirely sure. Even if they can help, out of scope for MDL.

—
Reply to this email directly or view it on GitHub
https://github.com/google/material-design-lite/issues/1253#issuecomment-126290051
.

Thanks @PaulKinlan, I’ll take a look if we can incorporate that.

@surma If it only works on a few browsers, we shouldn't.

While it would make the experience better for those, it would then be seen as a "bug" since it also doesn't work on IE and FF.

It will behave the same as it does now on the browsers that do not support the directive. I don’t see any harm. Actually, we are doing something similar with the progress bar, where the animated buffer bar is only visible in Blink and FF.

In any case, this is rather low priority. But we might want to use this opportunity to make an exemplary decision. @sgomes @addyosmani 2cents?

Unless there is a more general fix, I'm happy with us fixing it where possible, as suggested. This is aesthetic, not functional, and we can add similar fixes for other browsers if they're made available.

As well as the overlay issue , there is also the issue of the ugly yellow styling Chrome (and probably other browsers) is placing on the auto-filled fields. It seems they don't allow you to override the style applied with:
input:-webkit-autofill
However via the hack mentioned here:
http://stackoverflow.com/a/19426087

You can fool the browser using a box shadow like this:
input:-webkit-autofill {
-webkit-box-shadow: 0 0 0px 1000px white inset;
}

Which will produce a white background instead of the yellow shown in the screen shots above. This might be worth considering adding to MDL somewhere as you still get UI feedback on the fact the field is auto-fill as Chrome is styling the bottom border as yellow (instead of the default MD blue) so you can tell which form fields were auto-completed even with this hack in place, and without the hack in place the forms look very un-MD.

Edit: If you need to change the text colour as well as the background (if you don't want the default black) then you can also add this to the style:
-webkit-text-fill-color: blue;
(for example).

Was this ever fixed?

@sgomes you say in this thread you will be adding the fix to the project

but @Garbee says here https://github.com/google/material-design-lite/issues/1611 it will not be added

setTimeout(function() {
  $.each($('.mdl-textfield'), function() {
    var input = $(this).find("input");
    var len = input.val().length;
    var type = input.attr("type");

    if (len > 0 || type == "password")
      $(this).addClass("is-dirty");
  });
}, 100);

This works for both text and password fields. One downside is that password fields will always be marked as dirty, empty or not.

i found a solution and it works for me

belove script detect every input with autofilled and add a class name it's parents

$.each($('input:-webkit-autofill'), function() {
    var autofilled = $(this);
        var inputblock = $(this).parent('.input-block')
    $(inputblock).addClass('has-value');
});

i am using my own mdl style, you can change your specific classes, something like that:

$.each($('input:-webkit-autofill'), function() {
    var autofilled = $(this);
        var inputblock = $(this).parent('.mdl-textfield')
    $(inputblock).addClass('is-focused');
});

I adapted the timeout hack for non-jquery and it mostly works, although it's a bit delayed and messes with the font attributes for some reason.

setTimeout(function() {
            const x = document.querySelectorAll(".mdl-textfield__input:-webkit-autofill");
            for (let i = 0; i < x.length; i++) {
                const text_field = x[i].parentElement;

                text_field.classList.add("is-dirty");
            }
        }, 100);

Recently I also faced this problem. I found a way, how to solve it without calling setTimeout(). After some investigation I figured out that the proper solution for me would be a combination of two approaches: css animation event and 'mdl-componentupgraded' event. So I wait untill these two events are fired and then I set 'is-dirty' class. The events can be triggered in a different order, that's why I need to wait for both of them.

So, my solution:

css:

/* Animation is only needed to catch 'animationend' event and with help of it to fix the related autofill bug. 
   That's why 'from' and 'to' section are empty
*/
@keyframes autoFillAnimation {
    from {
    }

    to {
    }
}

.mdl-textfield__input:-webkit-autofill {
    animation-name: autoFillAnimation;
}

javascript:

(function () {
    "use strict";

    // The goal of this script is to fix 'autofill' problem which exists in google chrome browser.
    // The idea of the fix is to add 'is-dirty' class to corresponding html element at the proper moment of time. 
    // 'is-dirty' class should be added right after 'mdl-componentupgraded' from mdl library is fired and browser's 'autofill'-feature is executed.

    // keeps information about fired events grouped by input's id
    var firedEventsDict = {};

    var mdlTextFields = document.querySelectorAll(".mdl-textfield");
    for (let i = 0; i < mdlTextFields.length; i++) {
        var inputEl = mdlTextFields[i].querySelector(".mdl-textfield__input");
        firedEventsDict[inputEl.id] = {
            mdlUpgradedEventFired: false,
            autoFillAnimationEnded: false
        }

        mdlTextFields[i].addEventListener("mdl-componentupgraded", onComponentUpgradedHandler);
        inputEl.addEventListener("animationend", animationEndHandler);
    }

    function onComponentUpgradedHandler(e) {
        firedEventsDict[e.target.MaterialTextfield.input_.id].mdlUpgradedEventFired = true;
        tryToFixAutoFill(e.target.MaterialTextfield.input_);
    }

    function animationEndHandler(e) {
        if (e.animationName === "autoFillAnimation") {
            firedEventsDict[e.target.id].autoFillAnimationEnded = true;
            tryToFixAutoFill(e.target);
        }
    }

    function tryToFixAutoFill(inputEl) {
        // the fix will be called only after two necessary events are fired (mdl-componentupgraded and animationend)
        if (firedEventsDict[inputEl.id].mdlUpgradedEventFired && firedEventsDict[inputEl.id].autoFillAnimationEnded) {
            inputEl.parentElement.classList.add(inputEl.parentElement.MaterialTextfield.CssClasses_.IS_DIRTY);
        }
    }
})();

and the piece of relevant html:

<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
     <input class="mdl-textfield__input" type="text" asp-for="Username">
     <label class="mdl-textfield__label" asp-for="Username" id="OAUTH_LOGIN_name"></label>
     <i class="user"></i>
 </div>
 <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
     <input class="mdl-textfield__input" type="password" asp-for="Password">
     <label class="mdl-textfield__label" asp-for="Password" id="OAUTH_LOGIN_password"></label>
     <i class="lock"></i>
 </div>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

rafaelcorreiapoli picture rafaelcorreiapoli  Â·  3Comments

tleunen picture tleunen  Â·  5Comments

facekapow picture facekapow  Â·  5Comments

lgg picture lgg  Â·  3Comments

samuelcarreira picture samuelcarreira  Â·  4Comments