英文:
How can I make this accordion collapsed by default?
问题
你希望使用W3C提供的JavaScript来创建一个手风琴效果。你的问题是面板在页面加载时默认展开,而你想让它们在页面加载时折叠,但不知道如何更改这个设置。
你在JavaScript代码中提供了以下解决问题的脚本,但问题是折叠状态没有按预期工作:
'use strict';
class Accordion {
constructor(domNode) {
this.rootEl = domNode;
this.buttonEl = this.rootEl.querySelector('button[aria-expanded]');
const controlsId = this.buttonEl.getAttribute('aria-controls');
this.contentEl = document.getElementById(controlsId);
this.open = this.buttonEl.getAttribute('aria-expanded') === 'true';
// 添加事件监听器
this.buttonEl.addEventListener('click', this.onButtonClick.bind(this));
}
onButtonClick() {
this.toggle(!this.open);
}
toggle(open) {
// 如果打开状态没有改变,不执行任何操作
if (open === this.open) {
return;
}
// 更新内部状态
this.open = open;
// 处理DOM更新
this.buttonEl.setAttribute('aria-expanded', `${open}`);
if (open) {
this.contentEl.removeAttribute('hidden');
} else {
this.contentEl.setAttribute('hidden', '');
}
}
// 为了方便,添加公共的打开和关闭方法
open() {
this.toggle(true);
}
close() {
this.toggle(false);
}
}
// 初始化手风琴
const accordions = document.querySelectorAll('.accordion h3');
accordions.forEach((accordionEl) => {
new Accordion(accordionEl);
});
你提供的HTML代码如下:
<div id="accordionGroup" class="accordion">
<h3>
<button type="button"
aria-expanded="false"
class="accordion-trigger"
aria-controls="sect1"
id="accordion1id">
<span class="accordion-title">
Section 1
<span class="accordion-icon"></span>
</span>
</button>
</h3>
<div id="sect1"
role="region"
aria-labelledby="accordion1id"
class="accordion-panel">
<div>
<div class="accordion-content">
Section 1 content
</div>
</div>
</div>
</div>
你已经确保了aria-expanded="false"
,但页面加载时仍然是展开的。这可能是由于JavaScript代码中的初始值设置问题导致的。你可以尝试在HTML代码中将按钮的aria-expanded
属性设置为"false"
,以确保它在页面加载时处于折叠状态,如下所示:
<button type="button"
aria-expanded="false" <!-- 这里设置为"false" -->
class="accordion-trigger"
aria-controls="sect1"
id="accordion1id">
<span class="accordion-title">
Section 1
<span class="accordion-icon"></span>
</span>
</button>
这样应该确保在页面加载时手风琴面板是折叠的。如果问题仍然存在,请检查JavaScript代码,确保没有其他设置导致面板默认展开。
英文:
I'd like to use the javascript that W3C provides here for an accordion. My problem is that the panels are expanded by default. I would like them to be collapsed when the page loads, and I can't figure out how to change it.
javascript:
'use strict';
class Accordion {
constructor(domNode) {
this.rootEl = domNode;
this.buttonEl = this.rootEl.querySelector('button[aria-expanded]');
const controlsId = this.buttonEl.getAttribute('aria-controls');
this.contentEl = document.getElementById(controlsId);
this.open = this.buttonEl.getAttribute('aria-expanded') === 'true';
// add event listeners
this.buttonEl.addEventListener('click', this.onButtonClick.bind(this));
}
onButtonClick() {
this.toggle(!this.open);
}
toggle(open) {
// don't do anything if the open state doesn't change
if (open === this.open) {
return;
}
// update the internal state
this.open = open;
// handle DOM updates
this.buttonEl.setAttribute('aria-expanded', `${open}`);
if (open) {
this.contentEl.removeAttribute('hidden');
} else {
this.contentEl.setAttribute('hidden', '');
}
}
// Add public open and close methods for convenience
open() {
this.toggle(true);
}
close() {
this.toggle(false);
}
}
// init accordions
const accordions = document.querySelectorAll('.accordion h3');
accordions.forEach((accordionEl) => {
new Accordion(accordionEl);
});
HTML:
<div id="accordionGroup" class="accordion">
<h3>
<button type="button"
aria-expanded="false"
class="accordion-trigger"
aria-controls="sect1"
id="accordion1id">
<span class="accordion-title">
Section 1
<span class="accordion-icon"></span>
</span>
</button>
</h3>
<div id="sect1"
role="region"
aria-labelledby="accordion1id"
class="accordion-panel">
<div>
<div class="accordion-content">
Section 1 content
</div>
</div>
</div>
</div>
I made sure that aria-expanded="false", but it's still expanded when the page loads.
答案1
得分: 0
看代码,它没有为你添加隐藏状态,所以你要么手动添加它,要么使用以下方式之一:
constructor(domNode) {
this.rootEl = domNode;
this.buttonEl = this.rootEl.querySelector('button[aria-expanded]');
const controlsId = this.buttonEl.getAttribute('aria-controls');
this.contentEl = document.getElementById(controlsId);
this.open = this.buttonEl.getAttribute('aria-expanded') === 'true';
// 确保隐藏元素实际上是隐藏的
if (!this.open && !this.contentEl.getAttribute("hidden")) {
this.contentEl.setAttribute("hidden", "")
}
// 添加事件监听器
this.buttonEl.addEventListener('click', this.onButtonClick.bind(this));
}
更新
在添加隐藏属性之前检查手风琴是否已关闭可以避免冲突的状态。
如果设置了 hidden
,并且同时设置了 aria-expanded
,或者状态相反,你将不得不按两次按钮。第一次按下将同步属性,第二次才会执行你想要的操作。
英文:
looking at the code it doesn't add the hidden state for you, so you'd either have to manually add it, or use something like the following
constructor(domNode) {
this.rootEl = domNode;
this.buttonEl = this.rootEl.querySelector('button[aria-expanded]');
const controlsId = this.buttonEl.getAttribute('aria-controls');
this.contentEl = document.getElementById(controlsId);
this.open = this.buttonEl.getAttribute('aria-expanded') === 'true';
// make sure hidden elements are actually hidden
if (!this.open && !this.contentEl.getAttribute("hidden")) {
this.contentEl.setAttribute("hidden", "")
}
// add event listeners
this.buttonEl.addEventListener('click', this.onButtonClick.bind(this));
}
update
checking if the accordion is closed before adding the hidden attribute avoids conflicting states.
if hidden
is set, and aria-expanded
is also set, or the opposite state, you will have to press the button twice. the first press syncs the attributes, and the second actually does the action you wanted.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论