Как правильно переключать классы, используя document.getElementsByClassName и Element.classList
У меня есть страница, на которой я хочу иметь возможность включать или выключать классы для определенных элементов.
В попытке сделать это я написал функцию:
function toggleClass(obj) {
alert(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) {
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>
1 ответ
Проблема в том, что вы продолжаете ссылаться obj.className
, но в forEach
цикл, после того, как элемент, по которому щелкают, повторяется, obj.className
становится пустым, поэтому на дальнейших итерациях (таких как "а" в is a story
), строка передана 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('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>