Skip to content
Advertisement

In Javascript, how do I write one function that will effect multiple buttons, each with their own separate arrays?

I am currently setting up an application with three separate buttons, each which is supposed to randomly select an element from an array specific to that button. I’ve successfully coded it with individual functions for each button, but I was wondering if there is a way to condense it into a single function that can apply to all three buttons.

This is my current Javascript:

const greyButton = document.querySelector('#grey');
greyButton.addEventListener('click', () => {
  let grey = ['Statblocks/Grey/badger.png', 'Statblocks/Grey/giantrat.png', 'Statblocks/Grey/badger.png', 'Statblocks/Grey/boar.png', 'Statblocks/Grey/panther.png', 'Statblocks/Grey/gitant badger.png', 'Statblocks/Grey/dire wolf.png', 'Statblocks/Grey/giant elk.png']
  
  for (i=0;i<grey.length;i++){
    let greyBalls = grey[Math.floor(Math.random() * grey.length)];
    document.getElementById('greyBall').src = greyBalls;
  }
});

const rustButton = document.querySelector('#rust');
rustButton.addEventListener('click', () => {
  let rust = ['Statblocks/Rust/rat.png', 'Statblocks/Rust/owl.png', 'Statblocks/Rust/mastiff.png', 'Statblocks/Rust/goat.png', 'Statblocks/Rust/giant goat.png', 'Statblocks/Rust/giant boar.png', 'Statblocks/Rust/lion.png', 'Statblocks/Rust/brown bear.png']
  
  for (i=0;i<rust.length;i++){
    let rustBalls = rust[Math.floor(Math.random() * rust.length)];
    document.getElementById('rustBall').src = rustBalls;
  }
});

const tanButton = document.querySelector('#tan');
tanButton.addEventListener('click', () => {
  let tan = ['Statblocks/Tan/jackal.png', 'Statblocks/Tan/ape.png', 'Statblocks/Tan/baboon.png', 'Statblocks/Tan/axe beak.png', 'Statblocks/Tan/black bear.png', 'Statblocks/Tan/giant weasel.png', 'Statblocks/Tan/giant hyena.png', 'Statblocks/Tan/tiger.png']
  
  for (i=0;i<tan.length;i++){
    let tanBalls = tan[Math.floor(Math.random() * tan.length)];
    document.getElementById('tanBall').src = tanBalls;
  }
});

And the connected HTML:

 <div class="row">
            <div class="column">
                <h1>Grey Bag of Tricks</h1>
                <button class="button" id='grey'>Draw from the Bag</button>
                <img src="" alt="" id="greyBall">
            </div>
            <div class="column">
                <h1>Rust Bag of Tricks</h1>
                <button class="button" id='rust'>Draw from the Bag</button>
                <img src="" alt="" id="rustBall">
            </div>
            <div class="column">
                <h1>Tan Bag of Tricks</h1>
                <button class="button" id='tan'>Draw from the Bag</button>
                <img src="" alt="" id="tanBall">
            </div>
        </div>

Advertisement

Answer

var urlsByColor = {
  grey: ['Statblocks/Grey/badger.png', 'Statblocks/Grey/giantrat.png', 'Statblocks/Grey/badger.png', 'Statblocks/Grey/boar.png', 'Statblocks/Grey/panther.png', 'Statblocks/Grey/gitant badger.png', 'Statblocks/Grey/dire wolf.png', 'Statblocks/Grey/giant elk.png'],
  rust: ['Statblocks/Rust/rat.png', 'Statblocks/Rust/owl.png', 'Statblocks/Rust/mastiff.png', 'Statblocks/Rust/goat.png', 'Statblocks/Rust/giant goat.png', 'Statblocks/Rust/giant boar.png', 'Statblocks/Rust/lion.png', 'Statblocks/Rust/brown bear.png'],
  tan: ['Statblocks/Tan/jackal.png', 'Statblocks/Tan/ape.png', 'Statblocks/Tan/baboon.png', 'Statblocks/Tan/axe beak.png', 'Statblocks/Tan/black bear.png', 'Statblocks/Tan/giant weasel.png', 'Statblocks/Tan/giant hyena.png', 'Statblocks/Tan/tiger.png']
};

function changeBall (e) {
  const urls = urlsByColor[e.target.id];
  const randomIndex = Math.floor(Math.random() * urls.length);
  const randomUrl = urls[randomIndex];
  const associatedBall = e.target.closest('.column').querySelector('.ball');
  
  console.log(`change ${e.target.id} to ${randomUrl}`);
  associatedBall.src = randomUrl;
  console.log(associatedBall);
}

[...document.querySelectorAll('.color.button')].forEach(button =>
  button.addEventListener('click', changeBall)
);
<div class="row">
  <div class="column">
    <h1>Grey Bag of Tricks</h1>
    <button class="button color" id='grey'>Draw from the Bag</button>
    <img src="" alt="" class="ball" id="greyBall">
  </div>
  <div class="column">
    <h1>Rust Bag of Tricks</h1>
    <button class="button color" id='rust'>Draw from the Bag</button>
    <img src="" alt="" class="ball" id="rustBall">
  </div>
  <div class="column">
    <h1>Tan Bag of Tricks</h1>
    <button class="button color" id='tan'>Draw from the Bag</button>
    <img src="" alt="" class="ball" id="tanBall">
  </div>
</div>

Ok so a few things changed.

  • I extracted the lists of urls out to a map, that can use the id of the button to lookup what urls to use
  • The markup for the buttons and balls changed to have common classes for finds and lookups
  • When a click happens, we get the urls by the button id
  • We then get a random index like was done before
  • We get the random assoicated url for that index
  • We find the ball that is associated with the button contextually by the parent column class
  • And finally we change the ball’s url
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement