it-roy-ru.com

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

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

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

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

if (autoFilled == true) {

} else {

}

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

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

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

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

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

132
Undefined

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

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

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

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

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

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

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

Вы можете прочесть об этом ЗДЕСЬ

110
afrin216

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

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

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

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

Кредиты для Кларна UI команды. Посмотрите их реализацию Nice здесь:

44
Lev Kazakov

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

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

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

Для автозаполнения Google Chrome это работает для меня:

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

К сожалению, единственный надежный способ проверить этот кросс-браузер - опросить ввод. Чтобы сделать его отзывчивым, также слушайте события. 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);
    });
    
7
Bucket

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

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

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

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

Правка: это будет работать для каждого браузера 

7
DrNio

В github появился новый компонент polyfill для решения этой проблемы. Посмотрите на автозаполнение-событие . Просто нужно поставить его и вуаля, автозаполнение работает как положено.

bower install autofill-event
6
David

Я искал похожую вещь. Только 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>
4
Julesezaar

Мое решение:

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

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

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

4
Camilo Martin

В chrome вы можете обнаружить поля автозаполнения, установив специальное правило 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"))
2
Pietro Coelho

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

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

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

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

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

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

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

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

1
S.Lund

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

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

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

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

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

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

Мое решение:

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

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

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

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

0
Cvetan Himchev

Если вы хотите только определить, использовалось ли автоматическое заполнение или нет, а не точно определить, когда и в каком поле использовалось автоматическое заполнение, вы можете просто добавить скрытый элемент, который будет заполняться автоматически, а затем проверить, содержит любое значение. Я понимаю, что это может быть не то, что интересует многих людей. Установите поле ввода с отрицательным индексом 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';

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

0
bornSwift

Мне удалось на Chrome с:

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

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

0
Bridget Arrington

Это решение для браузеров с механизмом рендеринга 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);

});

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

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

0
Adam Šipický

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

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

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

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

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

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

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

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

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

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

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

0
Dan D