div теряет фокус при нажатии на дочерний элемент, у которого есть фокус - PullRequest
0 голосов
/ 05 августа 2020

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

В случаях, когда у модального окна есть дочерний элемент, на который можно сфокусироваться, модальное окно теряет фокус, я также обработал это в приведенном ниже коде. Эти случаи правильно обрабатываются onFocusLoss, но не onFocusLoss2.

function onClickButton() {
  var modal = document.getElementById('modal');
  modal.style.visibility = 'visible';
  modal.focus();
}

function onFocusLoss() {
  var modal = document.getElementById('modal');
  
  setTimeout(function() {
    var activeEl = document.activeElement;
    
    if (modal !== activeEl && !modal.contains(activeEl)) {
      modal.style.visibility = 'hidden';
    }
  }, 0);
}

function onFocusLoss2() {
  var modal = document.getElementById('modal');
  var activeEl = document.activeElement;
  
  if (modal !== activeEl && !modal.contains(activeEl)) {
    modal.style.visibility = 'hidden';
  }
}
#modal {
  position: fixed;
  visibility: hidden;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 1px solid red;
}

#modal > div {
  padding: 16px;
}
<button onclick='onClickButton()'>Show Modal</button>
<div id='modal' tabindex='-1' onfocusout='onFocusLoss()'>
  <div>Focus Test</div>
  <div>
    <input>
  </div>
</div>

Вот как я предполагаю, что события фокуса происходят, когда модальное окно сфокусировано, а затем я щелкаю внутри ввода, затем сначала модальное окно теряет фокус, тело является активным элементом, а затем входной элемент становится активным элементом, а тело теряет фокус. тело, в то время как в onFocusLoss, activeEl - это вход.

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

Мое решение основано на этом ответе Хотя .

Ответы [ 2 ]

0 голосов
/ 05 августа 2020

Так же, как @RiverTwilight, я убираю необходимость фокуса и просто добавляю событие onClick.

Я поместил <div> внутри вашего #modal и заставил #modal заполнить весь экран, это Таким образом, вы можете использовать различные анимации и другие методы для анимации вашего контента, если #modal не имеет отступов.

Надеюсь, вы получили свой ответ. ✌️

function onClickButton() {
  var modal = document.getElementById('modal');
  modal.style.visibility = 'visible';
  modal.focus();
}

function onModalBGClick(e) {
  var modal = document.getElementById('modal');
  var activeEl = e.target;
  
  if (activeEl === modal) {
    modal.style.visibility = 'hidden';
  }
}
#modal {
  position: fixed;
  visibility: hidden;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
}

.modal-inner {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 1px solid red;
}

#modal > div {
  padding: 16px;
}
<button onclick='onClickButton()'>Show Modal</button>
<div id='modal' onclick='onModalBGClick(event)'>
  <div class="modal-inner">
    <div>Focus Test</div>
    <div>
      <input>
    </div>
  </div>
</div>
0 голосов
/ 05 августа 2020

Может с sh передумать. Когда модальное окно сфокусировано, добавьте событие щелчка к элементу под ним, чтобы закрыть модальное окно.

<body>
  <button onclick='onClickButton()'>Show Modal</button>
  <div id='modal' tabindex='-1'>
    <div>Focus Test</div>
    <div>
      <input>
    </div>
  </div>
</body>
function onClickButton() {
  const modal = document.getElementById('modal');
  modal.style.visibility = 'visible';
  modal.focus();
  document.body.addEventListener('click', ()=>{
    modal.style.visiable = 'hidden'
  })
}

Не забудьте настроить модальное окно z-index, чтобы убедиться, что оно находится над телом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...