3

I have a large html document where each part is separated by <section> </section> labels, for example:

<!DOCTYPE html>
<html>
<body>
<section>
<h1>A file</h1>

<form action="/action_page.php">
  <p>Please select your gender:</p>
  <input type="radio" id="male" name="gender" value="male">
  <label for="male">Male</label><br>
  <input type="radio" id="female" name="gender" value="female">
  <label for="female">Female</label><br>
  <input type="radio" id="other" name="gender" value="other">
  <label for="other">Other</label>
</section>
  <br>  
<section>
  <p>Please select your age:</p>
  <input type="radio" id="age1" name="age" value="30">
  <label for="age1">0 - 30</label><br>
  <input type="radio" id="age2" name="age" value="60">
  <label for="age2">31 - 60</label><br>  
  <input type="radio" id="age3" name="age" value="100">
  <label for="age3">61 - 100</label><br><br>
</section>
  <input type="submit" value="Submit">
</form>

</body>
</html>

How can I randomly shuffle the order of the sections? that is, I would like to each time the user loads the page the order of the section randomly switch?

aywoki
  • 199
  • 11

3 Answers3

2

To sort randomly you can use the sort() method along with Math.random() to reorder the elements. Also note that your HTML would need to be changed slightly to make the logic simpler - primarily by adding a new div around the section elements to contain them, and also ensuring that the <form> element wraps all the section content. Try this:

let $container = $('.sections');
$container.find('section').sort((a, b) => Math.random() > 0.5 ? 1 : -1).prependTo($container);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="/action_page.php">
  <h1>A file</h1>
  <div class="sections">
    <section>
      <p>Please select your gender:</p>
      <input type="radio" id="male" name="gender" value="male">
      <label for="male">Male</label><br>
      <input type="radio" id="female" name="gender" value="female">
      <label for="female">Female</label><br>
      <input type="radio" id="other" name="gender" value="other">
      <label for="other">Other</label>
    </section>
    <section>
      <p>Please select your age:</p>
      <input type="radio" id="age1" name="age" value="30">
      <label for="age1">0 - 30</label><br>
      <input type="radio" id="age2" name="age" value="60">
      <label for="age2">31 - 60</label><br>
      <input type="radio" id="age3" name="age" value="100">
      <label for="age3">61 - 100</label><br><br>
    </section>
  </div>
  <input type="submit" value="Submit">
</form>
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • Thanks for the help, is there any way of doing it with out adding more divs? The problem is that when I add the new divs they break my document – aywoki Mar 04 '21 at 14:17
  • 1
    It may well be possible, but the JS would be a rather hacky, brittle mess. I'd suggest you spend the time fixing the layout. My assumption would be that the additional `div` has affected some CSS rules which you simply need to update. – Rory McCrossan Mar 04 '21 at 14:21
  • Not only the CSS, more javascript logic to control the views, and other things, such like the structure of the website. For example, in my real case it added all the views in each view, for example in view 1 I had 3 questionnaires, now I have like 10 – aywoki Mar 04 '21 at 14:22
1

Here's a solution that does not use jquery.

  • Add unique ids to each section
  • make a list of ids and shuffle them up (I use Knuth shuffle)
  • traverse the shuffled array and:
    • remove the section belonging to the current id (could be anywhere in the current ordering)
    • prepend the section belonging to the current id to the html (this produces a random ordering)
<!DOCTYPE html>
<html>
   <body>
      <h1>A file</h1>
      <form action="/action_page.php" id="action-page-form">
         <section id="gender-section">
            <p>Please select your gender:</p>
            <input type="radio" id="male" name="gender" value="male">
            <label for="male">Male</label><br>
            <input type="radio" id="female" name="gender" value="female">
            <label for="female">Female</label><br>
            <input type="radio" id="other" name="gender" value="other">
            <label for="other">Other</label>
         </section>
         <section id="age-section">
            <p>Please select your age:</p>
            <input type="radio" id="age1" name="age" value="30">
            <label for="age1">0 - 30</label><br>
            <input type="radio" id="age2" name="age" value="60">
            <label for="age2">31 - 60</label><br>  
            <input type="radio" id="age3" name="age" value="100">
            <label for="age3">61 - 100</label><br>
         </section>
         <br>
         <input type="submit" value="Submit">
      </form>
   </body>
   <script>
      const sectionList = ["gender-section", "age-section"];
      
      // Fisher-Yates (aka Knuth) Shuffle
      function shuffle(array) {
        var currentIndex = array.length, temporaryValue, randomIndex;
      
        // While there remain elements to shuffle...
        while (0 !== currentIndex) {
      
          // Pick a remaining element...
          randomIndex = Math.floor(Math.random() * currentIndex);
          currentIndex -= 1;
      
          // And swap it with the current element.
          temporaryValue = array[currentIndex];
          array[currentIndex] = array[randomIndex];
          array[randomIndex] = temporaryValue;
        }
      
        return array;
      }
      
      shuffle(sectionList);
      
      var formElement = document.getElementById("action-page-form");
      
      sectionList.forEach(sectionId => {
          var thisSection = document.getElementById(sectionId)
          thisSection.remove();
          formElement.insertBefore(thisSection, formElement.childNodes[0]);
      })
   </script>
</html>

For Knuth Shuffle see: How to randomize (shuffle) a JavaScript array?

Atharva Shukla
  • 2,098
  • 8
  • 21
1

Here's the solution I came up with (while the question was still unanswered). I like the jQuery answer now already posted. But if you didn't want to use jQuery:

window.onload = () => {
    const sections = document.querySelectorAll('section');
    const form = document.querySelector('form');
    sections.forEach(el => form.removeChild(el));
    Array.from(Array(sections.length).keys()).sort(() => Math.random() - 0.5).forEach((el, i) => form.insertBefore(sections[el], form.childNodes[i]));
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Shuffle</title>
</head>
<body>
    <h1>A file</h1>
    <form action="/action_page.php">
        <section>
            <p>Please select your gender:</p>
            <input type="radio" id="male" name="gender" value="male">
            <label for="male">Male</label><br>
            <input type="radio" id="female" name="gender" value="female">
            <label for="female">Female</label><br>
            <input type="radio" id="other" name="gender" value="other">
            <label for="other">Other</label><br>
        </section>
        <section>
            <p>Please select your age:</p>
            <input type="radio" id="age1" name="age" value="30">
            <label for="age1">0 - 30</label><br>
            <input type="radio" id="age2" name="age" value="60">
            <label for="age2">31 - 60</label><br>
            <input type="radio" id="age3" name="age" value="100">
            <label for="age3">61 - 100</label><br>
        </section>
        <br>
        <input type="submit" value="Submit">
    </form>
</body>
</html>
Adam Sassano
  • 234
  • 1
  • 9
  • This one looks good because I do not need to add more divs and jquery makes it simpler – aywoki Mar 04 '21 at 14:40
  • I caught that in my original answer I ended up removing the submit button. For this I added a div to separate the sections content from the rest of the form content. – Adam Sassano Mar 04 '21 at 15:15
  • 1
    OK, now I edited it again after figuring out how to do without adding an additional div. – Adam Sassano Mar 04 '21 at 15:31