Randomize a sequence of div elements with jQuery

Viewed 54205

I'm trying to do my frist steps with jQuery but I have some trouble to understand how to find a list of child elements from a div parent element. I'm used to work with ActionScript 2 and ActionScript 3 so i could mistake some concept, like what is the better way to randomize a sequence of div elements with jQuery!

I have this simple portion of HTML code:

<div class="band">
    <div class="member">
        <ul>
            <li>John</li>
            <li>Lennon</li>
        </ul>
    </div>
    <div class="member">
        <ul>
            <li>Paul</li>
            <li>McCartney</li>
        </ul>
    </div>
    <div class="member">
        <ul>
            <li>George</li>
            <li>Harrison</li>
        </ul>
    </div>
    <div class="member">
        <ul>
            <li>Ringo</li>
            <li>Starr</li>
        </ul>
    </div>
</div>

I have attempted some way to do that like map .member divs in one array and then changing the sort order but without success.

function setArrayElements (element_parent) {
    var arr = [];
    //alert (element_parent[0].innerHTML);
    for (var i = 0; i < element_parent.children().length; i ++) {
        arr.push (element_parent[i].innerHTML);
    }
}
setArrayElements($(".band"));

when i attempted to alert element_parent[0] i thought to get the first child of my .member list of divs but it isn't.

if i make an alert with element_parent[0].innerHTML i see that:

<div class="member">
    <ul>
        <li>John</li>
        <li>Lennon</li>
    </ul>
</div>
<div class="member">
    <ul>
        <li>Paul</li>
        <li>McCartney</li>
    </ul>
</div>
<div class="member">
    <ul>
        <li>George</li>
        <li>Harrison</li>
    </ul>
</div>
<div class="member">
    <ul>
        <li>Ringo</li>
        <li>Starr</li>
    </ul>
</div>

Why? How can I do to get exactly one of the members like this?

<div class="member">
    <ul>
        <li>Paul</li>
        <li>McCartney</li>
    </ul>
</div>

I'm sure this should be easy but I just don't know how :(

please help
thanks
vittorio


EDIT:

Thanks for the fastness and this various ways to get the selected children, I'll take a note of these ways for the future!
I tried this methods, but it seems I couldn't get the entire div (please tell'me if i mistake something, it' could be too much possible!!).

I shoud get this content:

<div class="member">
    <ul>
        <li>Ringo</li>
        <li>Starr</li>
    </ul>
</div>

but with one of this methods like $("div.band div.member:eq(2)") or the other useful ways, I get this:

alert ($('div.band div.member')[0]);
/* result
<ul>
    <li>Ringo</li>
    <li>Starr</li>
</ul>
*/

so is there a way to get the .member div container too in my node?

5 Answers

Just in case you are ok with doing it without jquery:

/** @param {HTMLElement} parent */
const shuffleChildren = (parent) => {
    const cards = [...parent.children];
    for (const child of cards) {
        const newPlace = Math.floor(Math.random() * cards.length);
        parent.insertBefore(child, cards[newPlace + 1] || null);
    }
};

(an answer unrelated to jquery was closed as duplicate of this one, so posting here)

This solution is inspired by the existing solutions, but uses the Fisher-Yates algorithm for sorting.

This ensures that the elements are randomized fairly, which is important for many use cases.

$.fn.randomizeChildrenOrder = function() {
    this.each(function(){
        let childrenArray = $(this).children().toArray();
        let shuffledChildrenArray = fisherYatesShuffle(childrenArray);
        $(shuffledChildrenArray).detach().appendTo(this);
    });

    return this;
    
    // https://stackoverflow.com/a/2450976/665825
    function fisherYatesShuffle(array){
        let currentIndex = array.length, temporaryValue, randomIndex;
        while (currentIndex !== 0) {
            randomIndex = Math.floor(Math.random() * currentIndex);
            currentIndex -= 1;
            temporaryValue = array[currentIndex];
            array[currentIndex] = array[randomIndex];
            array[randomIndex] = temporaryValue;
        }
        return array;
    }
}

Usage: call the function on the parent element of the elements you need to shuffle. If the elements share the parent element with elements that need to be left alone, add an extra parent around them, so this is no longer the case.

$('.member ul').randomizeChildrenOrder();

Generalized:

$(parentSelector).randomizeChildrenOrder();
Related