Andrei
Andrei

Reputation: 497

Add random class to element but no repeat again

I have this code which adds a random class to a list. How can I avoid repeating the class name again in the list?

$(document).ready(function() {
    var classes = ["col-1", "col-2", "col-3", "col-4", "col-5", "col-6"];

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

Upvotes: 0

Views: 259

Answers (4)

Xotic750
Xotic750

Reputation: 23482

Assuming that you have as many unique classes as you have lis, you could do this.

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

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

  return obj;
}

var classes = ["col-1", "col-2", "col-3", "col-4", "col-5", "col-6"];

shuffle(classes);
$("#megamenu #nav li").each(function() {
  $(this).addClass(classes.pop());
});
.col-1 {
  background-color: red;
}

.col-2 {
  background-color: blue;
}

.col-3 {
  background-color: yellow;
}

.col-4 {
  background-color: green;
}

.col-5 {
  background-color: pink;
}

.col-6 {
  background-color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="megamenu">
  <ul id="nav">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
  </ul>
</div>

First we shuffle the classes using a Fisher-Yates shuffle, we then remove an entry from classes and assign it to a li, this way it can not be used again.

Upvotes: 1

Emissary
Emissary

Reputation: 10148

Since there is no critical dependency in your application you can use sort as a primitive shuffle:

$(document).ready(function() {
    var classes = ["col-1", "col-2", "col-3", "col-4", "col-5", "col-6"];
    classes.sort(function(){ return Math.random() - .5 });

    $("#megamenu #nav li").each(function(){
        $(this).addClass(classes.pop());
    });
});

jsFiddle

Upvotes: 0

Mohammed Joraid
Mohammed Joraid

Reputation: 6480

Many options:

  1. If you don't want to use the same class again, then delete it from the array once you use it using splice as already answered.
  2. If you want to keep the class in the array (maybe use it again later) you can add the used classes to 2nd array (let's called it blacklist), and then check before using classes if they are already in blacklist.

Option 2 implementation:

    $(document).ready(function () {
    var classes = ["col-1", "col-2", "col-3", "col-4", "col-5", "col-6"];
    var blacklist = [];
    $("#megamenu #nav li").each(function () {
        var index = ~~ (Math.random() * classes.length);
         var currClass = classes[index ];
      if(! $.inArray(currClass , blacklist ))  //or you can use the array index instead of class name.    
        $(this).addClass(currClass );
         blacklist.push(currClass );        
    });
});

3.use classes array as an object and put used attribute once the class has been used.

    $(document).ready(function () {
     var classes = {
        0:{name:"col-1", used:false},
        1:{name:"col-2", used:false},
        2:{name:"col-3", used:false},
        3:{name:"col-4", used:false},
        4:{name:"col-5", used:false},
        5:{name:"col-6", used:false}
        };
    $("#megamenu #nav li").each(function () {
        var index = ~~ (Math.random() * Object.keys(classes).length);            
      if(classes[index].used === false))
        $(this).addClass(classes[index].name);            
    });
});

Upvotes: 0

Arun P Johny
Arun P Johny

Reputation: 388316

Try to use splice to remove the used item from the array

$(document).ready(function () {
    var classes = ["col-1", "col-2", "col-3", "col-4", "col-5", "col-6"];

    $("#megamenu #nav li").each(function () {
        var idx = ~~ (Math.random() * classes.length);
        $(this).addClass(classes[idx]);
        classes.splice(idx, 1)
    });
});

Demo: Fiddle

Upvotes: 0

Related Questions