skip to Main Content

I’m a beginner in JavaScript and I have a problem. I’m building a randomizing page, where I use 3 arrays and 3 buttons. I want it to expand with the answer (button 1 – array no1, button 2 – array no2, etc) when the button is clicked. But the problem is that I only get the answer to the querySelectorAll for the first button anyway and only it expands.

For now i using only one array, but i can’t figure out how to solve the problem of expanding buttons when they are clicked. How expand this button, which was clicked?

Codepen

console.clear();
const color = ["red", "green", "blue", "aqua", "black", "purple", "yellow"];
const fruits = [{
    type: "fruit",
    name: "orange",
    img: "https://t4.ftcdn.net/jpg/01/02/31/01/240_F_102310122_TyKkml1yRFle2IGtD2fAUrZLtixIGJqa.jpg"
  },
  {
    type: "fruit",
    name: "apple",
    img: "https://t3.ftcdn.net/jpg/03/10/32/02/240_F_310320273_I9rR1l7918MJoZ0GRHGIBgZl9F9ShEXq.jpg"
  },
  {
    type: "fruit",
    name: "banana",
    img: "https://t3.ftcdn.net/jpg/02/36/07/60/240_F_236076021_Lf2nHzSUcTxNGdG7hap6PjJNDwHT1VfC.jpg"
  },
  {
    type: "fruit",
    name: "mango",
    img: "https://t4.ftcdn.net/jpg/00/52/87/43/240_F_52874381_Ucxx67h9KLuxSXiNGcsmHfSjAuqRXqDr.jpg"
  },
  {
    type: "fruit",
    name: "kiwi",
    img: "https://t4.ftcdn.net/jpg/00/68/65/13/240_F_68651370_CVcQlAdJqvxtL8bIUm70UP1HwnFXOblQ.jpg"
  },
  {
    type: "fruit",
    name: "strawberries",
    img: "https://t4.ftcdn.net/jpg/00/84/36/81/240_F_84368117_irN0O3akL7ALdMe17ZtxH6nya1cHiG5H.jpg"
  },
  {
    type: "fruit",
    name: "grape",
    img: "https://t4.ftcdn.net/jpg/00/70/94/63/240_F_70946377_VJXdpJqld6XOsOTO6lt95ieZSxGO0faM.jpg"
  },
  {
    type: "fruit",
    name: "pear",
    img: ""
  }
];

let btns = document.querySelectorAll(".js-button");
let btn = document.querySelector(".js-button");
let isOpen = false;
let result = document.querySelector(".js-button-result");
let img = document.querySelector(".js-button-img");
let imgSrc = document.querySelector(".js-img");

btn.addEventListener("click", () => {
  if (!isOpen) {
    btn.classList.add("button--active");
    img.classList.add("button-img--active");
    result.classList.add("button-result--true");
    //draw.classList.add("draw--open")
    isOpen = true;
    const rand = Math.floor(Math.random() * fruits.length);
    result.innerHTML = fruits[rand].name;
    imgSrc.src = fruits[rand].img;
  } else {
    btn.classList.remove("button--active");
    img.classList.remove("button-img--active");
    result.classList.remove("button-result--true");
    //draw.classList.remove("draw--open")
    isOpen = false;
  }
});

window.addEventListener("click", (e) => {
  if (e.target !== btn /*&& e.target !== draw*/ ) {
    btn.classList.remove("button--active");
    img.classList.remove("button-img--active");
    result.classList.remove("button-result--true");
    //draw.classList.remove("draw--open")
    isOpen = false;
  }
});

btns.forEach((i) => {
  i.addEventListener("click", function() {
    let dataValue = event.target.getAttribute("data-value");

    /*if (!isOpen) {
    btn.classList.add("button--active");
    img.classList.add("button-img--active");
    result.classList.add("button-result--true");
    //draw.classList.add("draw--open")
    isOpen = true;
    const rand = Math.floor(Math.random() * fruits.length);
    result.innerHTML = fruits[rand].name;
    imgSrc.src = fruits[rand].img;
    
  } else {
    btn.classList.remove("button--active");
    img.classList.remove("button-img--active");
    result.classList.remove("button-result--true");
    //draw.classList.remove("draw--open")
    isOpen = false;
  }
    */
  });
});
* {
  box-sizing: border-box;
  font-size: 16px;
  letter-spacing: 1px;
  font-family: Montserrat, sans-serif;
}

body {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0;
  padding: 0;
}

.wrapper {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  margin: auto;
  position: relative;
  width: 30vw;
  height: 30vh;
}

.button {
  padding: 5% 0;
  margin: 10px 0;
  width: 100%;
  height: auto;
  text-align: center;
  border-radius: 0 20px;
  background-color: #dad7cd;
  user-select: none;
  transition: 100ms ease-in-out;
  outline: 0;
}

.button--active {
  position: absolute;
  top: 0;
  left: 0;
  margin: 0;
  height: 100%;
}

.button-result {
  display: none;
}

.button-result--true {
  display: block;
}

.button-img {
  width: 150px;
  height: 0;
  margin: 0 auto;
  display: flex;
  justify-content: center;
  border-radius: 20px;
  overflow: hidden;
  opacity: 0;
  transition: all 0.6s ease-in-out;
}

.button-img--active {
  height: 150px;
  margin: 5% auto;
  opacity: 1;
}

.button:hover {
  outline: 2px solid #a3b18a;
  background-color: #a3b18a;
  outline-offset: 5px;
}

.button:active {
  outline-offset: 8px;
}
<div class="wrapper">
  <div class="js-button button button-1" data-value="1">
    Click!
    <div class="js-button-img button-img">
      <img class="js-img" alt="No image!" />
    </div>
    <div class="js-button-result button-result">
      Result
    </div>
  </div>
  <div class="js-button button button-2" data-value="2">
    Click!
    <div class="js-button-img button-img">
      <img class="js-img" alt="No image!" />
    </div>
    <div class="js-button-result button-result">
      Result
    </div>
  </div>
  <div class="js-button button button-3" data-value="3">
    Click!
    <div class="js-button-img button-img">
      <img class="js-img" alt="No image!" />
    </div>
    <div class="js-button-result button-result">
      Result
    </div>
  </div>
</div>

2

Answers


  1. btns.forEach((i) => {
      i.addEventListener("click", function() {
        let dataValue = event.target.getAttribute("data-value");
    
        /*if (!isOpen) {
        //btn.classList.add("button--active"); 
        i.classList.add("button--active"); 
        img.classList.add("button-img--active");
        result.classList.add("button-result--true");
        //draw.classList.add("draw--open")
        isOpen = true;
        const rand = Math.floor(Math.random() * fruits.length);
        result.innerHTML = fruits[rand].name;
        imgSrc.src = fruits[rand].img;
        
      } else {
        // btn.classList.remove("button--active");
        i.classList.remove("button--active");
        img.classList.remove("button-img--active");
        result.classList.remove("button-result--true");
        //draw.classList.remove("draw--open")
        isOpen = false;
      }
        */
      });
    });
    

    in your btns.forEach body, you use btn.classList.add("button--active"); , the btn is not current element, it will not change with the iterator. you can use i to replace btn

    Login or Signup to reply.
  2. I would suggest using a delegated event listener, bound to the parent DIV element (.wrapper) and inspect the event.target to determine if the event originated on the button. From that point the event handler will function for all buttons rather than a single button that might be identified using querySelector

    You can simplify some of the above code by using the toggle method for the classList operations rather than the isOpen logic block.

    The following does, I think, what you were trying to do(?) but uses a single listener. Perhaps it will help.

    const color = [
      "red", "green", "blue", "aqua", "black", "purple", "yellow"
    ];
    const fruits = [{
        type: "fruit",
        name: "orange",
        img: "https://t4.ftcdn.net/jpg/01/02/31/01/240_F_102310122_TyKkml1yRFle2IGtD2fAUrZLtixIGJqa.jpg"
      },
      {
        type: "fruit",
        name: "apple",
        img: "https://t3.ftcdn.net/jpg/03/10/32/02/240_F_310320273_I9rR1l7918MJoZ0GRHGIBgZl9F9ShEXq.jpg"
      },
      {
        type: "fruit",
        name: "banana",
        img: "https://t3.ftcdn.net/jpg/02/36/07/60/240_F_236076021_Lf2nHzSUcTxNGdG7hap6PjJNDwHT1VfC.jpg"
      },
      {
        type: "fruit",
        name: "mango",
        img: "https://t4.ftcdn.net/jpg/00/52/87/43/240_F_52874381_Ucxx67h9KLuxSXiNGcsmHfSjAuqRXqDr.jpg"
      },
      {
        type: "fruit",
        name: "kiwi",
        img: "https://t4.ftcdn.net/jpg/00/68/65/13/240_F_68651370_CVcQlAdJqvxtL8bIUm70UP1HwnFXOblQ.jpg"
      },
      {
        type: "fruit",
        name: "strawberries",
        img: "https://t4.ftcdn.net/jpg/00/84/36/81/240_F_84368117_irN0O3akL7ALdMe17ZtxH6nya1cHiG5H.jpg"
      },
      {
        type: "fruit",
        name: "grape",
        img: "https://t4.ftcdn.net/jpg/00/70/94/63/240_F_70946377_VJXdpJqld6XOsOTO6lt95ieZSxGO0faM.jpg"
      }
    ];
    
    
    
    const d = document;
    
    // class names used
    const css = {
      'bttn': 'js-button',
      'active': 'button--active',
      'bttnresult': 'js-button-result',
      'bttnrestrue': 'button-result--true',
      'img': 'button-img--active'
    };
    
    // parent node to bind delegated listener to
    const wrapper = d.querySelector('div.wrapper');
    
    // create a pseudo random number between low & high bounds
    const mt_rand = (a, b) => Math.floor(Math.random() * (b - a + 1) + a);
    
    // use the random number to return a random item from an input array
    const getarray = (src) => src[mt_rand(0, src.length - 1)];
    
    
    let is_open = false; // global boolean to indicate panel open status
    let img_src; // store reference to selected fruit image for use when closing panel
    
    
    wrapper.addEventListener('click', e => {
      if (e.target instanceof HTMLDivElement && e.target.classList.contains(css.bttn) && e.target.parentNode == wrapper) {
        // find the dataset attribute(s)
        let value = Number( e.target.dataset.value );
        // find the IMG element
        let img = e.target.querySelector('img');
        // find the div that will display the fruit name
        let result = e.target.querySelector(`.${css.bttnresult}`);
        // select a random fruit ( or other type of "thing" )
        let fruit = getarray(fruits);
    
        // toggle the class for current button/panel and associated child elements
        e.target.classList.toggle(css.active);
    
        result.classList.toggle(css.bttnrestrue);
        result.textContent = !is_open ? fruit.name : '';
    
        img.parentNode.classList.toggle(css.img);
        img.src = !is_open ? fruit.img : img_src;
        img.alt = !is_open ? fruit.name : 'No image!';
    
        console.info('Panel:%d is open:%s', value, !is_open)
    
        // toggle the global boolean variable to indicate open status
        is_open = !is_open;
        img_src = fruit.img;
      }
    });
    * {
      box-sizing: border-box;
      font-size: 16px;
      letter-spacing: 1px;
      font-family: Montserrat, sans-serif;
    }
    
    body {
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      margin: 0;
      padding: 0;
    }
    
    .wrapper {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      margin: auto;
      position: relative;
      width: 30vw;
      height: 30vh;
    }
    
    .button {
      padding: 5% 0;
      margin: 10px 0;
      width: 100%;
      height: auto;
      text-align: center;
      border-radius: 0 20px;
      background-color: #dad7cd;
      user-select: none;
      transition: 100ms ease-in-out;
      outline: 0;
      cursor: pointer;
    }
    
    .button--active {
      position: absolute;
      top: 0;
      left: 0;
      margin: 0;
      height: 100%;
    }
    
    .button-result {
      display: none;
    }
    
    .button-result--true {
      display: block;
    }
    
    .button-img {
      width: 150px;
      height: 0;
      margin: 0 auto;
      display: flex;
      justify-content: center;
      border-radius: 20px;
      overflow: hidden;
      opacity: 0;
      transition: all 0.6s ease-in-out;
    }
    
    .button-img--active {
      height: 150px;
      margin: 5% auto;
      opacity: 1;
      z-index: 100;
    }
    
    .button:hover {
      outline: 2px solid #a3b18a;
      background-color: #a3b18a;
      outline-offset: 5px;
    }
    
    .button:active {
      outline-offset: 8px;
    }
    <div class="wrapper">
      <div class="js-button button button-1" data-value="1">
        Click!
        <div class="js-button-img button-img">
          <img class="js-img" alt="No image!" />
        </div>
        <div class="js-button-result button-result"></div>
      </div>
    
      <div class="js-button button button-2" data-value="2">
        Click!
        <div class="js-button-img button-img">
          <img class="js-img" alt="No image!" />
        </div>
        <div class="js-button-result button-result"></div>
      </div>
    
      <div class="js-button button button-3" data-value="3">
        Click!
        <div class="js-button-img button-img">
          <img class="js-img" alt="No image!" />
        </div>
        <div class="js-button-result button-result"></div>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search