Treehouse: Grow your CSS skills. Land your dream job.

Last updated on:

Shuffle DOM Elements

This is from James Padolsey. Check out his article for a pure JavaScript technique as well.

Plugin

(function($){
 
    $.fn.shuffle = function() {
 
        var allElems = this.get(),
            getRandom = function(max) {
                return Math.floor(Math.random() * max);
            },
            shuffled = $.map(allElems, function(){
                var random = getRandom(allElems.length),
                    randEl = $(allElems[random]).clone(true)[0];
                allElems.splice(random, 1);
                return randEl;
           });
 
        this.each(function(i){
            $(this).replaceWith($(shuffled[i]));
        });
 
        return $(shuffled);
 
    };
 
})(jQuery);

Usage

Target elements, call shuffle.

$('ul#list li').shuffle();

Comments

  1. Vladimir Komarov
    Permalink to comment#

    Thank you for this post – it’s useful. I’m going to read again jQuery docs about map, get and replaceWith, and about native js splice as well.

  2. Alexandre Cárdenas
    Permalink to comment#

    Your web design is awesome. I love it. Congratulations!

    Alex

  3. Kiran
    Permalink to comment#

    Great piece. Thank You.

  4. Nitin
    Permalink to comment#

    Great plugin. Thanks a million.

  5. Trevor
    Permalink to comment#

    Anyone have an idea how to make this work if you want to randomize say two different lists on the same page? Yes I could assign a different ID to each list then suffle them like so:

    $(‘ul#list1 li’).shuffle();
    $(‘ul#list2 li’).shuffle();

    But what I’d like to be able to do is just go:
    $(‘ul.randlist li’).shuffle();

    And that would then randomize just the list items within that UL, even if I had multiple lists on a page. Right now what it does it randomizes all the list items across ALL the ul’s with that class. Which is not what I want as the list items need to stay with their parent.

  6. Jesse

    Trevor, this is simple using each()

    $('ul.randlist').each(function(){
    $(this).find('li').shuffle()
    })

  7. Jesse

    Also, I noticed that this plugin will break references to the original elements (since it actually copies them). I wrote a version that actually shuffles the original elements.

    “`
    (function($){

    $.fn.shuffle = function() {
    
      var elements = this.get()
      var copy = [].concat(elements)
      var shuffled = []
      var placeholders = []
    
      // Shuffle the element array
      while (copy.length) {
        var rand = Math.floor(Math.random() * copy.length)
        var element = copy.splice(rand,1)[0]
        shuffled.push(element)
      }
    
      // replace all elements with a plcaceholder
      for (var i = 0; i < elements.length; i++) {
        var placeholder = document.createTextNode('')
        findAndReplace(elements[i], placeholder)
        placeholders.push(placeholder)
      }
    
      // replace the placeholders with the shuffled elements
      for (var i = 0; i < elements.length; i++) {
        findAndReplace(placeholders[i], shuffled[i])
      }
    
      return $(shuffled)
    
    }
    
    function findAndReplace(find, replace) {
      find.parentNode.replaceChild(replace, find)
    }
    

    })(jQuery)
    “`

  8. Andrew Van Wart

    Excellent tip! I would just add that if you have nested list items (ul ul li) within your parent ul#list, in order to only randomize the parent list items, use this code to initialize:

    $('ul#list > li').shuffle();
  9. Trevor

    Thanks Jesse! Wow, that was an easy fix, I clearly need to learn jQuery better. And good stuff with your updated shuffle function!

    I just wondered what exactly you meant by the function “will break references to the original elements”?

  10. Markus
    Permalink to comment#

    license?

  11. Rahul
    Permalink to comment#

    What is the minimum number of item required?

  12. Shahab

    Nice solution :)
    I’ve made a small change to make a plugin to randomly remove some items:
    (function($) {
    $.fn.randomRemove = function(n) {
    var allElems = this.get(),
    getRandom = function(max) {
    return Math.floor(Math.random() * max);
    };
    if (allElems.length > n) {
    while (n > 0) {
    var random = getRandom(allElems.length);
    $(allElems[random]).remove();
    allElems.splice(random, 1);
    n–;
    }
    }
    return $(allElems);
    };
    })(jQuery);

  13. Aamir Afridi
    Permalink to comment#

    Or just try this

    var parent = $("#shuffle");
    var divs = parent.children();
    while (divs.length) {
            parent.append(divs.splice(Math.floor(Math.random() * divs.length), 1)[0]);
    }
    

Leave a Comment

Posting Code

We highly encourage you to post problematic HTML/CSS/JavaScript over on CodePen and include the link in your post. It's much easier to see, understand, and help with when you do that.

Markdown is supported, so you can write inline code like `<div>this</div>` or multiline blocks of code in in triple backtick fences like this:

```
<script>
  function example() {
    element.innerHTML = "<div>code</div>";
  }
</script>
```