Как привязать обработчик событий к нескольким HTML элементам
У меня есть код который при нажатии на кнопку открывает попап окно. Мне нужно еще чтобы такое же попап окно открывалось при нажатии на определенный пункт меню, но дело в том что как только я назначила класс openDialogBtn пункту меню попап окно уже не открывается при нажатии на кнопку, то есть почему можно сделать либо на кнопку либо только на пункт меню.
<body class="parent ">
<button
class="openDialogBtn button-violet"
type="button"
aria-haspopup="dialog"
aria-controls="myDialog"
>
Примеры работ
</button>
<dialog class="child" id="myDialog">
<div class="dialog__wrapper">
<div class="icons">
<a class="icon" href="https://rutube.ru/channel/48172946/"><img src="https://antiugon161.ru/wp-content/uploads/2025/05/rutub.png" > </a>
<a class="icon" href="https://m.vkvideo.ru/@id888935889"><img src="https://antiugon161.ru/wp-content/uploads/2025/05/вк1.png" > </a>
<a class="icon" href="https://youtube.com/@protectorrostov?si=DevGLs5nWOyiH7j8"><img src="https://antiugon161.ru/wp-content/uploads/2025/05/ютюб1.png" > </a>
</div>
</div>
</dialog>
</body>
<script>
const dialog = document.getElementById('myDialog')
const dialogOpener = document.querySelector('.openDialogBtn')
const dialogCloser = dialog.querySelector('.closeDialogBtn')
function closeOnBackDropClick({ currentTarget, target }) {
const dialog = currentTarget
const isClickedOnBackDrop = target === dialog
if (isClickedOnBackDrop) {
close()
}
}
function openModalAndLockScroll() {
dialog.showModal()
document.body.classList.add('scroll-lock')
}
function returnScroll() {
document.body.classList.remove('scroll-lock')
}
function close() {
dialog.close()
returnScroll()
}
dialog.addEventListener('click', closeOnBackDropClick)
dialog.addEventListener('cancel', (event) => {
returnScroll()
});
dialogOpener.addEventListener('click', openModalAndLockScroll)
dialogCloser.addEventListener('click', (event) => {
event.stopPropagation()
close()
})
</script>
Ответы (3 шт):
Вот как это может работать:
const dialog = document.getElementById('myDialog');
const dialogOpener = document.querySelector('.openDialogBtn');
const dialogMenuOpener = document.querySelector('.openDialogMenuItem');
const dialogCloser = dialog.querySelector('.closeDialogBtn');
function closeOnBackDropClick({ currentTarget, target }) {
const isClickedOnBackDrop = target === currentTarget;
if (isClickedOnBackDrop) {
close();
}
}
function openModalAndLockScroll() {
dialog.showModal();
document.body.classList.add('scroll-lock');
}
function returnScroll() {
document.body.classList.remove('scroll-lock');
}
function close() {
dialog.close();
returnScroll();
}
dialog.addEventListener('click', closeOnBackDropClick);
dialog.addEventListener('cancel', returnScroll);
// Обработчик для кнопки
dialogOpener.addEventListener('click', openModalAndLockScroll);
// Обработчик для пункта меню
dialogMenuOpener.addEventListener('click', (event) => {
event.preventDefault(); // предотвращаем переход по ссылке
openModalAndLockScroll();
});
// Обработчик для закрытия попапа
if (dialogCloser) {
dialogCloser.addEventListener('click', (event) => {
event.stopPropagation();
close();
});
}
body {
display: flex;
height: 100vh;
margin: 0;
font-family: Arial, sans-serif;
}
.menu {
width: 200px;
background-color: #f0f0f0;
padding: 20px;
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
}
.menu a {
display: block;
margin: 10px 0;
text-decoration: none;
color: #333;
}
.main {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.openDialogBtn {
padding: 10px 20px;
background-color: #6a5acd;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.child {
padding: 20px;
}
.icons img {
width: 25%; /* Уменьшаем размер иконок до 25% от их оригинального размера */
height: auto; /* Сохраняем пропорции */
}
dialog {
width: 75%; /* Устанавливаем ширину попапа на 75% от ширины страницы */
max-width: 800px; /* Ограничиваем максимальную ширину попапа */
border: none; /* Убираем рамку */
border-radius: 8px; /* Закругляем углы */
}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Попап окно</title>
<link rel="stylesheet" href="styles.css"> <!-- Подключаем CSS -->
</head>
<body class="parent">
<div class="menu">
<a href="#" class="openDialogMenuItem">Примеры работ</a>
<!-- Можно добавить больше пунктов меню здесь -->
</div>
<div class="main">
<button
class="openDialogBtn button-violet"
type="button"
aria-haspopup="dialog"
aria-controls="myDialog"
>
Примеры работ
</button>
</div>
<dialog class="child" id="myDialog">
<div class="dialog__wrapper">
<div class="icons">
<a class="icon" href="https://rutube.ru/channel/48172946/"><img src="https://antiugon161.ru/wp-content/uploads/2025/05/rutub.png"></a>
<a class="icon" href="https://m.vkvideo.ru/@id888935889"><img src="https://antiugon161.ru/wp-content/uploads/2025/05/вк1.png"></a>
<a class="icon" href="https://youtube.com/@protectorrostov?si=DevGLs5nWOyiH7j8"><img src="https://antiugon161.ru/wp-content/uploads/2025/05/ютюб1.png"></a>
</div>
</div>
</dialog>
<script src="script.js"></script> <!-- Подключаем JavaScript -->
</body>
</html>
Юлия, Вам предстоит самостоятельно разобраться в том,
почему ваш код не работал...
Успехов!
(возможно позже дополню ответ)
Я бы предложил вот такой вариант:
//класс .openDialogBtn назначаете всем объектам,
// по клику на которые должно срабатывать открытие окна
//Выбираем все объекты с классом .openDialogBtn
let objects = document.querySelectorAll(".openDialogBtn");
//детектим, нажатие и передаем в функцию для обработки
Array.from(objects, el => el.addEventListener('click', e => {
openModalAndLockScroll(e));
}));
function openModalAndLockScroll(e) {
//Если нужна проверка, что было нажато кнопка или ссылка и т.д.
//let whatsClick = e.target;
//...
//Ваша функция
dialog.showModal();
document.body.classList.add('scroll-lock');
}
Мне нужно еще чтобы такое же попап окно открывалось при нажатии на определенный пункт меню
Если у этих элементов есть некий общий родитель - можно использовать делегирование событий.
const dialog = document.getElementById('myDialog')
const dialogOpener = document.querySelector('section')
const dialogCloser = dialog.querySelector('.closeDialogBtn')
function closeOnBackDropClick({
currentTarget,
target
}) {
const dialog = currentTarget
const isClickedOnBackDrop = target === dialog
if (isClickedOnBackDrop) {
close()
}
}
function openModalAndLockScroll() {
dialog.showModal()
document.body.classList.add('scroll-lock')
}
function returnScroll() {
document.body.classList.remove('scroll-lock')
}
function close() {
dialog.close()
returnScroll()
}
dialog.addEventListener('click', closeOnBackDropClick)
dialog.addEventListener('cancel', (event) => {
returnScroll()
});
dialogOpener.addEventListener('click', e => {
const o = e.target.closest('.openDialogBtn')
if (!o) return
e.preventDefault()
openModalAndLockScroll()
})
dialogCloser.addEventListener('click', (event) => {
event.stopPropagation()
close()
})
<body class="parent ">
<section>
<a href='#' class='openDialogBtn'>Некий пункт меню</a>
<button
class="openDialogBtn button-violet"
type="button"
aria-haspopup="dialog"
aria-controls="myDialog"
>
Примеры работ
</button>
</section>
<dialog class="child" id="myDialog">
<button class='closeDialogBtn'>Закрыть</button>
<div class="dialog__wrapper">
<div class="icons">
<a class="icon" href="https://rutube.ru/channel/48172946/"><img src="https://antiugon161.ru/wp-content/uploads/2025/05/rutub.png" > </a>
<a class="icon" href="https://m.vkvideo.ru/@id888935889"><img src="https://antiugon161.ru/wp-content/uploads/2025/05/вк1.png" > </a>
<a class="icon" href="https://youtube.com/@protectorrostov?si=DevGLs5nWOyiH7j8"><img src="https://antiugon161.ru/wp-content/uploads/2025/05/ютюб1.png" > </a>
</div>
</div>
</dialog>
</body>