Обнаружение автозаполнения браузера

Как вы узнаете, что браузер автоматически заполнил текстовое поле? Особенно с полями имени пользователя и пароля, которые автоматически заполняются при загрузке страницы.

Мой первый вопрос: когда это происходит в последовательности загрузки страницы? Это до или после document.ready?

Во-вторых, как я могу использовать логику, чтобы узнать, произошло ли это? Это не то, что я хочу, чтобы это не произошло, просто подключитесь к событию. Предпочтительно что-то вроде этого:

if (autoFilled == true) {

} else {

}

Если возможно, мне бы хотелось увидеть jsfiddle, показывающий ваш ответ.

Возможные дубликаты

Событие DOM для автозаполнения пароля браузера?

События, связанные с автозаполнением браузера и Javascript

- Оба эти вопроса на самом деле не объясняют, какие события запускаются, они просто постоянно перепроверяют текстовое поле (это не полезно для производительности!).

Ответ 1

Проблема в том, что автозаполнение обрабатывается по-разному разными браузерами. Некоторые отправляют событие изменения, некоторые - нет. Поэтому почти невозможно подключить событие, которое запускается, когда браузер автоматически заполняет поле ввода.

  • Изменить триггер событий для разных браузеров:

    • Для полей имени пользователя/пароля:

      • Firefox 4, IE 7 и IE 8 не отправляют событие изменения.
      • Safari 5 и Chrome 9 отправляют событие изменения.
    • Для других полей формы:

      • IE 7 и IE 8 не отправляют событие изменения.
      • Firefox 4 отправляет событие изменения изменений, когда пользователи выбирают значение из списка предложений и табуляции вне поля.
      • Chrome 9 не отправляет событие изменения.
      • Safari 5 отправляет событие изменения.

Вам лучше всего либо отключить автозаполнение формы, используя autocomplete="off" в вашей форме или опросе через регулярный интервал, чтобы узнать, заполнено ли оно.

Для вашего вопроса о том, заполняется ли он или раньше документа. он снова меняется от браузера к браузеру и даже версии к версии. Для полей имени пользователя/пароля только при выборе поля имени пользователя заполняется. Таким образом, у вас будет очень грязный код, если вы попытаетесь подключиться к любому событию.

Вы можете хорошо прочитать это ЗДЕСЬ

Ответ 2

Решение для браузеров WebKit

В документах MDN для псевдо-класса CSS : - webkit-autofill:

Псевдокласс класса -webkit-autofill сопоставляется, когда элемент имеет свое значение, авторизованное браузером

Мы можем определить правило css перехода void в желаемом элементе <input> после его :-webkit-autofill ed. Затем JS сможет подключиться к событию animationstart.

Кредиты команде Klarna UI. См. Их замечательную реализацию здесь:

Ответ 3

Это работает для меня в последних версиях Firefox, Chrome и Edge:

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

Ответ 4

На всякий случай кто-то ищет решение (так же, как и я был сегодня), чтобы прослушать изменение автозаполнения браузера, вот настраиваемый метод 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!");
});

Ответ 5

Для автозаполнения google chrome это сработало для меня:

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

Ответ 6

Я много читал об этой проблеме и хотел найти очень быстрое решение, которое мне помогло.

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

где inputBackgroundNormalState для моего шаблона - "rgb (255, 255, 255)".

Таким образом, в основном, когда браузеры применяют автозаполнение, они имеют тенденцию указывать, что ввод автоматически заполняется путем применения к нему другого (раздражающего) желтого цвета.

Изменение: это будет работать для каждого браузера

Ответ 7

К сожалению, единственный надежный способ проверить этот кросс-браузер - опросить вход. Чтобы сделать его отзывчивым, также слушайте события. Chrome начал скрывать значения автозаполнения из javascript, требующие взлома.

  • Опросите каждую половину-треть секунды (в большинстве случаев не нужно быть мгновенным)
  • Запустите событие изменения с помощью 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);
    });
    

Ответ 8

Существует новый компонент polyfill для решения этой проблемы в github. Посмотрите autofill-event. Просто нужно подключить его, а voilà, автозаполнение работает, как ожидалось.

bower install autofill-event

Ответ 9

Мое решение:

Слушайте change события, как обычно, и на загрузке содержимого DOM, выполните следующее:

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

Это вызовет события изменения для всех полей, которые не являются пустыми, прежде чем пользователь сможет их редактировать.

Ответ 10

Я также столкнулся с той же проблемой, когда label не обнаруживал автозаполнение, и анимация перемещения метки при заполнении текста перекрывалась, и это решение работало для меня.

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

Ответ 11

Я искал похожую вещь. Только Chrome... В моем случае div обертки должен был знать, было ли заполнено поле ввода. Так что я мог бы дать ему дополнительные CSS, как это делает Chrome в поле ввода, когда он автоматически заполняет его. Посмотрев на все ответы выше, мое комбинированное решение было следующим:

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

Ответ 12

Я знаю, что это старый поток, но я могу себе представить, что многие приходят к решению этого вопроса здесь.

Для этого вы можете проверить, имеет ли вход (-ы) значение (-ы):

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

Я использую это самостоятельно, чтобы проверить значения в моей форме входа, когда он загружен, чтобы включить кнопку отправки. Код создан для jQuery, но при необходимости его легко изменить.

Ответ 13

На хроме вы можете обнаружить поля автозаполнения с помощью настроек специального правила 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"))

Ответ 14

У меня есть идеальное решение для этого вопроса, попробуйте этот фрагмент кода.
Демо здесь

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>

Ответ 15

Вот CSS-решение, взятое у команды Klarna UI. Смотрите их хорошую реализацию здесь ресурс

У меня отлично работает.

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

Ответ 16

Я использовал это решение для той же проблемы.

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

Ответ 17

Это решение для браузеров с движком рендеринга webkit. Когда форма заполнена автоматически, входные данные получат псевдокласс : -webkit-autofill- (например, 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);

});

Проблема при загрузке страницы - получить значение пароля, даже длину. Это потому, что безопасность браузера. Также тайм-аут, потому что браузер будет заполнять форму через некоторое время.

Этот код добавит класс auto_filled к заполненным входам. Кроме того, я попытался проверить значение пароля ввода или его длину, но это сработало сразу после того, как произошло какое-то событие на странице. Поэтому я попытался вызвать какое-то событие, но безуспешно. Пока это мое решение. Наслаждайтесь!

Ответ 18

Я использовал событие размытия на имени пользователя, чтобы проверить, было ли поле 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)

Ответ 19

У меня была та же проблема, и я написал это решение.

Он начинает опрос в каждом поле ввода при загрузке страницы (я установил 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);
});

Ответ 20

Если вы хотите только определить, использовалась ли автоматическая заливка или нет, вместо того, чтобы точно определять, когда и к какой области автозаполнения было использовано, вы можете просто добавить скрытый элемент, который будет автоматически заполнен, а затем проверьте, содержит ли это значение. Я понимаю, что это может быть не так, как многие заинтересованы. Установите поле ввода с отрицательным tabIndex и с абсолютными координатами, расположенными далеко от экрана. Важно, чтобы вход был частью той же формы, что и остальная часть ввода. Вы должны использовать имя, которое будет загружено с помощью автозаполнения (например, "второе имя" ).

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

Добавьте этот ввод в форму и проверьте его значение на форме submit.

Ответ 21

Кажется, что это решение, которое не полагается на опрос (по крайней мере, для Chrome). Это почти так же хакерски, но я думаю, что это немного лучше, чем глобальный опрос.

Рассмотрим следующий сценарий:

  • Пользователь начинает заполнять поле1

  • Пользователь выбирает предложение автозаполнения, которое автоматически заполняет поле2 и поле3

Решение: зарегистрируйте onblur во всех полях, которые проверяют наличие заполненных автоматически полей через следующий фрагмент jQuery $(': - webkit-autofill')

Это не будет немедленно, так как оно будет отложено до тех пор, пока пользователь не размывает поле1, но он не полагается на глобальный опрос, поэтому IMO, это лучшее решение.

Тем не менее, поскольку нажатие клавиши ввода может отправить форму, вам также может понадобиться соответствующий обработчик для onkeypress.

В качестве альтернативы вы можете использовать глобальный опрос для проверки $(': - webkit-autofill')

Ответ 22

Из моего личного опыта приведенный ниже код хорошо работает с IE Firefox и сафари, но не очень хорошо работает при сборке автозаполнения в хроме.

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

Ответ 23

Мне удалось хром с:

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

Ответ 24

Мое решение:

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

Ответ 25

После исследования проблема заключается в том, что браузер webkit не запускает событие изменения на автозаполнение. Мое решение состояло в том, чтобы получить класс автозаполнения, который добавляет веб-кит и запускает событие изменения самостоятельно.

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

Вот ссылка на проблему в хроме. https://bugs.chromium.org/p/chromium/issues/detail?id=636425

Ответ 27

попробуйте в CSS

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