skip to Main Content

Hoping someone can help with this…

I am trying to set up a page to randomly display Div content from several Div blocks onClick. I have some base code I found and have been playing with but I can’t work out how to modify it to display multiple Divs at once.

var random = document.getElementsByClassName('random')[0];
var menuCovers = document.getElementsByClassName('menu_cover2');

function openRandomMenu() {

  for (var i = 0; i < menuCovers.length; i++) {

    if (menuCovers[i].classList.contains('visible')) {
      var skip = i;
      menuCovers[i].classList.remove('visible');
      menuCovers[i].classList.add('invisible');
    }
  }

  var randomNumber = skip;

  while (randomNumber === skip) {
    randomNumber = Math.floor(Math.random() * menuCovers.length);
  }

  menuCovers[randomNumber].classList.remove('invisible');
  menuCovers[randomNumber].classList.add('visible');
}

random.addEventListener('click', openRandomMenu, false);
.visible {
  display: block;
}

.invisible {
  display: none;
}

.bloc {
  padding: 20px;
  border: 1px solid #ff0000;
}

.offset {
  margin-top: 200px;
}
<div>
  <p class="random bloc">Random</p>
  <div class="menu_cover invisible bloc">One</div>
  <div class="menu_cover invisible bloc">Menu two</div>
  <div class="menu_cover invisible bloc">Menu three</div>
  <div class="menu_cover invisible bloc">Menu four</div>
  <div class="menu_cover invisible bloc">Menu five</div>
  <div class="menu_cover invisible bloc">Menu six</div>
</div>

<div>
  <div class="menu_cover2 invisible bloc offset">Menu Xone</div>
  <div class="menu_cover2 invisible bloc offset">Menu Xtwo</div>
  <div class="menu_cover2 invisible bloc offset">Menu Xthree</div>
  <div class="menu_cover2 invisible bloc offset">Menu Xfour</div>
  <div class="menu_cover2 invisible bloc offset">Menu Xfive</div>
  <div class="menu_cover2 invisible bloc offset">Menu Xsix</div>
</div>

With the above, as per the original example, I can get one of the Div blocks to display, in this case ‘menu_cover2’ but not the first.

Any ideas out there?

2

Answers


  1. You mean something like this?

    I am assuming the two sets have the same number of divs

    const randomNumbers = (n, min, max) => Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1) + min));
    
    const covers = document.querySelectorAll(".menu_cover");
    const covers2 = document.querySelectorAll(".menu_cover2");
    
    document.querySelector('.random')
      .addEventListener('click', () => {
        covers.forEach(cover => cover.hidden = true);
        covers2.forEach(cover => cover.hidden = true);
        const arr = randomNumbers(2, 0, covers.length-1);
        covers[arr[0]].hidden = false;
        covers2[arr[1]].hidden = false;
      });
    .bloc {
      padding: 20px;
      border: 1px solid #ff0000;
    }
    
    .offset {
      margin-top: 200px;
    }
    <div>
      <p class="random bloc">Random</p>
      <div class="menu_cover bloc" hidden>Menu One</div>
      <div class="menu_cover bloc" hidden>Menu two</div>
      <div class="menu_cover bloc" hidden>Menu three</div>
      <div class="menu_cover bloc" hidden>Menu four</div>
      <div class="menu_cover bloc" hidden>Menu five</div>
      <div class="menu_cover bloc" hidden>Menu six</div>
    </div>
    
    <div>
      <div class="menu_cover2 bloc offset" hidden>Menu Xone</div>
      <div class="menu_cover2 bloc offset" hidden>Menu Xtwo</div>
      <div class="menu_cover2 bloc offset" hidden>Menu Xthree</div>
      <div class="menu_cover2 bloc offset" hidden>Menu Xfour</div>
      <div class="menu_cover2 bloc offset" hidden>Menu Xfive</div>
      <div class="menu_cover2 bloc offset" hidden>Menu Xsix</div>
    </div>

    If the list of divs is of different length we can do this

    const randomNumber = (len) => Math.floor(Math.random() * len);
    
    const covers = document.querySelectorAll(".menu_cover");
    const covers2 = document.querySelectorAll(".menu_cover2");
    
    document.querySelector('.random')
      .addEventListener('click', () => {
        covers.forEach(cover => cover.hidden = true);
        covers2.forEach(cover => cover.hidden = true);
        const ran = randomNumber(covers.length);
        const ran2 = randomNumber(covers2.length);
        covers[ran].hidden = false;
        covers2[ran2].hidden = false;
      });
    .bloc {
      padding: 20px;
      border: 1px solid #ff0000;
    }
    
    .offset {
      margin-top: 200px;
    }
    <div>
      <p class="random bloc">Random</p>
      <div class="menu_cover bloc" hidden>Menu One</div>
      <div class="menu_cover bloc" hidden>Menu two</div>
      <div class="menu_cover bloc" hidden>Menu three</div>
      <div class="menu_cover bloc" hidden>Menu four</div>
      <div class="menu_cover bloc" hidden>Menu five</div>
      <div class="menu_cover bloc" hidden>Menu six</div>
    </div>
    
    <div>
      <div class="menu_cover2 bloc offset" hidden>Menu Xone</div>
      <div class="menu_cover2 bloc offset" hidden>Menu Xtwo</div>
      <div class="menu_cover2 bloc offset" hidden>Menu Xthree</div>
    </div>
    Login or Signup to reply.
    • No need for the .visible rule. Also, use rather a .is-hidden instead of .invisible (which would imply visibility:hidden instead of display:none )
    • use Element.classList.toggle("is-hidden", boolean) on both your sets
    • create a reusable function rand(min, max) that returns a float random number in range 0, NodeList.length, and then use Math.floor(rn) or ~~rn to round it down
    • use <button> is something should be a user-action element, not <p>
    // DOM helpers, utils:
    const el = (sel, par) => (par || document).querySelector(sel);
    const els = (sel, par) => (par || document).querySelectorAll(sel);
    const rand = (min, max) => Math.random() * (max - min) + min;
    
    // Task: toggle random menu covers:
    const elRandom = el(".random");
    const elsCover1 = els(".menu_cover");
    const elsCover2 = els(".menu_cover2");
    
    const openRandomMenu = () => {
      const r1 = Math.floor(rand(0, elsCover1.length));
      const r2 = Math.floor(rand(0, elsCover2.length));
      elsCover1.forEach((elC1, i) => elC1.classList.toggle("is-hidden", i !== r1));
      elsCover2.forEach((elC2, i) => elC2.classList.toggle("is-hidden", i !== r2));
    }
    
    elRandom.addEventListener('click', openRandomMenu, false);
    .blocks > * {
      padding: 20px;
      border: 1px solid #ff0000;
    }
    
    .is-hidden {
      display: none;
    }
    <div class="blocks">
      <button class="random" type="button">Random</button>
      <div class="menu_cover is-hidden">Menu one</div>
      <div class="menu_cover is-hidden">Menu two</div>
      <div class="menu_cover is-hidden">Menu three</div>
      <div class="menu_cover is-hidden">Menu four</div>
      <div class="menu_cover is-hidden">Menu five</div>
      <div class="menu_cover is-hidden">Menu six</div>
    </div>
    
    <div class="blocks offset">
      <div class="menu_cover2 is-hidden">Menu Xone</div>
      <div class="menu_cover2 is-hidden">Menu Xtwo</div>
      <div class="menu_cover2 is-hidden">Menu Xthree</div>
      <div class="menu_cover2 is-hidden">Menu Xfour</div>
      <div class="menu_cover2 is-hidden">Menu Xfive</div>
      <div class="menu_cover2 is-hidden">Menu Xsix</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search