Search code examples
javascriptaddeventlistener

addEventListener to elements of array whose target is in a different array of different length


Given a set of <buttons> and <divs> such as:


<button class="buttTest" id="butt1">butt 1</button>
<button class="buttTest" id="butt2">butt 2</button>
<!-- <button class="buttTest" id="butt3">butt 3</button> DISABLED OR MISSING BUTTON-->
<button class="buttTest" id="butt4">butt 4</button>
<button class="buttTest" id="butt5">butt 5</button>

<div class="divTest" id="div1">div 1</div>
<div class="divTest" id="div2">div 2</div>
<div class="divTest" id="div3">div 3</div>
<div class="divTest" id="div4">div 4</div>
<div class="divTest" id="div5">div 5</div>

Suppose there exists the need to add the corresponding eventlistener to each button for each div such as this:

const buttArray = document.getElementsByClassName("buttTest");
const divArray = document.getElementsByClassName("divTest");

for (let i=0;i<=buttArray.length;i++) {
  buttArray[i].addEventListener("click", function () {divArray[i].style.display = 'none'})
}

clearly if one of the buttons needs to be disabled or is missing, the equivalence <button id="butt-i"> ---> <div id="divTest-j"> will be broken, and <button 4> will trigger <div 3> instead of <div 4>.

Is there a more or less straightforward way to achieve the proper correspondence between the two sets? I tried to test diverse array filter methods but failed. And also the words "lookup table" came to mind, but I'm at odds on how to implement this solution.


Solution

  • You are looping through buttons and divs without checking if there is a missing piece, adding a simple IF check or anything else like

    if (divArray[i]);
    // OR ANYTHING LIKE
    buttArray.forEach(button => {
    button.addEventListener("click", function () {
     const fetchedPartner = 
     document.querySelector(`#div${this.dataset.boundIndex}`);
     fetchedPartner.style.display = 'none';
    });
    

    will cause more problems, because the core issue is that when you have a missing button, the logic based on loops and indices can result in mismatches. For example, if one button is missing, it will always result in the last div to be left out, Instead of using loops with indices, we can map each button directly to its corresponding div by ID.

                // Select all buttons
                const buttons = document.querySelectorAll('.buttTest');
    
                // Loop over each button
                buttons.forEach(button => {
                    // Get the corresponding div id by replacing 'butt' with 'div'
                    const divId = button.id.replace('butt', 'div');
                    const div = document.getElementById(divId); // Find the div by id
    
                    // Check if the div exists
                    if (div) {
                        // Add event listener to the button
                        button.addEventListener('click', function() {
                            div.style.display = 'none'; // Hide the corresponding div
                        });
                    }
                });
    .divTest {
      background-color: lightcoral;
      padding: 10px;
      margin: 5px;
      display: block;
      }
        <html>
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
        </head>
        <body>
    
            <button class="buttTest" id="butt1">Button 1</button>
            <button class="buttTest" id="butt2">Button 2</button>
            <!-- <button class="buttTest" id="butt3">Button 3</button> DISABLED OR MISSING BUTTON -->
            <button class="buttTest" id="butt4">Button 4</button>
            <button class="buttTest" id="butt5">Button 5</button>
    
            <div class="divTest" id="div1">Div 1</div>
            <div class="divTest" id="div2">Div 2</div>
            <div class="divTest" id="div3">Div 3</div>
            <div class="divTest" id="div4">Div 4</div>
            <div class="divTest" id="div5">Div 5</div>
    
             
    
        </body>
        </html>

    OR

    const buttArray = document.getElementsByClassName("buttTest");
    
    for (let button of buttArray) {
        const buttonId = button.id.replace("butt", "div"); // Map "butt1" -> "div1"
        const targetDiv = document.getElementById(buttonId); // Get corresponding div
    
        if (targetDiv) {  // Only add event if div exists
            button.addEventListener("click", function () {
                targetDiv.style.display = 'none';
            });
        }
    }