1

Trying to shuffle a container's (a div) DOM elements (other divs) with a particular class name ("div"). Other divs ("extra") should stay put in the place where they are.

So far I have used the modified shuffle algorithm from link

The code I have almost did the trick but the "Extra" div is appended at the bottom of the stack while it's supposed to stay atop.

let divs       = document.getElementsByClassName("div")
let divsNumber = divs.length;
let divver     = document.getElementsByClassName("divver")[0]

function shuffler() {
  for (var i = divsNumber; i >= 0; i--) {
    if (!divver.children[i].classList.contains("div")) {
      divver.appendChild(divver.children[Math.random() * i | 0]);
    }
  }
}
<div class="divver">
  <div class="extra">  Extra  </div>
  <div class="div">    1  </div>
  <div class="div">    2  </div>
  <div class="div">    3  </div>
  <div class="div">    4  </div>
  <div class="div">    5  </div>
</div>

<button onclick="shuffler()" id="shuffles">Shuffle 'em</button>

Any hints greatly appreciated.

Mister Jojo
  • 20,093
  • 6
  • 21
  • 40
  • Wrap extras and shuffled divs to separate wrappers, shuffle only needed elements – Justinas Mar 25 '22 at 12:59
  • Use [`element.querySelectorAll`](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll) to get the wanted divs from `#divver`. No need for checking anything, just append randomly. – Teemu Mar 25 '22 at 13:16
  • Will the html *always* have only one static `extra` div at index `0`? Or could there be multiple `extra` divs at various indices? If the latter, I would modify the question to have at least one additional `extra` at another position in the child elements – Eric Phillips Mar 25 '22 at 13:19
  • 1
    Teemu, yours as well as Mr Jojo's below, are the ones with the least amount of code modifications needed which also steered me on the right track. Thanks. – Greg Greansky Mar 25 '22 at 14:25
  • For a better readability it is preferable to use `Math.floor(x)` instead of `x | 0` – Yukulélé Mar 29 '22 at 15:14

2 Answers2

2

const
  divver      = document.querySelector('div.divver')
, ShuffleDivs = divver.querySelectorAll('div.div') // just select this group
  ;
document.querySelector('button#shuffles').onclick = () =>
  {
  for (let i = ShuffleDivs.length; i >= 0; i--)
    {
    divver.appendChild(ShuffleDivs[Math.random() * i | 0])
    }
  }
<div class="divver">
  <div class="extra">  Extra  </div>
  <div class="div">    1  </div>
  <div class="div">    2  </div>
  <div class="div">    3  </div>
  <div class="div">    4  </div>
  <div class="div">    5  </div>
</div>

<button id="shuffles">Shuffle 'em</button>
Mister Jojo
  • 20,093
  • 6
  • 21
  • 40
  • Mister Jojo, yours as well as Teemu's above, are the ones with the least amount of code modifications needed which also steered me on the right track. Thanks. Unfortunately, I have too few points on stackoverflow myself to grant them to contributors. – Greg Greansky Mar 25 '22 at 14:28
-1

Since you wish to leave the first element out of the shuffle and arrays of elements are 0 based you can change * i | 0] to * i | 1]

let divs       = document.getElementsByClassName("div")
let divsNumber = divs.length;
let divver     = document.getElementsByClassName("divver")[0]

function shuffler() {
  for (var i = divsNumber; i >= 0; i--) {
    if (!divver.children[i].classList.contains("div")) {
      divver.appendChild(divver.children[Math.random() * i | 1]);
    }
  }
}
<div class="divver">
  <div class="extra">  Extra  </div>
  <div class="div">    1  </div>
  <div class="div">    2  </div>
  <div class="div">    3  </div>
  <div class="div">    4  </div>
  <div class="div">    5  </div>
</div>

<button onclick="shuffler()" id="shuffles">Shuffle 'em</button>
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
  • Should have thought of that myself. Brilliant! Thanks. – Greg Greansky Mar 25 '22 at 14:31
  • I down vote because your example doesn't work: it does a rotate in place of shuffle. `Math.random() * i | 1` will always return a odd number – Yukulélé Mar 29 '22 at 02:01
  • @Yukulélé Fair enough on that point - I focused on the question "leave that one div alone and out of scope" vs the validity of the OP's shuffle algorithm. I will leave this in place just for that reason. FWIW I would have likely done this differently; especially the markup than the OP but simply answered the basic question. – Mark Schultheiss Mar 29 '22 at 13:56
  • @MarkSchultheiss Unfortunately the code you provide does not give the expected behavior. – Yukulélé Mar 29 '22 at 15:11
  • `floatNumber | 0` proceed to return the integer part of the float. https://stackoverflow.com/questions/34077449/fastest-way-to-cast-a-float-to-an-int-in-javascript – Mister Jojo Mar 29 '22 at 21:17