JS скрипт игнорирует условие и срабатывает без него
У меня есть типичное модальное окно. Я хочу, чтобы модальное окно закрывалось, если пользователь кликнет по зоне вне информационного блока попапа (по затемнённому пространству).
Проблема заключается в том, что скрипт срабатывает по клику не только в затемнённой области, а в принципе в любом месте, в том числе по самому контенту модального окна.
const openPopUp = document.getElementById('open_pop_up');
const closePopUp = document.getElementById('pop_up_close');
const popUp = document.getElementById('pop_up');
openPopUp.addEventListener('click', function(e) {
e.preventDefault();
popUp.classList.add('active');
});
const entryDisplay = document.querySelectorAll('.pop_up');
entryDisplay[0].onclick = function(event) {
console.log(event.target);
if (event.target = entryDisplay[0]) {
entryDisplay[0].classList.remove('active');
};
};
.pop_up {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
background-color: transparent;
transform: translate(-90%) scale(0);
transition: .4s ease-in-out;
z-index: 100;
}
.pop_up.active {
transform: translateY(0%) scale(1);
background-color: rgba(0, 0, 0, 0.8);
}
.pop_up_container {
display: flex;
width: 100%;
height: 100%;
padding: 10px;
z-index: 99;
}
.pop_up_body {
margin: auto;
width: 500px;
height: 600px;
overflow-y: auto;
background-color: #fff;
position: relative;
}
.pop_up_body .nws-item__caption ul {
padding-left: 10px;
}
.pop_up_body .nws-item__caption span {
font-weight: 500;
}
.pop_up_body .nws-item__date {
margin-top: 6px;
}
.pop_up_close {
width: 50px;
height: 50px;
font-size: 30px;
background-color: #892bff;
color: #fff;
top: 5px;
left: 5px;
opacity: 0.7;
text-align: center;
line-height: 50px;
border-radius: 50%;
position: fixed;
}
.pop_up_close:hover {
opacity: 1;
transition: .2s;
cursor: pointer;
transform: rotate(180deg);
}
<div class="pop_up" id="pop_up">
<div class="pop_up_container">
<div class="pop_up_body" id="pop_up_body">
<div class="nws-item__image"><img src="img/news/card1.jpeg" alt="picture"></div>
<div class="nws-item__date">20 Aug 2022</div>
<hr>
<div class="nws-item__title">Заголовок окна</div>
<div class="nws-item__caption">Описание в информационном модальном окне.</div>
<div class="pop_up_close" id="pop_up_close">✖</div>
</div>
</div>
</div>
<button id="open_pop_up">Открыть</button>
Ответы (3 шт):
Решение лежит в том, что все Event передаются так-же всем Child элементам.
https://codepen.io/latdev/pen/JjLbpPr
function inside(target, inside) {
let result = null,
node = target;
while (node !== null) {
if (node.isEqualNode(inside)) return true;
node = node.parentNode;
}
return false;
}
document.addEventListener('click', $event => {
let debug = document.getElementById('debug');
let modal = document.getElementById('modal');
if (!inside($event.target, modal)) {
debug.textContent = "You clicked Window";
return;
}
debug.textContent = "You clicked Modal";
});
#modal {
position: fixed;
top: 115%;
left: 50%;
width: 320px;
margin-left: -100px;
height: 180px;
margin-top: -240px;
background: pink;
}
<div id="modal">
<p>Hello World!</p>
<input id="modal/test-input">
</div>
<h3 id="debug">Click on modal or outside</h3>
Думаю можно попробовать добавить доп. условие когда попап открыт и остановить событие клика
if (popUp.classList.contains('active'){
e.stopPropagation();
};
Нужно помнить, что событие от целевого элемента будет передаваться вверх по иерархии, вплоть до window, а не наоборот.
Если событие дошло до window, при этом "по пути" отсутствует .pop_up_body или целевым элементом является кнопка закрытия, то закрываем модальное окно.
Мы можем повесить обработчик на .pop_up_body, а можем использовать метод closest() для поиска ближайшего родителя:
window.addEventListener('click', function(e) {
if (!e.target.closest('.pop_up_body') || closePopUp === e.target) {
popUp.classList.remove('active');
}
});
Также в обработчике кнопки открытия нужно добавить stopPropagation(), чтобы событие не дошло до window и окно сразу не закрылось:
openPopUp.addEventListener('click', function(e) {
popUp.classList.add('active');
e.stopPropagation();
});
Вот и все премудрости...
Пример целиком:
const openPopUp = document.getElementById('open_pop_up');
const closePopUp = document.getElementById('pop_up_close');
const popUp = document.getElementById('pop_up');
openPopUp.addEventListener('click', function(e) {
popUp.classList.add('active');
e.stopPropagation();
});
window.addEventListener('click', function(e) {
if (!e.target.closest('.pop_up_body') || closePopUp === e.target) {
popUp.classList.remove('active');
}
});
.pop_up {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
background-color: transparent;
transform: translate(-90%) scale(0);
transition: .4s ease-in-out;
z-index: 100;
}
.pop_up.active {
transform: translateY(0%) scale(1);
background-color: rgba(0, 0, 0, 0.8);
}
.pop_up_container {
display: flex;
width: 100%;
height: 100%;
padding: 10px;
z-index: 99;
}
.pop_up_body {
margin: auto;
width: 500px;
height: 600px;
overflow-y: auto;
background-color: #fff;
position: relative;
}
.pop_up_body .nws-item__caption ul {
padding-left: 10px;
}
.pop_up_body .nws-item__caption span {
font-weight: 500;
}
.pop_up_body .nws-item__date {
margin-top: 6px;
}
.pop_up_close {
width: 50px;
height: 50px;
font-size: 30px;
background-color: #892bff;
color: #fff;
top: 5px;
left: 5px;
opacity: 0.7;
text-align: center;
line-height: 50px;
border-radius: 50%;
position: fixed;
}
.pop_up_close:hover {
opacity: 1;
transition: .2s;
cursor: pointer;
transform: rotate(180deg);
}
<div class="pop_up" id="pop_up">
<div class="pop_up_container">
<div class="pop_up_body" id="pop_up_body">
<div class="nws-item__image"><img src="img/news/card1.jpeg" alt="picture"></div>
<div class="nws-item__date">20 Aug 2022</div>
<hr>
<div class="nws-item__title">Заголовок окна</div>
<div class="nws-item__caption">Описание в информационном модальном окне.</div>
<div class="pop_up_close" id="pop_up_close">✖</div>
</div>
</div>
</div>
<button id="open_pop_up">Открыть</button>