如何使用 document.getElementsByClassName 和 Element.classList 正确切换类 [英] How to correctly toggle classes using document.getElementsByClassName and Element.classList
问题描述
我有一个页面,我希望能够在其中打开或关闭特定元素上的类.
为了做到这一点,我编写了一个函数:
function toggleClass(obj) {警报(obj.className);Array.from(document.getElementsByClassName(obj.className)).forEach(function(element) {element.classList.toggle(obj.className);});}
由表中的项目调用,例如 <td style=""><span class="determiner" onclick="toggleClass(this)">Determiner</span></td>
.
当我第一次单击该项目时,这可以正常工作,触发警报并删除该类.当我再次单击表中的同一项目以尝试切换/添加类时,警报会触发(因为类已被删除,所以为空)但未添加该类.
谁能告诉我我在这里做错了什么?
function toggleClass(obj) {警报(obj.className);Array.from(document.getElementsByClassName(obj.className)).forEach(function(element) {element.classList.toggle(obj.className);});}
.determiner {/* 颜色:RGB(248, 8, 8);*/边框:1px 实心 rgb(248, 8, 8);}.介词{颜色:RGB(40、18、236);/* 边框:1px 实心 rgb(40, 18, 236);*/}.动词存在{颜色:RGB(13、146、68);/* 边框:3px 实心 rgb(13, 146, 68);*/}span[class^='名词-'], span[class*='名词-']{颜色:#F00;}
<table class="grammar table table-hover" data-toggle="table" data-sort-name="instance_use" 数据-sort-order="desc"><thead><tr><th style="" data-field="grammar_type" tabindex="0"><div class="th-inner sortable both">语法类型</div><;div class="fht-cell"></div></th><th style="" data-field="instance_use" tabindex="0"><div class="th-内部可排序的两个 desc">使用实例</div><div class="fht-cell"></div></th></tr></thead><tbody><tr data-index="0"><td style=""><span class="adverb" onclick="toggleClass(this)">副词</span></td><td style="">2 </td></tr><tr data-index="1"><td style=""><span class="动词-present" onclick="toggleClass(this)">动词,呈现</span></td><td style="">2 </td></tr><tr 数据-index="2"><td style=""><span class="determiner" onclick="toggleClass(this)">Determiner</span></td><td style="">2 </td></tr><tr data-index="3"><td style=""><span class="noun-sing-or-mass"onclick="toggleClass(this)"> 名词,唱歌.或质量</span></td><td style="">1 </td></tr><tr data-index="4"><td style=""><span class="" onclick="toggleClass(this)">介词</span></td><td style="">1 </td></tr><;tr data-index="5"><td style=""><span class="noun-plural" onclick="toggleClass(this)">名词,复数</span></td><td style="">1 </td></tr><tr data-index="6"><td style=""><span class="comma" onclick="toggleClass(this)">逗号</span></td><td style="">1 </td></tr><tr data-index="7"><td style=""><span class="personal-pronoun" onclick="toggleClass(this)">人称代词</span></td><td style="">1 </td></tr></tbody><div id="story_text"><span style="white-space: pre-line"><span class="adverb">这里</span><span class="verb-present">is</span><span class="determiner">a</span><span class="noun-sing-or-mass">story</span><span class="">with</span><span class="determiner">no</span><span class="名词复数">逗号</span><span class="逗号">,</span><span class="副词">现在</span><span class="personal-pronoun">it</span><span class="verb-present">确实</span></span>
问题是你一直在引用 obj.className
,但是在 forEach
循环中,一旦被点击的元素被迭代,obj.className
变成空白,所以进一步迭代(比如中的a"是一个故事
),传递给element.classList.toggle
为空.
另一个问题是,当您再次尝试单击该元素时,它没有现有的类,因此 obj.className
为空 - 没有可切换回的类.
不要在 HTML 属性中添加处理程序(这与 eval
一样糟糕),尝试遍历所有需要处理程序的元素事先,这样您就可以构建一个数组您希望能够切换的每个 className
的元素.
一个不太优雅的解决方案(需要更少的更改)是切换一个 不同的 类来覆盖 color
和 border
属性determiner
和其他类的:
function toggleClass(obj) {const className = obj.classList[0];document.querySelectorAll('.' + className).forEach(element => {element.classList.toggle('空白');});}
.determiner {/* 颜色:RGB(248, 8, 8);*/边框:1px 实心 rgb(248, 8, 8);}.介词{颜色:RGB(40、18、236);/* 边框:1px 实心 rgb(40, 18, 236);*/}.动词存在{颜色:RGB(13、146、68);/* 边框:3px 实心 rgb(13, 146, 68);*/}跨度[class^='名词-'],span[class*='名词-'] {颜色:#F00;}.空白的 {边框:0;颜色:黑色!重要;}
<table class="grammar table table-hover" data-toggle="table" data-sort-name="instance_use" 数据-sort-order="desc"><thead><tr><th style="" data-field="grammar_type" tabindex="0"><div class="th-inner sortable both">语法类型</div><;div class="fht-cell"></div></th><th style="" data-field="instance_use" tabindex="0"><div class="th-内部可排序的两个 desc">使用实例</div><div class="fht-cell"></div></th></tr></thead><tbody><tr data-index="0"><td style=""><span class="adverb" onclick="toggleClass(this)">副词</span></td><td style="">2 </td></tr><tr data-index="1"><td style=""><span class="动词-present" onclick="toggleClass(this)">动词,呈现</span></td><td style="">2 </td></tr><tr 数据-index="2"><td style=""><span class="determiner" onclick="toggleClass(this)">Determiner</span></td><td style="">2 </td></tr><tr data-index="3"><td style=""><span class="noun-sing-or-mass"onclick="toggleClass(this)"> 名词,唱歌.或质量</span></td><td style="">1 </td></tr><tr data-index="4"><td style=""><span class="" onclick="toggleClass(this)">介词</span></td><td style="">1 </td></tr><;tr data-index="5"><td style=""><span class="noun-plural" onclick="toggleClass(this)">名词,复数</span></td><td style="">1 </td></tr><tr data-index="6"><td style=""><span class="comma" onclick="toggleClass(this)">逗号</span></td><td style="">1 </td></tr><tr data-index="7"><td style=""><span class="personal-pronoun" onclick="toggleClass(this)">人称代词</span></td><td style="">1 </td></tr></tbody><div id="story_text"><span style="white-space: pre-line"><span class="adverb">这里</span><span class="verb-present">is</span><span class="determiner">a</span><span class="noun-sing-or-mass">story</span><span class="">with</span><span class="determiner">no</span><span class="名词复数">逗号</span><span class="逗号">,</span><span class="副词">现在</span><span class="personal-pronoun">it</span><span class="verb-present">确实</span></span>
I have a page where I want to be able to toggle classes on particular elements on or off.
In an attempt to do this I have written a function:
function toggleClass(obj) {
alert(obj.className);
Array.from(document.getElementsByClassName(obj.className)).forEach(function(element) {
element.classList.toggle(obj.className);
});
}
which is called by items in a table e.g <td style=""><span class="determiner" onclick="toggleClass(this)">Determiner</span></td>
.
This works fine when I first click the item, the alert is triggered and the class is removed. When I click the same item in the table again to try and toggle/add the class the alert fires (empty because the class has been removed) but the class is not added.
Can anyone advise what I am doing wrong here?
function toggleClass(obj) {
alert(obj.className);
Array.from(document.getElementsByClassName(obj.className)).forEach(function(element) {
element.classList.toggle(obj.className);
});
}
.determiner {
/* color: rgb(248, 8, 8); */
border: 1px solid rgb(248, 8, 8);
}
.preposition {
color: rgb(40, 18, 236);
/* border: 1px solid rgb(40, 18, 236); */
}
.verb-present {
color: rgb(13, 146, 68);
/* border: 3px solid rgb(13, 146, 68); */
}
span[class^='noun-'], span[class*=' noun-']{
color: #F00;
}
<table class="grammar table table-hover" data-toggle="table" data-sort-name="instance_use" data-sort-order="desc">
<thead><tr><th style="" data-field="grammar_type" tabindex="0"><div class="th-inner sortable both">Grammar Type</div><div class="fht-cell"></div></th><th style="" data-field="instance_use" tabindex="0"><div class="th-inner sortable both desc">Instances of Use</div><div class="fht-cell"></div></th></tr></thead>
<tbody><tr data-index="0"><td style=""><span class="adverb" onclick="toggleClass(this)">Adverb</span></td><td style="">2 </td></tr><tr data-index="1"><td style=""><span class="verb-present" onclick="toggleClass(this)">Verb, present</span></td><td style="">2 </td></tr><tr data-index="2"><td style=""><span class="determiner" onclick="toggleClass(this)">Determiner</span></td><td style="">2 </td></tr><tr data-index="3"><td style=""><span class="noun-sing-or-mass" onclick="toggleClass(this)">Noun, sing. or mass</span></td><td style="">1 </td></tr><tr data-index="4"><td style=""><span class="" onclick="toggleClass(this)">Preposition</span></td><td style="">1 </td></tr><tr data-index="5"><td style=""><span class="noun-plural" onclick="toggleClass(this)">Noun, plural</span></td><td style="">1 </td></tr><tr data-index="6"><td style=""><span class="comma" onclick="toggleClass(this)">Comma</span></td><td style="">1 </td></tr><tr data-index="7"><td style=""><span class="personal-pronoun" onclick="toggleClass(this)">Personal pronoun</span></td><td style="">1 </td></tr></tbody>
</table>
<div id="story_text">
<span style="white-space: pre-line">
<span class="adverb">here</span> <span class="verb-present">is</span> <span class="determiner">a</span> <span class="noun-sing-or-mass">story</span> <span class="">with</span> <span class="determiner">no</span> <span class="noun-plural">commas</span><span class="comma">,</span> <span class="adverb">now</span> <span class="personal-pronoun">it</span> <span class="verb-present">does</span>
</span>
</div>
The problem is that you keep referencing obj.className
, but in the forEach
loop, once the clicked element is iterated over, the obj.className
becomes blank, so on further iterations (such as the "a" in is a story
), the string passed to element.classList.toggle
is blank.
Another problem is that when you try to click the element again, it has no existing class, so obj.className
is empty - there's no class to toggle back on.
Instead of adding handlers in HTML attributes (which is as bad as eval
), try iterating through all elements that need a handler beforehand, so you can build an array of elements for each className
you want to be able to toggle.
A less elegant solution (that would require many fewer changes) would be to toggle a different class which overrides the color
and border
properties of the determiner
and other classes:
function toggleClass(obj) {
const className = obj.classList[0];
document.querySelectorAll('.' + className).forEach(element => {
element.classList.toggle('blank');
});
}
.determiner {
/* color: rgb(248, 8, 8); */
border: 1px solid rgb(248, 8, 8);
}
.preposition {
color: rgb(40, 18, 236);
/* border: 1px solid rgb(40, 18, 236); */
}
.verb-present {
color: rgb(13, 146, 68);
/* border: 3px solid rgb(13, 146, 68); */
}
span[class^='noun-'],
span[class*=' noun-'] {
color: #F00;
}
.blank {
border: 0;
color: black !important;
}
<table class="grammar table table-hover" data-toggle="table" data-sort-name="instance_use" data-sort-order="desc">
<thead><tr><th style="" data-field="grammar_type" tabindex="0"><div class="th-inner sortable both">Grammar Type</div><div class="fht-cell"></div></th><th style="" data-field="instance_use" tabindex="0"><div class="th-inner sortable both desc">Instances of Use</div><div class="fht-cell"></div></th></tr></thead>
<tbody><tr data-index="0"><td style=""><span class="adverb" onclick="toggleClass(this)">Adverb</span></td><td style="">2 </td></tr><tr data-index="1"><td style=""><span class="verb-present" onclick="toggleClass(this)">Verb, present</span></td><td style="">2 </td></tr><tr data-index="2"><td style=""><span class="determiner" onclick="toggleClass(this)">Determiner</span></td><td style="">2 </td></tr><tr data-index="3"><td style=""><span class="noun-sing-or-mass" onclick="toggleClass(this)">Noun, sing. or mass</span></td><td style="">1 </td></tr><tr data-index="4"><td style=""><span class="" onclick="toggleClass(this)">Preposition</span></td><td style="">1 </td></tr><tr data-index="5"><td style=""><span class="noun-plural" onclick="toggleClass(this)">Noun, plural</span></td><td style="">1 </td></tr><tr data-index="6"><td style=""><span class="comma" onclick="toggleClass(this)">Comma</span></td><td style="">1 </td></tr><tr data-index="7"><td style=""><span class="personal-pronoun" onclick="toggleClass(this)">Personal pronoun</span></td><td style="">1 </td></tr></tbody>
</table>
<div id="story_text">
<span style="white-space: pre-line">
<span class="adverb">here</span> <span class="verb-present">is</span> <span class="determiner">a</span> <span class="noun-sing-or-mass">story</span> <span class="">with</span> <span class="determiner">no</span> <span class="noun-plural">commas</span><span class="comma">,</span> <span class="adverb">now</span> <span class="personal-pronoun">it</span> <span class="verb-present">does</span>
</span>
</div>
这篇关于如何使用 document.getElementsByClassName 和 Element.classList 正确切换类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!