У меня есть класс с названием view
под «пятёркой» div
. И у меня двое детей по имени rView
, братья и сестры view
родителей. Теперь, если я хочу запустить событие click
в классе view
, который находится в cc1.fir
и нацелен на все классы rView
, все классы rView
запускаются либо в cc1.fir
, либо в cc1.sec
. Кроме того, когда я хочу нажать на событие view
, которое находится в событии cc1.sec
, оно не запускается.
Я хочу, чтобы, если пользователь нажимает cc1.fir
, должны отображаться все классы rView
, а не только rView
, присутствующие в cc1.sec
. И это событие щелчка должно работать для всех классов cc1
.
view = document.getElementsByClassName('view');
rView = document.querySelectorAll('.rView');
for (var i = 0; i < view.length; i++) {
view[i].addEventListener('click', () => {
rView.forEach(element => {
element.classList.toggle('View_active');
});
});
}
.rView {
display: none;
}
.View_active {
display: block;
}
<div class = "section">
<div class = "fir cc1">
<div class = "cc2">
<div class = "cc3">
<div class = "cc4">
<div class = "cc5">
<p class = "view">view</p>
</div>
</div>
</div>
</div>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
<div class = "sec cc1">
<div class = "cc2">
<div class = "cc3">
<div class = "cc4">
<div class = "cc5">
<p class = "view">view</p>
</div>
</div>
</div>
</div>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
</div>
Ваш код переключает все элементы, поскольку вы выбираете все элементы .rView
. Вам придется либо найти и переключить все элементы .rView
под разделом .cc1
, в котором находится ссылка на просмотр. Или лучше присвоить «представлению» и его элементам общий атрибут data-group
или аналогичный, чтобы знать, какие элементы div принадлежат какой ссылке «представление». Это делает его независимым от позиции элемента в HTML.
Это будет работать для вашего варианта использования:
view = document.getElementsByClassName('view');
for (var i = 0; i < view.length; i++) {
view[i].addEventListener('click', (e) => {
expand = e.currentTarget.getAttribute("data-expand");
rView = document.querySelectorAll('.rView[data-expand = "'+expand+'"]');
rView.forEach(element => {
element.classList.toggle('View_active');
});
});
}
.rView {
display: none;
}
.View_active {
display: block;
}
<div class = "section">
<div class = "fir cc1">
<div class = "cc2">
<div class = "cc3">
<div class = "cc4">
<div class = "cc5">
<p class = "view" data-expand = "1">view</p>
</div>
</div>
</div>
</div>
</div>
<div class = "text rView" data-expand = "1">
<p>Hello-down</p>
</div>
<div class = "text rView" data-expand = "1">
<p>Hello-down</p>
</div>
<div class = "sec cc1">
<div class = "cc2">
<div class = "cc3">
<div class = "cc4">
<div class = "cc5">
<p class = "view" data-expand = "2">view</p>
</div>
</div>
</div>
</div>
</div>
<div class = "text rView" data-expand = "2">
<p>Hello-down</p>
</div>
<div class = "text rView" data-expand = "2">
<p>Hello-down</p>
</div>
</div>
Хотя этот код выполняет свою работу, есть несколько проблем: 1. Вам не нужно перечислять каждый элемент, чтобы проверить, какой из них следует расширить. 2. for (var i = 0; i < view.length; i++)
можно заменить на view.forEach((element, index) => ...)
для улучшения читаемости и устранения риска ошибок, связанных с отклонением на единицу. 3. Не оптимально прикреплять прослушиватель событий к каждому триггеру view
. Вместо этого вы можете использовать всплытие событий. Узнайте, как более удобно реализовать эту функциональность: stackoverflow.com/a/78892079/8997321
@BrunoKawka Извините, что говорю вам, но вы изменили мой HTML
, вы добавили еще два div
и разделили их на два раздела, что не соответствует моему стилю.
@Brentspine Ваш код работает. Спасибо.
Нет проблем, я понимаю, что мой ответ может быть для вас слишком сложным в данный момент. Продолжайте учиться! :)
Это был мой мыслительный процесс. Обратите внимание, что решение может быть не лучшим, но на данный момент жаловаться на небольшие проблемы с дизайном или производительностью не имеет смысла. Удачи в изучении \@Renukasharma и в любом случае спасибо за советы @brunokawka
Я могу дополнить свой ответ подробным решением, если это поможет @Renukasharma
Кроме того, когда я хочу щелкнуть представление, которое находится в событии cc1.sec, оно не запускается.
Это связано с тем, что вы прикрепляете прослушиватель событий к самому первому селектору .view
, который появится в DOM.
Чтобы настроить таргетинг на все представления:
querySelectorAll
:click
к каждому представлению с помощью цикла forEach
.Кроме того, код написан не очень хорошо. Вместо этого вам следует:
а) Используйте элемент <button
с onclick <button onclick = "toggleActiveView()">view</button>
. Div не имеет готовой поддержки специальных возможностей. Как правило, использовать его для взаимодействия с пользователем — плохая идея, если только вы не предоставите все специальные возможности самостоятельно.
или
б) В JS есть такая вещь, как Всплытие и захват, чтобы вы могли обернуть все свои кнопки в div и перехватывать там все события. Но убедитесь, что вы проверили, что щелчок был на кнопке, а не на элементе div.
const wrapper = document.getElementById('wrapper');
wrapper.addEventListener('click', (event) => {
const isButton = event.target.nodeName === 'BUTTON';
if (!isButton) {
return;
}
console.dir(event.target.id);
})
Кроме того, вам не нужно перебирать все элементы rView, чтобы переключить их видимость. Вместо этого вы можете использовать атрибут данных родителя.
Вот улучшенная версия, которая:
data-accordion-trigger
, чтобы проверить, был ли нажат триггер.#accordion
используется всплывание событий.data-accordion-expanded
, чтобы указать, что rView должен быть виден.<html lang = "en">
<head>
<style>
#accordion[data-accordion-expanded] .rView {
display: block;
}
.rView {
display: none;
}
</style>
</head>
<body>
<div class = "section">
<div id = "accordion">
<div class = "fir cc1">
<div class = "cc2">
<div class = "cc3">
<div class = "cc4">
<div class = "cc5">
<button class = "view" data-accordion-trigger = "true">
view
</button>
</div>
</div>
</div>
</div>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
<div class = "sec cc1">
<div class = "cc2">
<div class = "cc3">
<div class = "cc4">
<div class = "cc5">
<button class = "view" data-accordion-trigger = "true">
view
</button>
</div>
</div>
</div>
</div>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
</div>
</div>
<script>
const accordion = document.querySelector("#accordion");
accordion.addEventListener("click", (event) => {
const isTrigger = event.target.hasAttribute("data-accordion-trigger");
if (isTrigger) {
toggleAccordion();
}
});
function toggleAccordion() {
accordion.toggleAttribute("data-accordion-expanded");
}
</script>
</body>
</html>
Обновлено:
Если вы хотите только развернуть группу элементов для данной кнопки, вам необходимо соответствующим образом отредактировать код:
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8" />
<meta name = "viewport" content = "width=device-width, initial-scale=1.0" />
<meta http-equiv = "X-UA-Compatible" content = "ie=edge" />
<title>HTML + CSS</title>
<style>
#accordion div[data-accordion-group][data-accordion-expanded] .rView {
display: block;
}
.rView {
display: none;
}
</style>
</head>
<body>
<div class = "section">
<div id = "accordion">
<div data-accordion-group = "">
<div class = "fir cc1">
<div class = "cc2">
<div class = "cc3">
<div class = "cc4">
<div class = "cc5">
<button class = "view" data-accordion-trigger = "">view</button>
</div>
</div>
</div>
</div>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
</div>
<div data-accordion-group = "">
<div class = "sec cc1">
<div class = "cc2">
<div class = "cc3">
<div class = "cc4">
<div class = "cc5">
<button class = "view" data-accordion-trigger = "">view</button>
</div>
</div>
</div>
</div>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
<div class = "text rView">
<p>Hello-down</p>
</div>
</div>
</div>
</div>
<script>
const accordion = document.querySelector("#accordion");
accordion.addEventListener("click", (event) => {
const isTrigger = event.target.hasAttribute("data-accordion-trigger");
if (isTrigger) {
const groupElement = event.target.closest("[data-accordion-group]");
toggleAccordionGroup(groupElement);
}
});
function toggleAccordionGroup(groupElement) {
groupElement.toggleAttribute("data-accordion-expanded");
}
</script>
</body>
</html>
Я не хочу видеть Hello-down
из cc1.sec
, когда я нажимаю cc1.fir
, или не хочу видеть Hello-down
из cc1.fir
, когда я нажимаю cc1.sec
.
Что ж, в этом случае вам нужно определить группу для данного триггерного элемента. Это можно сделать аналогично с помощью следующего атрибута данных: data-accordion-group = ""
. Затем в обработчике событий click
вам нужно найти ближайший восходящий элемент event.target с атрибутом «data-accordion-group». const groupElement = event.target.closest("[data-accordion-group]");
. Затем вместо переключения data-accordion-expanded
на контейнере-аккордеоне вы делаете это аналогично для группы groupElement.toggleAttribute("data-accordion-expanded");
. Полный код прикреплен в моем отредактированном ответе.
«Когда я хочу нажать на представление, которое находится в событии cc1.sec, оно не запускается». - вы вообще никогда не привязывали обработчик кликов к этому элементу.
querySelector
возвращает только первый найденный соответствующий элемент.