skip to Main Content

I have a few html <div> elements that each have another <div> nested in them. The nested element is responsible for the CSS, and the outer element is responsible for the JavaScript. (The outer <div> element is necessary because the nested element would have holes in its hitbox if it was responsible for detecting clicks.)

Anyways, to aid my explanation, here’s my code:

window.onload = function() {
  const buttons = document.getElementsByClassName('icon-wrapper');
  [...buttons].forEach(button => button.addEventListener('click', function() {
    var target = this.children[0]
    target.classList.toggle('toggled')
    console.log(target)
    // code dependant on the value of this
  }))
};
/* css for each button has been removed because I don't want to release them yet...*/

body {
  margin: 5%;
  display: flex;
  -moz-column-gap: 5%;
  column-gap: 5%;
  row-gap: 5%;
}

.icon-wrapper {
  height: 8vmin;
  width: 8vmin;
  position: relative;
  display: flex;
  cursor: pointer;
  /* extra code for visablility */
  background-color: black;
}
<div class="icon-wrapper">
  <div id="menu-icon"></div>
</div>
<div class="icon-wrapper">
  <div id="full-screen-icon"></div>
</div>
<div class="icon-wrapper">
  <div id="tab-icon"></div>
</div>
<div class="icon-wrapper">
  <div id="volume-icon"></div>
</div>
<iframe class="windowed" id="iframe" frameborder="0" allowtransparency="true" src="https://www.heavensgate.com/">
</iframe>

Now on to the actual specifics! As you can see, each button will have a unique function. My problem is that I can’t assign a unique function to each event listener based on the element it’s targeting. For example, when the second icon wrapper which contains the full screen button <div> is clicked, the <iframe> element will request full screen. But when the third button is clicked, the <iframe> will open in a new tab. Basically, I want each iteration of the forEach loop to have a different function. Finally, if possible, I also want the unique function to be based on the Id of the nested element, and not the index of the loop/array, so I can reorder the elements without it breaking.

I hope I got the point across in this post, but if you need me to elaborate on anything, please ask.

Edit: Unless they post a stand-alone answer, check the comments for what Barmar said, it seems to be what I was after.

2

Answers


  1. Chosen as BEST ANSWER

    Posting an answer that I got in the comments from @Barmar

    "You could just use a switch statement: switch(target.id)"


  2. You can use an object to associate each id with a function to execute on click (as also mentioned by Barmar).

    Also note that if you use document.querySelectorAll, you can directly call forEach without converting the result to an array first.

    const fns = {
        "menu-icon"() {
            console.log('menu icon clicked');
        },
        "full-screen-icon"() {
            console.log('full screen icon clicked');
        }
        // ...
    };
    document.querySelectorAll('.icon-wrapper').forEach(wrapper =>
        wrapper.addEventListener('click', fns[wrapper.firstElementChild.id]));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search