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. User Avatar
    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. User Avatar
    Alexandre Cárdenas
    Permalink to comment#

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

    Alex

  3. User Avatar
    Kiran
    Permalink to comment#

    Great piece. Thank You.

  4. User Avatar
    Nitin
    Permalink to comment#

    Great plugin. Thanks a million.

  5. User Avatar
    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. User Avatar
    Jesse

    Trevor, this is simple using each()

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

  7. User Avatar
    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. User Avatar
    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. User Avatar
    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. User Avatar
    Markus
    Permalink to comment#

    license?

  11. User Avatar
    Rahul
    Permalink to comment#

    What is the minimum number of item required?

  12. User Avatar
    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. User Avatar
    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]);
    }
    
  14. User Avatar
    binaryum
    Permalink to comment#

    Nice one @jess. Really helped, the other options were breaking the references, therefore, breaking my app!
    Thanks again!

  15. User Avatar
    Donnie Kerr
    Permalink to comment#

    Thank you! Helped me out big time!

  16. User Avatar
    rogez
    Permalink to comment#

    works as a jewel. thanks!

Submit a Comment

Posting Code

You may write comments in Markdown. This makes code easy to post, as you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences (```) with double new lines before and after.

Code of Conduct

Absolutely anyone is welcome to submit a comment here. But not all comments will be posted. Think of it like writing a letter to the editor. All submitted comments will be read, but not all published. Published comments will be on-topic, helpful, and further the discussion or debate.

Want to tell us something privately?

Feel free to use our contact form. That's a great place to let us know about typos or anything off-topic.

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag