JS | При нажатии на кнопку скрытия/показа пароля, на поле ввода постоянно срабатывает анимация получения фокуса, даже если поле уже находится в фокусе

Создал форму входа, с выезжающими <label>ми на странице браузера. И, к полю с паролем, добавил "кнопку" Глаза, чтобы показывать и скрывать пароль.

Мне нужно было, что бы при нажатии на Глазик, фокус оставался на поле ввода. Для этого я, в js, в обработчике события, прописал для поля ввода метод focus().

Да, теперь, при нажатии на глаз, мое поле всегда получает фокус. Но, теперь также, при нажатии на Глаз, постоянно срабатывает анимация выезжания <label>а. А если, например, нажимать на само поле ввода (не на Глаз), когда оно в фокусе, то анимация уже не срабатывает, и поле при этом все равно остается в фокусе.

В общем, можно ли сделать так, чтобы, при нажатии на Глазик, постоянно не срабатывала анимация, и чтобы поле, при этом, оставалось в фокусе?

function showPassword() {
  /*
  Получаем наш глаз:
  */
  const eye = document.querySelector('.eye');

  /*
  Получаем поле ввода пароля:
  */
  const input = document.querySelector('.show__password');

  /*
  Прописываем обработчик на изменение
  цвета (добавляем или убираем класс .active),
  по клику на наш глаз:
  */
  eye.addEventListener('click', () => {
    eye.classList.toggle('active');
    /*
    А также, меняем значение атрибута
    type, с password на text:
    */
    if (input.getAttribute('type') === 'password') {
      input.setAttribute('type', 'text');
      input.focus(); /* input.focus() */
      /*
      Или, на оборот:
      */
    } else {
      input.setAttribute('type', 'password');
      input.focus(); /* input.focus() */
    }
  });
}

showPassword();
/*
Размещаем форму в центре,
по горизонтали:
*/
body {
  display: flex;
  justify-content: center;
}

/*
Делаем границу для формы
и задаем ей шрифт
(в свойстве transform: translate(),
с помощью процентного значения,
можно регулировать положение формы,
по высоте):
*/
.form {
  width: 300px;
  transform: translate(0, 110%);
  padding: 32px 32px 0 32px;
  border-radius: 10px;
  box-shadow: 0 4px 16px #ccc;
  font-family: sans-serif;
  letter-spacing: 1px;
  /* расстояние между буквами */
}

/*
Задаем шрифт для самих
полей ввода и для кнопки:
*/
.form__input,
.form__button {
  font-family: sans-serif;
  letter-spacing: 1px;
  font-size: 16px;
}

/*
Заголовок:
*/
.form__title {
  text-align: center;
  margin: 0 0 35px 0;
  font-weight: normal;
  user-select: none;
}

/*
Поле для Email(а):
*/
.form__email {
  position: relative;
  margin: 32px 0 43px 0;
}

/*
Поле для Пароля:
*/
.form__password {
  position: relative;
  transition: .3s;
}

/*
Надписи "Email" и "Пароль":
*/
.form__label {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
  color: #a3a3a3;
  user-select: none;
  transition: 0.3s;
}

/*
Поля ввода:
*/
.form__input {
  width: 100%;
  padding: 1px 0 6px 0;
  border: none;
  border-bottom: 1px solid #e0e0e0;
  background-color: transparent;
  outline: none;
  user-select: none;
  transition: 0.3s;
}

/*
Нижние подчеркивания меняют
цвет, при наведении и фокусировке
на них:
*/
.form__input:focus,
.form__input:hover {
  border-bottom: 1px solid #1a80ba;
}

/*
Кнопка "Войти":
*/
.form__button {
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  margin: 33px 0 35px 0;
  color: #fff;
  background-color: #0071f0;
  outline: none;
  cursor: pointer;
  user-select: none;
  transition: 0.3s;
}

/*
Меняем цвет кнопки,
при наведении и фокусировке
на нее:
*/
.form__button:focus,
.form__button:hover {
  background-color: #055bbd;
}

/*
Глазик:
*/
.eye {
  position: fixed;
  left: 307px;
  top: 173px;
  fill: #bcbcbc;
  cursor: pointer;
  transition: .3s;
  z-index: -0;
}

/*
Реализуем эффект, что бы при
фокусировке подсказки уезжали
наверх:
*/
.form__input:focus~.form__label,
.form__input:not(:placeholder-shown)~.form__label {
  top: -18px;
  font-size: 12px;
}

/*
Меняем цвет подсказок,
при фокусировке:
*/
.form__input:focus~.form__label {
  color: #1a73a8;
}

/*
Класс active добавляется к
нашему глазу в HTML, когда
мы нажимаем на наш глазик.
А, здесь мы прописали стиль
изменения цвета для данного
класса active:
*/
.active {
  fill: #1c85c1;
}
<!--
    Сама наша форма:
    -->
<form action="" class="form">

  <!--
        Заголовок:
        -->
  <h1 class="form__title">Вход</h1>

  <!--
        Поле для ввода Email(а):
        -->
  <div class="form__email">
    <input type="email" class="form__input" placeholder=" " required>
    <label for="" type="email" class="form__label">Email</label>
  </div>

  <!--
        Поле для ввода Пароля:
        -->
  <div class="form__password">
    <input type="password" class="form__input show__password" placeholder=" " required>
    <label for="" class="form__label">Пароль</label>
    <!--
            Картинка глаза:
            -->
    <svg class="eye" width="20" height="20" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
                <path fill-rule="evenodd" clip-rule="evenodd" d="M8 13.078c4.418 0 8-5 8-5s-3.582-5-8-5-8 5-8 5 3.582 5 8 5zm0-2a3 3 0 100-6 3 3 0 000 6zm0-1.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path>
            </svg>
  </div>

  <!--
        Кнопка "Войти":
        -->
  <button class="form__button">Войти</button>

  <script src="js/main.js"></script>

</form>


Ответы (1 шт):

Автор решения: ksa

В общем, можно ли сделать так, чтобы, при нажатии на Глазик, постоянно не срабатывала анимация, и чтобы поле, при этом, оставалось в фокусе?

Предложу такой вариант...

function showPassword() {
  /*
  Получаем наш глаз:
  */
  const eye = document.querySelector('.eye');
  const box = document.querySelector('.form__password');

  /*
  Получаем поле ввода пароля:
  */
  const input = document.querySelector('.show__password');

  /*
  Прописываем обработчик на изменение
  цвета (добавляем или убираем класс .active),
  по клику на наш глаз:
  */
  box.addEventListener('click', e => {
    if (!ok(e)) return;
    eye.classList.toggle('active');
    /*
    А также, меняем значение атрибута
    type, с password на text:
    */
    const v = input.getAttribute('type') === 'password'
      ? 'text'
      : 'password'
    input.setAttribute('type', v);
  });
}
showPassword();
//
function ok(e) {
  if (e.offsetY < 10 || e.offsetY > 20) return false
  if (e.offsetX < 265 || e.offsetX > 295) return false
  return true
}
/*
Размещаем форму в центре,
по горизонтали:
*/
body {
  display: flex;
  justify-content: center;
}

/*
Делаем границу для формы
и задаем ей шрифт
(в свойстве transform: translate(),
с помощью процентного значения,
можно регулировать положение формы,
по высоте):
*/
.form {
  width: 300px;
  transform: translate(0, 110%);
  padding: 32px 32px 0 32px;
  border-radius: 10px;
  box-shadow: 0 4px 16px #ccc;
  font-family: sans-serif;
  letter-spacing: 1px;
  /* расстояние между буквами */
}

/*
Задаем шрифт для самих
полей ввода и для кнопки:
*/
.form__input,
.form__button {
  font-family: sans-serif;
  letter-spacing: 1px;
  font-size: 16px;
}

/*
Заголовок:
*/
.form__title {
  text-align: center;
  margin: 0 0 35px 0;
  font-weight: normal;
  user-select: none;
}

/*
Поле для Email(а):
*/
.form__email {
  position: relative;
  margin: 32px 0 43px 0;
}

/*
Поле для Пароля:
*/
.form__password {
  position: relative;
  transition: .3s;
}

/*
Надписи "Email" и "Пароль":
*/
.form__label {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
  color: #a3a3a3;
  user-select: none;
  transition: 0.3s;
}

/*
Поля ввода:
*/
.form__input {
  width: 100%;
  padding: 1px 0 6px 0;
  border: none;
  border-bottom: 1px solid #e0e0e0;
  background-color: transparent;
  outline: none;
  user-select: none;
  transition: 0.3s;
}

/*
Нижние подчеркивания меняют
цвет, при наведении и фокусировке
на них:
*/
.form__input:focus,
.form__input:hover {
  border-bottom: 1px solid #1a80ba;
}

/*
Кнопка "Войти":
*/
.form__button {
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  margin: 33px 0 35px 0;
  color: #fff;
  background-color: #0071f0;
  outline: none;
  cursor: pointer;
  user-select: none;
  transition: 0.3s;
}

/*
Меняем цвет кнопки,
при наведении и фокусировке
на нее:
*/
.form__button:focus,
.form__button:hover {
  background-color: #055bbd;
}

/*
Глазик:
*/
.eye {
  position: fixed;
  left: 307px;
  top: 173px;
  fill: #bcbcbc;
  cursor: pointer;
  transition: .3s;
  z-index: -0;
}

/*
Реализуем эффект, что бы при
фокусировке подсказки уезжали
наверх:
*/
.form__input:focus~.form__label,
.form__input:not(:placeholder-shown)~.form__label {
  top: -18px;
  font-size: 12px;
}

/*
Меняем цвет подсказок,
при фокусировке:
*/
.form__input:focus~.form__label {
  color: #1a73a8;
}

/*
Класс active добавляется к
нашему глазу в HTML, когда
мы нажимаем на наш глазик.
А, здесь мы прописали стиль
изменения цвета для данного
класса active:
*/
.active {
  fill: #1c85c1;
}
<!--
    Сама наша форма:
    -->
<form action="" class="form">

  <!--
        Заголовок:
        -->
  <h1 class="form__title">Вход</h1>

  <!--
        Поле для ввода Email(а):
        -->
  <div class="form__email">
    <input type="email" class="form__input" placeholder=" " required>
    <label for="" type="email" class="form__label">Email</label>
  </div>

  <!--
        Поле для ввода Пароля:
        -->
  <div class="form__password">
    <input type="password" class="form__input show__password" placeholder=" " required>
    <label for="" class="form__label">Пароль
    <!--
            Картинка глаза:
            -->
      <svg class="eye" width="20" height="20" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
        <path fill-rule="evenodd" clip-rule="evenodd" d="M8 13.078c4.418 0 8-5 8-5s-3.582-5-8-5-8 5-8 5 3.582 5 8 5zm0-2a3 3 0 100-6 3 3 0 000 6zm0-1.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path>
      </svg>
    </label>
  </div>

  <!--
        Кнопка "Войти":
        -->
  <button class="form__button">Войти</button>

  <script src="js/main.js"></script>

</form>

→ Ссылка