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.