[英]Adding remove class section to existing eventlistener loop
What I am trying to do, is loop through all my.nav__btn elements, use them as buttons through the addEventListener, and through that add the class.open to certain elements.我想做的是循环遍历所有 my.nav__btn 元素,通过 addEventListener 将它们用作按钮,然后将 class.open 添加到某些元素。
This part actually works fine, and I even managed to make it remove the.open class from other elements, when a new one is triggered.这部分实际上工作正常,我什至设法让它在触发新元素时从其他元素中删除 .open class 。
However, I have tried in multiple ways now to make it remove the.open class, if the same button is pressed again.但是,如果再次按下同一个按钮,我现在已经尝试了多种方法让它删除 .open class。
I have tried using:我试过使用:
if (sections[x].classList.contains('open')) {
sections.classList.remove('open')
}
in different locations of the function, but without success.在 function 的不同位置,但没有成功。 Either it breaks the script or simply has no effect.
它要么破坏脚本,要么根本没有效果。
my only solution is creating a completely seperate function to handle this matter, and have 2 EventListeners on the same elements, but I think it can be worked into this script.我唯一的解决方案是创建一个完全独立的 function 来处理这个问题,并在相同的元素上有 2 个 EventListener,但我认为它可以用于此脚本。 I just do not have the skills to do so, aparently.
显然,我只是没有这样做的技能。
Below a complete snippet:下面是一个完整的片段:
var btns = document.querySelectorAll('.nav__btn'); var sections = document.querySelectorAll('section'); for (var i = 0; i < btns.length; i++) { (function(x) { btns[x].addEventListener('click', _ => { if (sections[x].classList.contains('open')) { sections[x].classList.remove('open') } sections.forEach(section => { if (section.classList.contains('open')) { section.classList.remove('open') } }) sections[x].classList.toggle('open') }) })(i) }
section { position: absolute; top: 0; right: 0; height: 50vh; width: 50vw; opacity: 0; visiblity: 0; z-index: 30; } section:nth-child(2) { background: #00ff00; } section:nth-child(3) { background: #ff0000; } section:nth-child(4) { background: #0000ff; } section:nth-child(5) { background: #ccc; }.open { opacity: 1; visibility: 1; }
<nav class="nav"> <ul class="nav__list"> <li><span class="nav__btn">Button 1</span></li> <li><span class="nav__btn">Button 2</span></li> <li><span class="nav__btn">Button 3</span></li> <li><span class="nav__btn">Button 4</span></li> </ul> </nav> <section>section 1</section> <section>section 2</section> <section>section 3</section> <section>section 4</section>
Additionaly, here is a JsFiddle link: https://jsfiddle.net/ajLxbqzk/4/此外,这是一个 JsFiddle 链接: https://jsfiddle.net/ajLxbqzk/4/
To handle correctly sections display, you can loop through them this way:要正确处理部分显示,您可以通过这种方式循环:
section
is associated to the button, toggle its displaysection
与按钮相关联,则切换其显示Below a working version:下面是一个工作版本:
var btns = document.querySelectorAll('.nav__btn');
var sections = document.querySelectorAll('section');
// We loop through all buttons in the btns collection
// "i" is the index of the current button processed in the loop
btns.forEach((btn, i) => {
btn.addEventListener('click', _ => {
// If btns[i] is clicked, loop through sections...
sections.forEach((section, j) => {
if (i == j) {
// The current section is of index i (because i == j)
// We toogle it
section.classList.toggle('open');
} else {
// Other sections are just hided
section.classList.remove('open');
}
});
});
});
This is your click handler code:这是您的点击处理程序代码:
//1
if (sections[x].classList.contains('open')) {
sections[x].classList.remove('open')
}
//2
sections.forEach(section => {
if (section.classList.contains('open')) {
section.classList.remove('open')
}
})
//3
sections[x].classList.toggle('open')
I labeled it into three steps.我把它标记为三个步骤。 When you click a button, these three things happen:
当你点击一个按钮时,会发生这三件事:
Step 1 is redundant because step 2 closes all sections anyway - the end result will always be all sections being closed.第 1 步是多余的,因为第 2 步无论如何都会关闭所有部分 - 最终结果将始终是所有部分都被关闭。
Since step 2 ensures that all sections are always closed by the time you reach step 3, step 3 only can possibly do one thing: set the current section to open.由于第 2 步确保在您到达第 3 步时所有部分始终关闭,因此第 3 步只能做一件事:将当前部分设置为打开。 The current section can never be open at this point - because it was just closed in both step 1 and 2 - so
sections[x].classList.toggle('open')
can't possibly do anything other than make the section open.当前部分此时永远无法打开 - 因为它刚刚在步骤 1 和 2 中关闭 - 所以
sections[x].classList.toggle('open')
除了打开该部分之外不可能做任何事情。
What you've described as what you want to happen is not the function that you wrote.你所描述的你想要发生的不是你写的 function 。 What you want is something like this:
你想要的是这样的:
Because that way, when step 2 runs, the current section might still be open, therefore toggling it sets it to closed.因为这样,当第 2 步运行时,当前部分可能仍处于打开状态,因此切换它会将其设置为关闭。 So all you have to do is write it exactly as described:
因此,您所要做的就是完全按照描述编写它:
//1 - close all sections EXCEPT sections[x]
sections.forEach(section => {
if (section != sections[x] && section.classList.contains('open')) {
section.classList.remove('open')
}
})
//2 - toggle sections[x]
sections[x].classList.toggle('open')
Here it is in your complete example:这是您的完整示例:
var btns = document.querySelectorAll('.nav__btn'); var sections = document.querySelectorAll('section'); for (var i = 0; i < btns.length; i++) { (function(x) { btns[x].addEventListener('click', _ => { //1 - close all sections EXCEPT sections[x] sections.forEach(section => { if (section.= sections[x] && section.classList.contains('open')) { section.classList.remove('open') } }) //2 - toggle sections[x] sections[x].classList.toggle('open') }) })(i) }
section { position: absolute; top: 0; right: 0; height: 50vh; width: 50vw; opacity: 0; visiblity: 0; z-index: 30; } section:nth-child(2) { background: #00ff00; } section:nth-child(3) { background: #ff0000; } section:nth-child(4) { background: #0000ff; } section:nth-child(5) { background: #ccc; }.open { opacity: 1; visibility: 1; }
<nav class="nav"> <ul class="nav__list"> <li><span class="nav__btn">Button 1</span></li> <li><span class="nav__btn">Button 2</span></li> <li><span class="nav__btn">Button 3</span></li> <li><span class="nav__btn">Button 4</span></li> </ul> </nav> <section>section 1</section> <section>section 2</section> <section>section 3</section> <section>section 4</section>
I really don't like using loops in code.我真的不喜欢在代码中使用循环。 It creates messy code and looping over elements takes time.
它会创建混乱的代码并且遍历元素需要时间。 I prefer storing variables instead.
我更喜欢存储变量。
I removed your inner method that had x
as an argument.我删除了以
x
作为参数的内部方法。 Instead, I changed var i
in your loop to let i
, otherwise i would have the value of 4 inside the anonymous click method.相反,我将循环中的
var i
更改为let i
,否则 i 将在匿名单击方法中具有 4 的值。
I created a content element as a container for all the sections which I which added "content" as an id.我创建了一个内容元素作为所有部分的容器,我将“内容”添加为 id。
I then just add the attribute previous-index
to content and let that keep track of which section that was previously opened and let an if statement decide if I should remove the open
class or not.然后,我只需将属性
previous-index
添加到内容中,让它跟踪之前打开的部分,并让 if 语句决定我是否应该删除open
的 class。 I could use a global variable outside of the click methods but using global variables are always in the risk of being overwritten in larger projects.我可以在点击方法之外使用全局变量,但使用全局变量在较大的项目中总是有被覆盖的风险。
I'm using sectionIsOpen
and newButtonClicked
in order to explain code through variables, because it's harder to read "not statements", like i != previouslyClickedIndex
.我正在使用
sectionIsOpen
和newButtonClicked
来通过变量解释代码,因为它更难阅读“非语句”,例如i != previouslyClickedIndex
。
Finally, you're using the wrong values on visibility
.最后,您在
visibility
上使用了错误的值。 It should be hidden
or visible
, not 0 or 1.它应该是
hidden
或visible
,而不是 0 或 1。
const btns = document.querySelectorAll('.nav__btn'); const sections = document.querySelectorAll('section'); const content = document.getElementById('content'); for (let i = 0; i < btns.length; i++) { btns[i].addEventListener('click', () => { const NOT_SET = -1; let previouslyClickedIndex = content.getAttribute('previous-index') || NOT_SET; let sectionIsOpen = previouslyClickedIndex;= NOT_SET; let newButtonClicked = i.= previouslyClickedIndex. if (sectionIsOpen && newButtonClicked) { sections[previouslyClickedIndex];classList.remove('open'). } sections[i];classList.toggle('open'), content;setAttribute('previous-index'; i); }); }
section { position: absolute; top: 0; right: 0; height: 50vh; width: 50vw; opacity: 0; visiblity: hidden; z-index: 30; } section:nth-child(2) { background: #00ff00; } section:nth-child(3) { background: #ff0000; } section:nth-child(4) { background: #0000ff; } section:nth-child(5) { background: #ccc; }.open { opacity: 1; visibility: visible; }
<nav class="nav"> <ul class="nav__list"> <li><span class="nav__btn">Button 1</span></li> <li><span class="nav__btn">Button 2</span></li> <li><span class="nav__btn">Button 3</span></li> <li><span class="nav__btn">Button 4</span></li> </ul> </nav> <content id="content"> <section>section 1</section> <section>section 2</section> <section>section 3</section> <section>section 4</section> </content>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.