skip to Main Content

Consider I have this simple div:

<div class="diamond"><span class="material-symbols-outlined" id="locks">lock</span></div>

The CSS for this is below:

.rotate-and-change {
    transform: rotate(360deg);
}
.diamond {
    aspect-ratio: 1 / 1;
    margin: 0px -2px;
    background-color: #f44336;
    clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
    scale: 0.8;
}
#locks{
    padding: 8px;
    transition: transform 0.5s ease;  
}

And the function that I am having trouble with is:

    let diamonds=document.getElementsByClassName('diamond');
    let locks=document.querySelectorAll('#locks');

function changeTheMarksInDiamonds(parameter){
    setTimeout(() => {
    for(let i=0;i<=correctGuess-parameter;i++){
    diamonds[i].style.background=parameter==0?"#f44336":"#4caf50";
    //diamonds[i].innerHTML=parameter==1?"<span id="locks" class="material-symbols-outlined" >check</span>":"<span id="locks"class="material-symbols-outlined" >lock</span>";
    //diamonds[i].innerHTML=parameter==1?"<span id="locks" class="material-symbols-outlined" >check</span>":"<span id="locks"class="material-symbols-outlined" >lock</span>";
    /*
    const newLockElement = diamonds[i].querySelector("#locks");
    newLockElement.classList.add("rotate-and-change");
    */
}
  }, 500);
  if(parameter==1){
    document.getElementsByClassName('conditionsStatistics')[0].style.paddingLeft=200-correctGuess*50+"px";
  }

}

So, whenever I call this changeTheMarksInDiamonds(parameter) function with any parameter, it is supposed to add the class rotate-and-change to the span of id locks after 0.5 seconds. But nothing such happens. The content in the span changes surely though, but the id locks get attached as a class named locks, that I do not want to. Moreover, the rotation-transformation effect also does not work. I though there is a simple logic being missed in my JavaScript code, but how to solve it?

Any kind of assistance is appreciated.

3

Answers


  1. I don’t understand why you are doing it so difficult.
    When you change the innerHtml fo a parent element(here, like ‘.diamond’), it recreates the content inside the div. So any references to the original elements like #locks span will be lost, and the #locks id might be incorrectly applied as a class.

    So to do this, instead of replacing the entire innerhtml of the ‘.diamond’ div, you could directly modify the ‘span’ inside it.
    I gave you the corrrected code.

        <div class="diamond"> 
    <span class="material-symbols-outlined" id = locks">lock</span></div>
    

    CSS:

    .rotate-and-change {
    transform: rotate(360deg);
    trnasition: transform 0.5s ease;
    }
    .diamond {
    aspect-ratio: 1/1;
    margin: 0px -2px;
    background-color: #f44336;
    clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
    scale: 0.8;
    }
    
    #locks {
    padding: 8px;
     }
    

    JavaScript:

    let diamonds = document.getElementsByClassName('diamond');
    let locks = document.querySelectorAll('#locks');
    
    function changeTheMarksInDiamonds(parameter) {
        setTimeout(() => {
            for (let i = 0; i <= correctGuess - parameter; i++) {
                // Update background color based on parameter
                diamonds[i].style.background = parameter == 0 ? "#f44336" : "#4caf50";
    
                // Get the span inside the diamond and update its content
                const lockElement = diamonds[i].querySelector('#locks');
    
                if (lockElement) {
                    // Apply rotation class
                    lockElement.classList.add("rotate-and-change");
    
                    // Change content
                    lockElement.textContent = parameter == 1 ? "check" : "lock";
                }
            }
        }, 500);
    
        if (parameter == 1) {
            document.getElementsByClassName('conditionsStatistics')[0].style.paddingLeft = 200 - correctGuess * 50 + "px";
        }
    }
    
    Login or Signup to reply.
  2. I’m guessing changeTheMarksInDiamonds(parameter) function seems to stem from the way you’re updating the innerHTML of the diamond elements. When you set innerHTML, it replaces the entire content of the element, causing the existing DOM nodes (including the span with the id="locks") to be removed and recreated. This means the reference to the original #locks element is lost, and any event listeners or styles applied to the original element are not transferred to the new one.

    I tried to implement it and it seems to be working:

    let diamonds = document.getElementsByClassName('diamond');
    let correctGuess = 2; // Example value
    
    function changeTheMarksInDiamonds(parameter) {
      setTimeout(() => {
        for (let i = 0; i < diamonds.length; i++) {
          const spanElement = diamonds[i].querySelector("#locks");
    
          // Update background color
          diamonds[i].style.background = parameter == 0 ? "#f44336" : "#4caf50";
    
          if (parameter == 1) {
            spanElement.textContent = "check";
          } else {
            spanElement.textContent = "lock";
          }
    
          // Apply the rotation class to trigger the animation
          spanElement.classList.add("rotate-and-change");
        }
      }, 500);
    
      if (parameter == 1) {
        document.getElementsByClassName('conditionsStatistics')[0].style.paddingLeft = 200 - correctGuess * 50 + "px";
      }
    }
    
    // Example
    changeTheMarksInDiamonds(1); // Call this function with 1 or 0 to test
    .rotate-and-change {
      transform: rotate(360deg);
    }
    
    .diamond {
      aspect-ratio: 1 / 1;
      margin: 0px -2px;
      background-color: #f44336;
      clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
      scale: 0.8;
      display: inline-block;
      text-align: center;
      vertical-align: middle;
      line-height: 100px;
      /* Adjust to vertically center the content */
    }
    
    #locks {
      padding: 8px;
      transition: transform 0.5s ease;
      font-size: 24px;
      /* Adjust size if needed */
      color: white;
      display: inline-block;
    }
    
    .conditionsStatistics {
      margin-top: 20px;
    }
    <div class="diamond"><span class="material-symbols-outlined" id="locks">lock</span></div>
    <div class="diamond"><span class="material-symbols-outlined" id="locks">lock</span></div>
    <div class="diamond"><span class="material-symbols-outlined" id="locks">lock</span></div>
    
    <div class="conditionsStatistics">Condition Statistics</div>
    Login or Signup to reply.
  3. Changed id="locks" to class="locks" to avoid duplicate IDs.
    Replacing all the HTML in the diamond element directly changed the content and classes of the existing span.
    Only then was a rotating triangle used to ensure variability.

            let diamonds = document.getElementsByClassName('diamond');
            let correctGuess = 3; // Example value; you should set this based on your application logic.
    
            function changeTheMarksInDiamonds(parameter) {
                setTimeout(() => {
                    for (let i = 0; i <= correctGuess - parameter; i++) {
                        // Change background color
                        diamonds[i].style.background = parameter == 0 ? "#f44336" : "#4caf50";
                        
                        // Get the span with class "locks"
                        const lockElement = diamonds[i].querySelector(".locks");
                        
                        // Change the icon and add rotation class
                        if (parameter == 1) {
                            lockElement.textContent = "check";
                            lockElement.classList.add("rotate-and-change");
                        } else {
                            lockElement.textContent = "lock";
                        }
                    }
                }, 500);
    
                if (parameter == 1) {
                    document.getElementsByClassName('conditionsStatistics')[0].style.paddingLeft = (200 - correctGuess * 50) + "px";
                }
            }
            .rotate-and-change {
                transform: rotate(360deg);
            }
    
            .diamond {
                aspect-ratio: 1 / 1;
                margin: 10px;
                background-color: #f44336;
                clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
                scale: 0.8;
                display: inline-block;
                text-align: center;
                line-height: 100px; /* Adjust this value based on the size of the diamond */
                font-size: 24px;
                color: white;
            }
    
            .locks {
                padding: 8px;
                transition: transform 0.5s ease;  
            }
    
            .conditionsStatistics {
                margin-top: 20px;
            }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <div class="diamond"><span class="material-symbols-outlined locks">lock</span></div>
        <div class="diamond"><span class="material-symbols-outlined locks">lock</span></div>
        <div class="diamond"><span class="material-symbols-outlined locks">lock</span></div>
        
        <div class="conditionsStatistics">
            <p>Conditions Statistics</p>
        </div>
    
        <button onclick="changeTheMarksInDiamonds(1)">Change Marks</button>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search