1

Is there a possibility to shuffle table rows and make them appear at random each time we click a button/icon (except for the first one with a header)? Something like w3schools' "How To Sort a Table" (https://www.w3schools.com/howto/howto_js_sort_table.asp) but so that the table would be sorted randomly.

The other possibility is to use JavaScript Array Sort but I wouldn't know how to make table rows appear as contents of an array.

https://jsfiddle.net/17bjxgfa/1/

I'd prefer vanilla JS solutions rather than jQuery.

Here is an exemplary table that we could work on:

.table-div {
  padding-top: 1rem;
}
<div class="table-div">
  <table id="myTable">
    <tr>
      <th class="button"><button class="my-btn" type="button" onclick="sortTable()">
        shuffle</button></th>
      <th>Text:</th>
      <th></th>
    </tr>

    <tr>
      <td class="left">Some text 1</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
                check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 2</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
                check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 3</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
                check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 4</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
                check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 5</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
                check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 6</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
                check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 7</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
                check</button></td>
    </tr>
mplungjan
  • 169,008
  • 28
  • 173
  • 236

2 Answers2

6

You can do the following:

  1. Get all of the rows of the table using lookups like document.getElementsByTagName or if you want to have a bit more specificity - document.querySelectorAll.
  2. These return an HTMLCollection, so you can just convert it into an array.
  3. Shuffle the array.
  4. Add it back to the table - since a node cannot appear twice in the DOM, that will move them, thus you don't have to manually remove them first.

function sortTable() {
  //get the parent table for convenience
  let table = document.getElementById("myTable");

  //1. get all rows
  let rowsCollection = table.querySelectorAll("tr");

  //2. convert to array
  let rows = Array.from(rowsCollection)
    .slice(1); //skip the header row

  //3. shuffle
  shuffleArray(rows);

  //4. add back to the DOM
  for (const row of rows) {
    table.appendChild(row);
  }
}


/**
 * Randomize array element order in-place.
 * Using Durstenfeld shuffle algorithm.
 * from: https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array/12646864#12646864
 */
function shuffleArray(array) {
  for (var i = array.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
}
.table-div {
  padding-top: 1rem;
}
<div class="table-div">
  <table id="myTable">
    <tr>
      <th class="button"><button class="my-btn" type="button" onclick="sortTable()">
    shuffle</button></th>
      <th>Text:</th>
      <th></th>
    </tr>

    <tr>
      <td class="left">Some text 1</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
            check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 2</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
            check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 3</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
            check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 4</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
            check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 5</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
            check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 6</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
            check</button></td>
    </tr>

    <tr>
      <td class="left">Some text 7</td>
      <td><input type="text"></td>
      <td class="right">more text.</td>
      <td class="button"><button class="my-btn" type="button">
            check</button></td>
    </tr>
VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • Thanks, works great in the example. Would it be possible to keep two rows together and not separate them during the shuffle? I have some rows that appear beneath the original one only if you click a button next to the original row. When I apply this code, the rows naturally get separated. – Krzysztof Delestowicz Sep 12 '19 at 14:01
  • Nevermind, I wrapped them in tbody and changed the et rowsCollection = table.querySelectorAll("tbody") – Krzysztof Delestowicz Sep 12 '19 at 14:59
  • Point 4 is an eye opener. – ctaleck Sep 12 '19 at 20:05
  • @VLAZ Was looking for an same answer, but my question is What if there are two (or more {unknown}) tables in the page? And I want all the rows in their particular tabke to be shuffled. ___ Or - Shall I post a new question for it with the same answered code? – paran May 02 '20 at 18:09
  • 1
    @paran no real problem with that. You can either target them individually through selectors or if you want to shuffle all tables at once, then you can just [go through each and shuffle](https://jsbin.com/widomil/edit?html,js,output). – VLAZ May 02 '20 at 18:19
  • @VLAZ Thanks, this is exactly what I was looking for and worked perfectly! – DaveArmstrong Feb 25 '22 at 22:46
0

Well, as far I could help without making all your code, is to get you going with a simple and legible logic...

Like you said, you want to shuffle the rows, so, for that you need to get all your rows. You can do it with var tableElms = document.getElementById("myTable").children; and filter it to get only the rows that you want.

After that you can create a list with the results and then sort it with var sortedList = filteredList.sort(); after that change your table dom (clean it) and append the new rows document.getElementById('myTable').appendChild(sortedList);

Hope I could help you :)

JPeter
  • 219
  • 1
  • 14
  • OP doesn't want to sort but shuffle. `sort` will not help unless you pre-process the array to assign random sort orders to each item and then use `sort` to sort on them. – VLAZ Sep 12 '19 at 13:55