1

Let's say I got three buttons and four iframes where the purpose of the button is to control the iframe width. Each iframe will have the same class .resize since the function they need is the same, so I just use querySelector to target them.

What's the best way to do this where the button only affects the respective iframe? I have thought of just creating as many classes as possible to different iframe and the function will be the same. But clearly, this will not make sense if I got 100 iframes then I will need to make 100 classes and 100 identical functions.

document.querySelector('.container').addEventListener('click', (e) => {

  if (!e.target.matches('button')) return;
  const wasChange = e.target.matches(':first-child'); 
  const styles = ['90px', '60%', '100%'].indexOf(e.target);
  iframe.style.width = styles[index];
  
});
.container {
  display: grid;
  grid-template-columns: repeat(2, minmax(150px, 1fr));
  grid-column-gap: 15px;
  grid-row-gap: 15px;
}

#iframe01 {
  background-color: orange;
}

#iframe02 {
  background-color: blue;
}

#iframe03 {
  background-color: green;
}

#iframe04 {
  background-color: yellow;
}
<div class="container">
  <div>
    <div>
      <button>Small</button>
      <button>Medium</button>
      <button>Big</button>
    </div>
    <iframe id="iframe01"></iframe>
  </div>
  <div>
    <div>
      <button>Small</button>
      <button>Medium</button>
      <button>Big</button>
    </div>
    <iframe id="iframe02"></iframe>
  </div>
  <div>
    <div>
      <button>Small</button>
      <button>Medium</button>
      <button>Big</button>
    </div>
    <iframe id="iframe03"></iframe>
  </div>
  <div>
    <div>
      <button>Small</button>
      <button>Medium</button>
      <button>Big</button>
    </div>
    <iframe id="iframe04"></iframe>
  </div>
</div>

1 Answers1

1

The best approach would be to

  • avoid inline handlers
  • iterate over the elements using JavaScript and, on click, dynamically navigate to the associated <iframe> in the same container. Event delegation would work well too here.

document.querySelector('#hr').addEventListener('click', (e) => {
  // if the click was on a change or back button:
  if (!e.target.matches('button')) return;
  const wasChange = e.target.matches(':first-child'); // true if "change", false if "back"
  const iframe = e.target.parentElement.nextElementSibling;
  iframe.style.width = wasChange ? "90px" : '100%';
});
#hr {
  display: grid;
  grid-template-columns: repeat(2, minmax(150px, 1fr));
  grid-column-gap: 15px;
  grid-row-gap: 15px;
}

#iframe01 {
  background-color: orange;
}

#iframe02 {
  background-color: blue;
}

#iframe03 {
  background-color: green;
}

#iframe04 {
  background-color: yellow;
}
<div id="hr">
  <div>
    <div class="hr">
      <button>Button01-change</button>
      <button>Button01-back</button>
    </div>
    <iframe id="iframe01" class="resize"></iframe>
  </div>
  <div>
    <div class="hr">
      <button>Button02-change</button>
      <button>Button02-back</button>
    </div>
    <iframe id="iframe02" class="resize"></iframe>
  </div>
  <div>
    <div class="hr">
      <button>Button03-change</button>
      <button>Button03-back</button>
    </div>
    <iframe id="iframe03" class="resize"></iframe>
  </div>
  <div>
    <div class="hr">
      <button>Button04-change</button>
      <button>Button04-back</button>
    </div>
    <iframe id="iframe04" class="resize"></iframe>
  </div>
</div>
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Hello, what if I need one more button which is 60%? –  Jul 09 '21 at 11:10
  • I've tried `iframe.style.width = wasChange ? "90px" : "60%" : '100%';` but it's not workingI've edit the snippet, you can have a look. –  Jul 10 '21 at 01:41
  • Use an array of styles instead, and look up the index of the clicked button in the array. `const styles = ['90px', '60%', '100%']` and `const index = [...e.target.parentElement.children].indexOf(e.target)` to find the style to apply – CertainPerformance Jul 10 '21 at 01:47
  • Sorry because I'm still learning JavaSript, I was trying to understand your code and apply it. I already understand your concept here but have no idea how to write/implement the code...Would you mind updating your answer –  Jul 10 '21 at 02:13
  • Once you have the index, just look up the value in the array and assign to the style. `frame.style.width = styles[index];` – CertainPerformance Jul 10 '21 at 02:21
  • I've just updated the snippet but it's weirdSorry if I make something stupid because I'm really learning JavaScript... –  Jul 10 '21 at 02:25
  • You need to spread the children into an array, as in the code in the comment. `[...e.target.parentElement.children]`, not `e.target.parentElement.children]` – CertainPerformance Jul 10 '21 at 02:26
  • I still can't understand...Sorry –  Jul 10 '21 at 02:39
  • Maybe can you just update the answer or add an updated answer below the original answer we can easily understand, please? –  Jul 10 '21 at 03:13