我创建了一个创建手风琴的Java Script代码。它现在的工作方式是当你点击一个封闭的内容标题面板时,内容会显示,但当我点击打开的内容的标题面板时,它不会关闭它。因此它打开其他面板但无法关闭当前打开的内容。
我尝试了其他不同的语句,针对不同的Java Script元素,但都引出了相同的结果。
function addClass(el, klass) {
el.classList.add(klass);
}
function removeClass(el, klass) {
el.classList.remove(klass);
}
const accordionItems = document.querySelectorAll(".accordion-item");
const accordionContentPanes = document.querySelectorAll(".accordion-content");
// Hide each besides target accordion on click
accordionItems.forEach(function(accordion) {
// Clicked accordions clickable target
const accordionTitleRow = accordion.firstElementChild;
console.log(accordion);
accordionTitleRow.addEventListener("click", toggleAccordion);
});
function toggleAccordion(e) {
accordionContentPanes.forEach(function(content) {
console.log(content);
// Check if clicked row matches the content's previous element sibling
if (content.previousElementSibling === e.target) {
removeClass(content, "hidden");
addClass(content.parentElement, "active");
}
else {
removeClass(content.parentElement, "active");
addClass(content, 'hidden');
}
});
}
最后的结果是我已经拥有的以及我上面解释的功能。
HTML看起来像:
<div class="accordion-item overflow-hidden w-full">
<div style="border-bottom: 1px solid #e2e2e2; border-top: 1px solid #e2e2e2;;" class="accordion-title-row flex justify-between items-center cursor-pointer
px-6 py-4 headerItem" id="first">
<div class="flex">
<i style=" font-size: 1.75em;margin-right: .5em;" class="fas fa-car fa-3x grey-text overlay"></i>
<h2 style="padding-top: .15em;" class="font-bold text-lg mb-0">Automotive</h2>
</div>
<div>
<svg style="color: #2196f3;" viewBox="0 0 20 20" width="20" height="20" class="fill-current text-grey-dark accordion-arrow">
<title>cheveron down</title>
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"></path>
</svg>
</div>
</div>
<div id="automotive" class="accordion-content list-reset leading-normal px-8 py-4 hidden">
Here is some content
</div>
</div>
<div class="accordion-item overflow-hidden w-full">
<div style="border-bottom: 1px solid #e2e2e2; border-top: 1px solid #e2e2e2;;" class="accordion-title-row flex justify-between items-center cursor-pointer
px-6 py-4 headerItem" id="second">
<div class="flex">
<i style=" font-size: 1.75em;margin-right: .5em;" class="fas fa-car fa-3x grey-text overlay"></i>
<h2 style="padding-top: .15em;" class="font-bold text-lg mb-0">Other</h2>
</div>
<div>
<svg style="color: #2196f3;" viewBox="0 0 20 20" width="20" height="20" class="fill-current text-grey-dark accordion-arrow">
<title>cheveron down</title>
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"></path>
</svg>
</div>
</div>
<div id="other" class="accordion-content list-reset leading-normal px-8 py-4 hidden">
Here is some more content
</div>
</div>
问题是e.target
不是你想象的那样。 e.target
是用户点击的,所以如果他们点击标题或SVG,那么e.target是标题或SVG,而不是你期望的标题行,所以比较:
content.previousElementSibling === e.target
工作非常不一致。
为了解决这个问题,我编写了以下函数,它将向后搜索包含类accordion-title-row
的父级。
function getTitleRowFromChild(elem) {
var result = elem;
while(result && !result.classList.contains("accordion-title-row")) {
if(result.parentElement)
result = result.parentElement;
}
return result;
}
然后我像这样修改了toggleAccordion:
function toggleAccordion(e) {
// get the title row from the target
var titleRow = getTitleRowFromChild(e.target);
accordionContentPanes.forEach(function(content) {
// change comparison to title row instead of e.target
if (content.previousElementSibling === titleRow) {
// this block is the only change
if(content.classList.contains("hidden")) {
removeClass(content, "hidden");
addClass(content.parentElement, "active");
}
else {
removeClass(content.parentElement, "active");
addClass(content, 'hidden');
}
} else {
removeClass(content.parentElement, "active");
addClass(content, 'hidden');
}
});
}
之后手风琴按预期工作。关于jsfiddle的完整示例,其中包含我从您的sharepoint.stackexchange帖子获得的HTML。它当然没有你所有的风格,但手风琴是有效的。