Добавление класса к каждому элементу с идентификатором в цикле foreach

#javascript #css #arrays #foreach

Вопрос:

Привет 🙂 Я кодирую переключатель темного режима и столкнулся с проблемой, которую не могу понять.

Я перебираю массив, содержащий элементы, которые выглядят следующим образом: { className: 'h3dark', elementId: 'h2'} . Затем я использую цикл forEach для применения каждого класса ко ВСЕМ элементам с определенным идентификатором. К сожалению, он применяет каждый класс только к первому html-элементу с идентификатором. Вы знаете, как это можно исправить?

HTML

     <h1 id="h1" class="h1">COLOR</h1>   <!--Color changed-->
    <h1 id="h2" class="h1">COLOR</h1>   <!--Color changed-->
    <h1 id="h3" class="h1">COLOR</h1>   <!--Color changed-->
    <h1 id="h1" class="h1">COLOR</h1>   <!--Color not changed-->
    <h1 id="h2" class="h1">COLOR</h1>   <!--Color not changed-->
    <h1 id="h3" class="h1">COLOR</h1>   <!--Color not changed-->
    
    <button onclick="darkSwitch()">CHANGE COLOR</button>

    </div>
 

язык JavaScript

     // checking if cookie exists
    var cookieState = Cookies.get('darkMode');

    // First visit - cookieState is undefined
    // If cookie exists we are parsing it to get a boolean
    if(cookieState === undefined){
        var isDarkmodeEnabled = false;
    }else{
        var isDarkmodeEnabled = JSON.parse(cookieState)
    };

    // Cookie doesn't exist: darkMode = false 
    // Cookie exists: darkMode = true/false
    var darkMode = isDarkmodeEnabled;

    // Add dark mode classes and elements' ids
    // className - a name of a class with dark mode attributes 
    // elementId - an id of an element a class will be added to
    var darkClasses = [
        { className: 'h1dark', elementId: 'h1'},
        { className: 'h2dark', elementId: 'h3'},
        { className: 'h3dark', elementId: 'h2'},           
    ];


    // Adding classes on page load if darkmode is enabled
    window.onload = addClassesOnLoad();

    // Changing darkMode state and adding or removing classes
    function darkSwitch(){

        // Setting darkMode to its opposite value
        darkMode = !darkMode;

        if(darkMode === true){
            // Looping through an array and deleting classes
            darkClasses.forEach(item => {
                document.getElementById(item.elementId).classList.add(item.className)
            });
        }
        else{
            // Looping through an array and deleting classes
            darkClasses.forEach(item => {
                document.getElementById(item.elementId).classList.remove(item.className)
            });  
        };
        // Saving darkMode state to the cookie
        Cookies.set('darkMode', darkMode);
    }

    // Adding classes on page load if darkmode is enabled
    function addClassesOnLoad(){

        if(darkMode === true){
            
            darkClasses.forEach(item =>{ 
                document.getElementById(item.elementId).classList.add(item.className)
            });
        };
    }
 

Вот как это выглядит и как должно быть

Комментарии:

1. НЕ ИСПОЛЬЗУЙТЕ ИДЕНТИФИКАТОРЫ ПОВТОРНО! Это плохая практика. Используйте классы или атрибуты, если вам нужно что-то многоразовое. Обратите внимание, как метод называется document.get Элемент по идентификатору. Не получить элементы по идентификатору. Предполагается, что он возвращает только один элемент.

2. Как вы думаете, это может быть как-то связано с тем, что идентификаторы same…in та половина, которая не работает? Это было бы моей первой подсказкой, если бы я устранял неполадки.

3. атрибут id уникален на странице, поэтому неверно в HTML иметь два дива с одинаковым идентификатором!

Ответ №1:

Попробуйте, как в следующем фрагменте:

 /*const cookieState = Cookies.get('darkMode');
if(cookieState === undefined){
    let isDarkmodeEnabled = false;
}else{
    let isDarkmodeEnabled = JSON.parse(cookieState)
};
let darkMode = isDarkmodeEnabled;*/
let darkMode = true //replace with isDarkmodeEnabled

const darkClasses = [
    { className: 'h1dark', classId: 'h1'},
    { className: 'h2dark', classId: 'h2'},
    { className: 'h3dark', classId: 'h3'},           
];

toggleDarkMode()

function darkSwitch(){
  darkMode = !darkMode;
  toggleDarkMode()
  //Cookies.set('darkMode', darkMode);
}

function toggleDarkMode(){
  darkClasses.forEach(item => { 
    const h1s = document.querySelectorAll(`.${item.classId}`)
    h1s.forEach(h => h.classList.toggle(item.className))
  })
} 
 .h1dark {
  color: orange;
}
.h2dark {
  color: red;
}
.h3dark {
  color: violet;
} 
 <h1 id="1" class="h1">COLOR</h1>   
<h1 id="2" class="h2">COLOR</h1>  
<h1 id="3" class="h3">COLOR</h1>  
<h1 id="4" class="h1">COLOR</h1>  
<h1 id="5" class="h2">COLOR</h1>   
<h1 id="6" class="h3">COLOR</h1>   

<button onclick="darkSwitch()">CHANGE COLOR</button> 

Комментарии:

1. Спасибо за ваш ответ! Это не сработало, но я внес небольшие изменения, и теперь это работает. Может быть, я неправильно реализовал ваш код.

2. Я не знаю почему, я кодирую уже несколько дней и не могу по-настоящему анализировать код, но я опубликовал решение ниже 🙂

3. Хороший приятель, я рад, что ты нашел решение. Если вам нужна какая-либо помощь, я готов помочь, если смогу. ура 🙂

4. item.defaultClass является элементом из вашего массива darkClasses и . является знаком для класса css (например .h1 ). Поэтому, когда вы получили элемент из массива, предположим, item.defaultClass=h1 мы добавим . его, чтобы мы могли ссылаться на класс css .h1

5. Вы можете узнать больше здесь

Ответ №2:

Благодаря ответу Николы Павичевича я все понял.

 darkClasses.forEach(item => {
    document.getElementById(item.elementId).classList.add(item.className)
});
 

Изменено на:

 darkClasses.forEach(item => {
    var element = document.querySelectorAll(`.${item.defaultClass}`)
    element.forEach(h => h.classList.add(item.newDarkClass))
});
 

и

 var darkClasses = [
        { newDarkClass: 'h1dark', defaultClass: 'h1'},
        { newDarkClass: 'h2dark', defaultClass: 'h2'},
        { newDarkClass: 'h3dark', defaultClass: 'h3'},           
    ];


    <h1 class="h1">COLOR</h1>   <!--Color changed-->
    <h1 class="h2">COLOR</h1>   <!--Color changed-->
    <h1 class="h3">COLOR</h1>   <!--Color changed-->
    <h1 class="h1">COLOR</h1>   <!--Color changed-->
    <h1 class="h2">COLOR</h1>   <!--Color changed-->
    <h1 class="h3">COLOR</h1>   <!--Color changed-->