2

I am trying to add classes to three divs with the same class, but I don't want any of the classes being added to repeat.

I have a script to add a class to 1, 2 or 3 divs that display at the same time. The desired effect is to have images displaying as background images, and in my stylesheet I have multiple classes with these images attached to them. These classes are defined and added to the relevant divs in the following code:

Javascript

$(document).ready(function(){
var classes = ["a01", "a02", "a03", "a04", "a05", "a06", "a07", "a08", "a09", "a10", "a11"];

    $(".S").each(function(){
    $(this).addClass(classes[~~(Math.random()*classes.length)]);
    });
});

This code is attached to the following HTML

<div class="brick">
    <div class="blend S"></div>
    <div class="blend S"></div>
    <div class="blend S"></div>
</div>

Here is an example of one result this combination might currently return:

<div class="brick">
    <div class="blend S a01"></div>
    <div class="blend S a01"></div>
    <div class="blend S a06"></div>
</div>

Note the repetition of a01. The following is the desired result:

<div class="brick">
    <div class="blend S a05"></div>
    <div class="blend S a02"></div>
    <div class="blend S a11"></div>
</div>

Here is a live test. If anybody has any jquery advice for how I can circumvent the repetition issue, I would be super grateful. Thank you!

Nimeshka Srimal
  • 8,012
  • 5
  • 42
  • 57
kiatas
  • 31
  • 2
  • 1
    I would recommend just shuffling `classes` (see https://stackoverflow.com/a/12646864/3462319) and then in your `each` give each class the index class from `classes` – depperm Jan 23 '18 at 16:48
  • On Stack Overflow, you are expected to try to **write the code yourself**. After **[doing more research](//meta.stackoverflow.com/questions/261592)** if you have a problem you can **post what you've tried** with a **clear explanation of what isn't working** and providing a **[Minimal, Complete, and Verifiable example](//stackoverflow.com/help/mcve)** within the question itself. – Rob Jan 23 '18 at 16:59
  • Possible duplicate of [Javascript: How to efficiently randomly select array item without repeats](https://stackoverflow.com/questions/17891173/javascript-how-to-efficiently-randomly-select-array-item-without-repeats) – Herohtar Jan 23 '18 at 19:35

3 Answers3

3

The simplest way to ensure no repetition is to shuffle the list and take the 1st 3 elements:

$(document).ready(function(){
    var classes = shuffle(["a01", "a02", "a03", "a04", "a05", "a06", "a07", "a08", "a09", "a10", "a11"]);

    $(".S").each(function(i){
       $(this).addClass(classes[i]);
    });
});

Note that I haven't included the implementation for shuffle.

Gershom Maes
  • 7,358
  • 2
  • 35
  • 55
  • 3
    Here are many [shuffle() implementations](https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array). – Mikey Jan 23 '18 at 16:52
  • Hi there – thank you for the reply Gershom. I've tested this and it works perfectly! For those reading, I preceded the script above with an implementation of a Fisher-Yates (Knuth) shuffle as detailed in the link provided above by Mikey. – kiatas Jan 23 '18 at 17:23
2

You could use splice(). If you call it with the random index and 1 as the length it will remove that single item and return it in an array, which you can take the first (and only) item from. Since it removes the item it uses it won't duplicate any.

$(document).ready(function(){
var classes = ["a01", "a02", "a03", "a04", "a05", "a06", "a07", "a08", "a09", "a10", "a11"];

  $(".S").each(function(){
    $(this).addClass(classes.splice(~~(Math.random()*classes.length), 1)[0]);
  });
});
.blend {
width: 150px;
height: 30px;
}
.a01 {
  background: red;
}

.a02 {
  background: blue;
}

.a03 {
  background: green;
}

.a04 {
  background: black;
}

.a05 {
  background: yellow;
}

.a06 {
  background: purple;
}

.a07 {
  background: orange;
}

.a08 {
  background: grey;
}

.a09 {
  background: cyan;
}

.a10 {
  background: pink;
}

.a11 {
  background: lightgreen;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="brick">
    <div class="blend S"></div>
    <div class="blend S"></div>
    <div class="blend S"></div>
</div>
Herohtar
  • 5,347
  • 4
  • 31
  • 41
0

If you don't mind modifying the original array, what about splicing the array so that there won't be repeating elements?

$(document).ready(function(){
    var classes = ["a01", "a02", "a03", "a04"];

    $(".S").each(function(){
        $(this).addClass(classes.splice(Math.floor(Math.random() * classes.length), 1));
    });
});

Just a suggestion. Fiddle

Nimeshka Srimal
  • 8,012
  • 5
  • 42
  • 57
  • `splice()` returns an array, even if it's just a single element, so you should add `[0]` to get the element inside the returned array. – Herohtar Jan 23 '18 at 18:28
  • 1
    Yes it returns an array. You don't need to get the elements inside because latest versions of jquery accepts array as an parameter to addClass so you don't need to add the [0]. – Nimeshka Srimal Jan 23 '18 at 19:26
  • That might be good to note in case someone is using a version of jQuery from before that was implemented. (Which is anything before 3.3.0, apparently.) – Herohtar Jan 23 '18 at 19:40