skip to Main Content

I’m trying to have a number of DIVs show up on page load but appear in a random order each time – but not entirely random as I’d like them to abide by some rules.

There are two different types of DIVs:

  1. Cards x5 (C)
  2. Image x4 (I)

The rules should be as follows:

  1. The first DIV must always be a C type
  2. Remaining DIVs should alternate between I and C
    (e.g. C, I, C, I, C, I, C, I, C)
  3. All DIVs should be randomly selected from their respective type/array

I’ve tried an array shuffle using jQuery from the solution to another problem (below), but that just puts the DIVs in a random order, not taking into account rules 1 and 2.

var $cont = $('#content'),
  itemsArr = $cont.children().get();

$cont.append(shuffle(itemsArr))

function shuffle(a) {
  var j, x, i;
  for (i = a.length; i; i--) {
    j = Math.floor(Math.random() * i);
    x = a[i - 1];
    a[i - 1] = a[j];
    a[j] = x;
  }
  return a;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row" id="content">
  <div class="col-sm-12 col-md-6 col-lg-4" id="card1">Card #1</div>
  <div class="col-sm-12 col-md-6 col-lg-4" id="card2">Card #2</div>
  <div class="col-sm-12 col-md-6 col-lg-4" id="card3">Card #3</div>
  <div class="col-sm-12 col-md-6 col-lg-4" id="card4">Card #4</div>
  <div class="col-sm-12 col-md-6 col-lg-4" id="card5">Card #5</div>
  <div class="col-sm-12 col-md-6 col-lg-4" id="image1">Image #1</div>
  <div class="col-sm-12 col-md-6 col-lg-4" id="image2">Image #2</div>
  <div class="col-sm-12 col-md-6 col-lg-4" id="image3">Image #3</div>
  <div class="col-sm-12 col-md-6 col-lg-4" id="image4">Image #4</div>
</div>

Would be eternally grateful for any suggestions or help to point me in the right direction.

3

Answers


    1. split the cards and images into two arrays and shuffle them, let’s say shuffledCards and shuffledImages
    2. create a simple decision function to decide if take a Card or Image, like
    const shouldTakeCard = (() => {
      let cardOrImage = 'C';
      return () => { 
        const shouldTakeCard = cardOrImage === 'C'; 
        cardOrImage = 'I';
        return shouldTakeCard;
      }
    })(); 
    

    Then, combine the two lists one by one by the shouldTakeCard response, for example

    while(shuffledCards.length + shuffledImages.length >= 0){
      const item = shouldTakeCard() ? shuffledCards.pop() : shuffledImages.pop();
      $cont.append(item);
    }
    

    So you will start by C type, as shouldTakeCard initialized with C. then it will pick I, C, I … until the array are empty.
    One cation here is the length of the arrays that should be shuffledCards.length === shuffledImages.length + 1

    Login or Signup to reply.
  1. Rough idea is to remove the elements from DOM, shuffle them and append to original parent:

    function shuffle(array) {
      // Fisher-Yates shuffle
      for (let i = array.length - 1; i > 0; i--) {
        let j = Math.floor(Math.random() * (i + 1));
        let temp = array[i];
        array[i] = array[j];
        array[j] = temp;
      }
    }
    $(function() {
      let cards = $("#content > [id^=card]").remove().get();
      let images = $("#content > [id^=image]").remove().get();
      shuffle(cards);
      shuffle(images);
      for (let i = 0; i < cards.length; i++) {
        $("#content").append(cards[i]);
        if (i < images.length) {
          $("#content").append(images[i]);
        }
      }
    });
    body {
      font: medium monospace;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="row" id="content">
      <div class="col-sm-12 col-md-6 col-lg-4" id="card1">Card #1</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="card2">Card #2</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="card3">Card #3</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="card4">Card #4</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="card5">Card #5</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="image1">Image #1</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="image2">Image #2</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="image3">Image #3</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="image4">Image #4</div>
    </div>
    Login or Signup to reply.
  2. Here is a non-JQuery example with some comment. By the way: in your html div#image5 is missing …

    const shuffle = array => {
      let i = array.length;
      while (i--) {
        const ri = Math.floor(Math.random() * (i + 1));
        [array[i], array[ri]] = [array[ri], array[i]];
      }
      return array;
    };
    
    const content = document.querySelector(`#content`);
    // shuffle the cards
    const cards = shuffle([...content.querySelectorAll(`#content [id^=card]`)]);
    const images = shuffle([...content.querySelectorAll(`#content [id^=image]`)]);
    // this (append/insertAdjacentElement) works because the 
    // shuffled elements are 'life' (so removal not necessary)
    cards.forEach( (card, i) => {
      content.append(card);
      // append image after the card (if aplicable)
      if (images[i]) {
        card.insertAdjacentElement(`afterend`, images[i]);
      }
    });
    body {
      font: medium monospace;
    }
    
    [id^="image"] {
      margin-left: 5px;
    }
    <div class="row" id="content">
      <div class="col-sm-12 col-md-6 col-lg-4" id="card1">Card #1</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="card2">Card #2</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="card3">Card #3</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="card4">Card #4</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="card5">Card #5</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="image1">Image #1</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="image2">Image #2</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="image3">Image #3</div>
      <div class="col-sm-12 col-md-6 col-lg-4" id="image4">Image #4</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search