How to display/hide info depending on random of IDs in javascript?

Viewed 41

This is a little complicated to explain, but I'll try my best. I have a JSON file full of data that my javascript and HTML pull from, depending on what options you select.

Basically, the number of displayed items can be like 1-100. There is also a button that toggles show more or less info about each item. Each item will call on this function, to toggle the show more or show less.

// THIS VAR IS THE NUMBER OF ITEMS DISPLAYED (CAN BE 1-100)
var numberList;

function showSpellInfo(id) {
  // ARRAYLIST FOR IDS AND RANDOM NUMBER AMOUNT
  var numberList = [0];
  var spellContentList = ["spellContent0"];
  var showMoreButtonList = ["showMoreButton0"];
  var showLessButtonList = ["showLessButton0"]; 
  
  // BLUIDS THE ARRAYS
  for (let i = 0; i < listNumber; i++){
      var newVal = i + 1;
      numberList.push(newVal)
      spellContentList.push("spellContent" + newVal);
      showMoreButtonList.push("showMoreButton" + newVal);
      showLessButtonList.push("showLessButton" + newVal); 
}
  // BUTTON TO SHOW MORE INFO
  for (let x = 0; x < numberList.length; x++)
  if (document.getElementById(showMoreButtonList[x]).onclick = true){
      document.getElementById(showMoreButtonList[x]).style.display="none";
      document.getElementById(showLessButtonList[x]).style.display="inline-block";
      document.getElementById(spellContentList[x]).style.display="block";
  }   
} 

My issue is the when I click one button it opens up all of them.

What I want, is when I click on an ID for it only open up the info for that ID. The problem is could be 1 or 100 ids. Is there an easier way to do this am I making this too complicated?

1 Answers

This won't work because you're trying to create a listener in the wrong way. But there's also a better way to structure this without all those messy ID's. Make it dynamic by using the show more/less button listener to find it's relevant element to effect. Take the following as an example since I wasn't able to determine how your data is set up.

var numberList;
let json = [{
  title: 'title1',
  description: 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.'
}, {
  title: 'title2',
  description: 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.'
}];

// the set up
let items = document.querySelector('.items');
const tpl = (item) => `<div class='item'><h3>${item.title}</h3><div class='desc'>${item.description}</div><button class='more-less'>Show More</button></div>`;
json.forEach(item => items.innerHTML += tpl(item));

// the event listener fires after the DOM has loaded
window.addEventListener('DOMContentLoaded', () => {
  // we listen to document for any click
  document.addEventListener('click', e => {
    // we test that the click came from one of our more-less buttons
    // e.target is the item that was clicked
    if (e.target.classList.contains('more-less')) {
      // we find the closest container element and set a class on it that will show or hide the data
      e.target.closest('.item').classList.toggle('viewing')
      // to change the button text, we need to know if it's currently showing
      let isopen = e.target.closest('.item').classList.contains('viewing')
      e.target.innerText = isopen ? 'Show Less' : 'Show More';
    }
  })
})
.item .desc {
  display: none;
}

.item.viewing .desc {
  display: block;
}
<div class='items'></div>

Related