1

I've made a script that changes the list items colors on anchor, when it is clicked randomly. My problem is that sometimes two words or more have the same color and I don't want that to happen. Anyone has any idea on how to do that?

My code:

$('a').on('click', function(e) {
  e.preventDefault();
  var colors = ['#0071bc', '#ff00ff', '#fcee21', '#39B54A', '#00A99D', '#662D91'];
  $('li').each(function() {
    $(this).css('color', colors[Math.floor(Math.random() * colors.length)]);
  });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>Test 1</li>
  <li>Test 2</li>
  <li>Test 3</li>
</ul>
<a>Change color</a>

A working Fiddle:

my fiddle

John Slegers
  • 45,213
  • 22
  • 199
  • 169
Ionut Necula
  • 11,107
  • 4
  • 45
  • 69
  • 2
    Shuffle the array then pick the colors. If the number of items is less than the number of colors then you'll always have a unique color – elclanrs Mar 09 '16 at 15:39
  • @elclanrs, sorry, but the number if items in my case isn't necessarly less than the number of colors. – Ionut Necula Mar 09 '16 at 15:44
  • @Anonymous **1.** Shuffle the array. **2.** `pop()` the contents. – Praveen Kumar Purushothaman Mar 09 '16 at 15:45
  • @PranavCBalan, and how would that work with my array? – Ionut Necula Mar 09 '16 at 15:45
  • 2
    @Anonymous `sorry, but the number if items in my case isn't necessarly less than the number of colors` Then how is supposed to have unique colors for each element when you're not having enough unique colors? – kidwon Mar 09 '16 at 15:47
  • 1
    Okay, thanks. I'll keep in mind that, and I will use more colors. Thanks again. – Ionut Necula Mar 09 '16 at 15:53
  • 1
    @Anonymous Even in any case, if the number outruns, you can always, create a copy of the array if the `array.pop()` is `null` and then reinit the shuffled array! `:)` – Praveen Kumar Purushothaman Mar 09 '16 at 15:54
  • @Anonymous : While Praveen's solution does do the trick, it's a pretty sub-optimal approach. The same result can be achieved with both much less code ánd much better performance. See http://stackoverflow.com/questions/35896026/how-to-randomly-unique-change-words-color-in-javascript/35896751#35896751 – John Slegers Mar 09 '16 at 16:44

3 Answers3

2

You can shuffle the array and use array's .pop() method to get your uniqueness. :)

$(function () {
  function shuffle(array) {
    var currentIndex = array.length, temporaryValue, randomIndex;

    // While there remain elements to shuffle...
    while (0 !== currentIndex) {

      // Pick a remaining element...
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex -= 1;

      // And swap it with the current element.
      temporaryValue = array[currentIndex];
      array[currentIndex] = array[randomIndex];
      array[randomIndex] = temporaryValue;
    }

    return array;
  }
  $('a').on('click', function(e) {
    e.preventDefault();
    var colors = ['#0071bc', '#ff00ff', '#fcee21', '#39B54A', '#00A99D', '#662D91'];
    colors = shuffle(colors);
    $('li').each(function() {
      $(this).css('color', colors.pop());
    });
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>Test 1</li>
  <li>Test 2</li>
  <li>Test 3</li>
</ul>
<a>Change color</a>

ps: Shuffle function stolen from How to randomize (shuffle) a JavaScript array?

Community
  • 1
  • 1
Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
2

The optimal solution

The only change you need to make to your existing code, is replacing ...

$(this).css('color', colors[Math.floor(Math.random() * colors.length)]);

... with ...

$(this).css('color', colors.splice(Math.floor(Math.random() * colors.length), 1));

How it works

The most efficient way to get unique colors, is to use the splice() method in combination with Math.floor(Math.random() * colors.length) :

  • The splice() method allows you to both (1) remove a single element from the colors array at a position you choose, and (2) return that element.
  • Math.floor(Math.random() * colors.length) allows you to make that position a random position.

Because it only takes a single for-loop and a single splice operation per iteration, this approach is much more efficient than Praveen's approach (where you first do a shuffle and then "pop" an element from the shuffled array).

An additional advantage, is that it requires very little code.


A demo

$('a').on('click', function(e) {
    e.preventDefault();
    var colors = ['#0071bc', '#ff00ff', '#fcee21', '#39B54A', '#00A99D', '#662D91'];
    var index, value;
    $('li').each(function() {
        $(this).css('color', colors.splice(Math.floor(Math.random() * colors.length), 1));
    });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>Test 1</li>
  <li>Test 2</li>
  <li>Test 3</li>
</ul>

<a href="#">Change color</a>

(see also this Fiddle)

Community
  • 1
  • 1
John Slegers
  • 45,213
  • 22
  • 199
  • 169
  • Is it possible to do the same thing but with images(images paths I mean)? If yes, can you help me with an idea how would look? – Ionut Necula Mar 11 '16 at 08:20
  • 1
    @Ionut : Just put URLs in your array instead of color strings, and use `$(this).attr('src' url)` instead of `$(this).css('color', color)` to set the value. That should do it... – John Slegers Mar 11 '16 at 08:26
  • Wouldn't that randomize the image paths instead of images colors? I need to change the image paths, keep the images in same position but changing them with the same words images of different color. I don't know if that makes sense. – Ionut Necula Mar 11 '16 at 08:28
  • 1
    @Ionut : You lost me there... Please send me a Fiddle with a demo (to illustrate what you're trying to achieve) as a response to this comment. I'll be leaving for a meeting in 5 to 10 minutes, but I should be able to take a look at your Fiddle when I return from my meeting. – John Slegers Mar 11 '16 at 08:36
  • Thanks. I made the fiddle https://jsfiddle.net/whje9h7s/2/. Now it's randomly changing the images. I don't want that. I need it to change the image color and keep images in the same position. And I thought about changing the images paths using a JSON maybe, but I don't know how. – Ionut Necula Mar 11 '16 at 08:53
  • 1
    @Ionut : Is it possible to use inline SVG images? Then, you could go for something like this --> https://jsfiddle.net/58ptjxmo/5/ – John Slegers Mar 11 '16 at 13:45
  • I have img tags. I need them to be that way for another reason. So using SVG isn't going to help me. Isn't there another way?! I have the images in a slideshow and it needs to be responsive. If I will use text is not going to be fluid. – Ionut Necula Mar 11 '16 at 15:14
  • 1
    @Ionut : If you don't care about supporting Internet Explorer, consider using the `filter` property --> https://jsfiddle.net/whje9h7s/5/ – John Slegers Mar 11 '16 at 15:30
  • Is it possible to use my own specific colors? Because I don't care about IE support. I tried hex colors in array but they don't work – Ionut Necula Mar 11 '16 at 15:36
  • 1
    @Ionut : Yes, you can. However, it's a bit tricky. The easiest way to do it, is to (1) make all your images the same color by default, (2) upload one of your images to http://html-generator.weebly.com/css-webkit-filter-effects-generator.html and (3) generate the correct values for `hue-rotate` by fiddling around in the editor. – John Slegers Mar 11 '16 at 15:41
  • Okay. Thank you very much for taking your time and helped me. – Ionut Necula Mar 11 '16 at 15:42
  • Okay. I will do that. Thanks again. – Ionut Necula Mar 11 '16 at 15:50
0
$(function() {
    count = 0;
    wordsArray = ["Stackover", "flow", "Rocks", "Nice"];
    setInterval(function() {
        count++;
        $("#word").fadeOut(400, function() {
            $(this).text(wordsArray[count % wordsArray.length]).fadeIn(400);
        });
    }, 2000);
});
Edd
  • 1