kieranstartup kieranstartup - 3 months ago 16
Javascript Question

Apply random class to multiple groups of elements with no repeat

I have multiple groups of divs that I need to apply a random class to with no repeats in each of the groups. Once I've done this, I then need to 'reset' the Array back to the original values, and move onto the next group of divs where I apply a random class to each div again.

The idea is to get to something that looks like this:

<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image left">
<div class="mini-thumbnail-individual-image centre">
<div class="mini-thumbnail-individual-image right">
</div>

<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image centre">
<div class="mini-thumbnail-individual-image right">
<div class="mini-thumbnail-individual-image left">
</div>

<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image right">
<div class="mini-thumbnail-individual-image left">
<div class="mini-thumbnail-individual-image centre">
</div>


etc.

I've shamelessly taken code taken from another stackoverflow question to do with this question, but I can't figure out how to get it to work over all my elements, instead of the first three.

Here's the jQuery:

function shuffle(obj) {
var l = obj.length,
i = 0,
rnd,
tmp;

while (i < l) {
rnd = Math.floor(Math.random() * i);
tmp = obj[i];
obj[i] = obj[rnd];
obj[rnd] = tmp;
i += 1;
}
}

var classes = ["centre", "left", "right"];
shuffle(classes);

jQuery(".mini-thumbnail-individual-image").each(function() {
jQuery(this).addClass(classes.pop());
});


And here's a basic outline of my div structure – I have multiples of these which I want to iterate over and apply the random class to each
<div class="mini-thumbnail-individual-image">


HTML:

<div class="col-1-6">
<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image">
<img class="mini-thumbnail-image" src="" />
</div>
<div class="mini-thumbnail-individual-image">
<img class="mini-thumbnail-image" src="" />
</div>
<div class="mini-thumbnail-individual-image">
<img class="mini-thumbnail-image" src="" />
</div>
</div>
</div>


I think I need to create a loop that looks is triggered after each iteration over the array, and once it spots the array is empty, I need to push the class names back in, and then loop over the next group of divs, until each group of divs has a random class applied, but maybe there is a simpler way that I haven't thought of yet.

Thanks in advance!

Answer

You're on the right track.

Without speaking of methods to optimize the code, here's (one) way to get quickly to where you need to be:

function shuffle(obj) {
    var l = obj.length,
        i = 0,
        rnd,
        tmp;

    while (i < l) {
        rnd = Math.floor(Math.random() * i);
        tmp = obj[i];
        obj[i] = obj[rnd];
        obj[rnd] = tmp;
        i += 1;
    }
}

// declare OUTSIDE the function for correct scope
var classes;

// Simple function to set up the classes variable and shuffle.
function setUpClasses() {
    classes = ["centre", "left", "right"];
    shuffle(classes);
}

jQuery(".mini-thumbnail-individual-image").each(function() {
    // Check if classes is set / empty.  If so, set up the classes again.
    if (!classes  || classes.length < 1) {
        setUpClasses();
    }
    jQuery(this).addClass(classes.pop());
});

If you want to look at cleaner / briefer ways to shuffle the array, this article has some other techniques. Here's one of them:

yourArray.sort(function() { return 0.5 - Math.random() });

So you could literally remove your shuffle function, and just do this:

function setUpClasses() {
    classes = ["centre", "left", "right"];
    classes.sort(function() { return 0.5 - Math.random() });
}

Or, if you wanted maximum brevity:

function setUpClasses() {
    classes = ["centre", "left", "right"].sort(function() { return 0.5 - Math.random() });
}

Here is a working Fiddle

Comments