Вот HTML-код (который появляется в нескольких местах, но к каждому виду следует относиться по-разному):
<div class = "foot-nav-heading">Click me!</div>
<div class = "textwidget">
<ul class = "quick-link accordion-content">
<li>Test</li>
</ul>
</div>
Вот код javascript:
var accordions = document.getElementsByClassName("foot-nav-heading");
for (var i = 0; i < accordions.length; i++) {
accordions[i].onclick = function() {
this.classList.toggle('is-open');
var content = this.nextElementSibling;
if (content.style.maxHeight) {
// accordion is currently open, so close it
content.style.maxHeight = null;
} else {
// accordion is currently closed, so open it
content.style.maxHeight = content.scrollHeight + "px";
}
}
}
Я хочу настроить таргетинг на «ul» в элементе «div.textwidget». я пробовал
var content = this.next.(".text-widget").find(".accordion-content")
Но это не работает.
Заранее спасибо!
document.querySelector('div.textwidget > ul.quick-link.accordion-content');
Обратите внимание, что приведенный ниже код появляется несколько раз в разных местах: <div class = "foot-nav-heading"> Нажми меня! </div> <div class = "textwidget"> <ul class = "quick-link accordion- content "> <li> Тест </li> </ul> </div>
document.querySelectorAll
...
@ j08691 Что я заменю на "document.querySelector ('div.textwidget> ul.quick-link.accordion-content');"? Не так хорошо с Javascript. Спасибо
Ваш код работает! Проблема не в брате, проблема в том, что вы не можете установить высоту css равной null
var accordions = document.getElementsByClassName("foot-nav-heading");
for (var i = 0; i < accordions.length; i++) {
accordions[i].onclick = function() {
this.classList.toggle('is-open');
var content = this.nextElementSibling;
if (content.style.maxHeight != "0px") {
// accordion is currently open, so close it
content.style.maxHeight = "0px";
} else {
// accordion is currently closed, so open it
content.style.maxHeight = "200px";
}
}
}
<div class = "foot-nav-heading">Click me!</div>
<div class = "textwidget">
<ul class = "quick-link accordion-content">
<li>Test</li>
</ul>
</div>
Here is the javascript code:
<div class = "foot-nav-heading">Click me!</div>
<div class = "textwidget">
<ul class = "quick-link accordion-content">
<li>Test</li>
</ul>
</div>
Here is the javascript code:
РЕДАКТИРОВАТЬ:
То, что вы пробовали со своим кодом, - это получить nextSibling. Но у вас могут быть дополнительные текстовые узлы с возвратом каретки. Попробуйте этот фрагмент:
document.querySelectorAll(".textwidget")[0].childNodes.forEach(function(el){
console.info(el.nodeName,el.nodeType);
});
<div class = "foot-nav-heading">Click me!</div>
<div class = "textwidget">
<ul class = "quick-link accordion-content">
<li>Test</li>
</ul>
</div>
Поэтому попытка нацеливания напрямую была бы рискованной (в вашем примере вы можете получить то, что хотите, с content.childNodes[1]
, но это опасно, если вы не знаете, как пишется html. Это может быть content.childNodes[0]
без возврата каретки). Следовательно, лучший вариант - проанализировать дочерние узлы и установить переменную или вставить элементы в массив, когда они выполняют условие. в твоем случае :
var ul;
content.forEach(function(el){
if (el.nodeName === 'UL') ul = el;
}
или создайте массив из списка узлов для фильтрации желаемого узла:
var ul = Array.from(document.querySelectorAll(".textwidget")[0].childNodes).filter(function(el) {if (el.nodeName == 'UL') return el});
// or use es6 features
// var ul = [...document.querySelectorAll(".textwidget")[0].childNodes].filter(e => e.nodeName == 'UL');
console.info(ul[0]);
<div class = "foot-nav-heading">Click me!</div>
<div class = "textwidget">
<ul class = "quick-link accordion-content">
<li>Test</li>
</ul>
</div>
Но он отлично работает там, где я его клонировал. Единственная разница в том, что <ul> заключен в <div>, поэтому мне нужно настроить таргетинг на <ul> внутри <div>
main#main
)e.target
, вы можете точно определить, какой тег был нажат.Относительно цели ОП:
"I want to target the child element in the next sibling parent without using class or ID."
Принимая во внимание фактический макет, каждая «кнопка» может быть нацелена на nextElementSibling
, добавить / удалить класс и по-прежнему иметь возможность воздействовать на дочерний элемент nextElementSibling
с помощью селектора CSS. Короче говоря, таргетинг на тег, вложенный в родительский элемент, является потраченным впустую, и который, в свою очередь, упрощает доступ к его потомкам через CSS.
<button>CLICK</button>
<section class='accordion'>
<ul class='list'>
<li>ITEM</li>
</ul>
</section>
/* By default this hides .list */
.accordion {
max-height: 0;
opacity: 0;
font-size: 0;
transition: all 0.3s;
border: 3px outset #666;
}
/* This class is added/removed when <button> is clicked */
/* .open is nextElementSibling and anytime .open is added, it's child .list
benefits from it as well
*/
.open,
.open .list {
height: auto;
max-height: 1000px;
opacity: 1;
font-size: 16px;
transition: all 0.3s;
border: 3px outset #666;
}
Детали прокомментированы в демо
// Reference the parent tag (main#main)
var main = document.getElementById('main');
/*
Register <main> to the click event...
toggleText() is the callback function
*/
main.addEventListener('click', toggleText);
// Pass the Event Object (e)
function toggleText(e) {
// Reference e.target -- clicked tag (header.head)
var tgt = e.target;
/*
Reference the next adjacent sibling of e.target (article.text)
*/
var actTxt = tgt.nextElementSibling;
// Collect all article.text into a NodeList
var txts = document.querySelectorAll('.text');
// if clicked tag has class .head...
if (tgt.classList.contains('head')) {
/*
On each loop...
if the current article.text is NOT e.target's .text sibling...
...remove class .open.
Toggle .open class on e.target's .text sibling.
*/
for (let i = 0; i < txts.length; i++) {
if (txts[i] !== actTxt) {
txts[i].classList.remove('open');
}
}
actTxt.classList.toggle('open');
}
}
.head {
cursor: pointer;
border: 3px outset #666;
text-align:center;
padding: 3px 5px;
}
.text {
max-height: 0;
opacity: 0;
font-size: 0;
transition: all 0.3s;
border: 3px outset #666;
}
.open,
.open .menu {
height: auto;
max-height: 1000px;
opacity: 1;
font-size: 16px;
transition: all 0.3s;
border: 3px outset #666;
}
<main id='main'>
<header class = "head">MENU</header>
<article class = "text">
<ul class = "menu">
<li>ITEM 1</li>
<li>ITEM 2</li>
<li>ITEM 3</li>
</ul>
</article>
<header class = "head">MENU</header>
<article class = "text">
<ul class = "menu">
<li>ITEM 1</li>
<li>ITEM 2</li>
<li>ITEM 3</li>
</ul>
</article>
<header class = "head">MENU</header>
<article class = "text">
<ul class = "menu">
<li>ITEM 1</li>
<li>ITEM 2</li>
<li>ITEM 3</li>
</ul>
</article>
</main>
this.querySelector('.accordion-content');
не уверен, что это сработает, но попробуй;)