简体   繁体   中英

div loses focus, when clicked on a child which has focus

So, I am making a modal which has focus on it when it is shown. And if the user clicks outside, I want to hide it. I have implemented this with the help of focus events.

In cases, where the modal itself has a child which is focusable, modal loses the focus, I have also handled it in the below code. These cases are correctly handled by onFocusLoss but not by 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>

This is how I assume focus events are going, when the modal is focused and then I click inside input, then first the modal loses focus, the body is the active element, and then the input element becomes the active element, and body loses focus.

Thus, the reason maybe that onFocusLoss2 is not handling the case because activeEl at that time is the body, while in onFocusLoss , the activeEl is the input.

My question is, why one approach is working and the other is not? I want a good technical reason. If your answer is that it gives enough time so that input element gains focus, I want to know how can you say that the time is enough and will always work?

My solution is based on this answer , though.

May wish to change your mind. When the modal is focused, add a click event to the element below it to close the modal.

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

Don't forget to adjust modal's z-index to make sure it's above the body.

Just like @RiverTwilight, I'm removing the focus need and simply adding an onClick event.

I placed a <div> inside your #modal and made #modal fill the whole screen, this way you can use different animations and other techniques to also animate your content as long as #modal doesn't have padding.

I hope you get your answer. ✌️

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM