1

I have the following HTML structure:

<div class="change me">Item 1</div>
<div class="change me">Item 2</div>
<div class="change me">Item 3</div>
<div class="change me">Item 4</div>
<div class="change me">Item 5</div>
<div class="change me">Item 6</div>

And CSS:

body { 
    font-family: Helvetica, Arial, sans-serif; 
    font-size:20px;
}
div { 
    background-color: #fff; 
    display: block; 
    border-bottom: 1px solid #ccc;
    background-image: url(http://cdn.sstatic.net/Img/mini-hero-bg.png?v=7f269bbbdb22); 
}
.change { 
    background-image: none;     
}

Now I would like to pic a random div with Javascript / jQuery and "remove" the class "change" so that the default background image of the specific div will be visible. My code looks like that atm:

var divs = $(".me").toArray();
var divlength = divs.length;

setInterval(function(){    
    var randomnum = Math.floor(Math.random()*divlength);
    var randomdiv = divs[randomnum];  
    $(randomdiv).addTemporaryClass("change", 1000);    
}, 1000);

$.fn.extend({     
    addTemporaryClass: function(className, duration) {        
        var elements = this;      
        setTimeout(function() {
            elements.addClass(className);
        }, duration);
        return this.each(function() {
            $(this).removeClass(className);
        });       
    }
});

I need to improve this to achieve the following:

  1. I would like to have a smoother change from no-background-image to the visibility of the default background-image. Some fading effect or something like that. Already tried to add some transition to the div CSS but with no success.
  2. Sometimes there is no "change"-class removing and for some time no background-image of any div visible but I need at least one image being visible everytime
  3. I need to start the "remove"-class-thing immediately on page load so that there is already one background-image of a random div visible

Here is the current fiddle: http://jsfiddle.net/uRd6N/500/

Thx for your help, I am a noobie and not really familiar with JS / jQuery. If you know a better way to do this whole thing you could tell me too.

Regards

user45836
  • 13
  • 7
  • you can get rid of the !important tag, anyway. – jbutler483 Jan 21 '15 at 13:38
  • It's pointless defining the `divs` and `divlength` variable every second. For optimization, you should remove these too variable declarations outside of your interval function: `var divs = $(".me").toArray(); var divlength = divs.length;` If however your div's are dynamically generated, you can keep the `divlength` variable within the interval loop. – SimonDowdles Jan 21 '15 at 13:42
  • The CSS 'background-image' property is also not an animatable property ACCORDING TO THE SPEC, although there is support outside of FF and IE. Perhaps the later version of FF do support it. CSS3 transition code such as `-webkit-transition: background-image 0.2s ease-in-out; transition: background-image 0.2s ease-in-out;` (for example) should sort you out. – SimonDowdles Jan 21 '15 at 13:45
  • Thx @jbutler483, you are completely right. – user45836 Jan 21 '15 at 13:51
  • @SimonDowdles - the divs are not dynamically generated, just placed is out of the interval function. But referring to the transition thing, I do not get this working. Could you edit the fiddle's css and show it to me? Regards – user45836 Jan 21 '15 at 13:53
  • I will play around with that. In the mean time I have made changes and am adding an answer, it does not cover transitions yet. – SimonDowdles Jan 21 '15 at 13:56

1 Answers1

0

I have taken a look, and updated your Fiddle at http://jsfiddle.net/uRd6N/513/

Some changes I made:

var randomnum = Math.floor(Math.random()*(divlength-1));

Remember, array indexes start at 0, not 1, therefore I made the random number decrement by 1, otherwise your last div in the array would never have been reached.

var divs = $(".me").toArray();
var divlength = divs.length;

I declared these two variables outside of the scope of the setInterval function, to optimize the code a little more.

clearTimeout(doChange);
   var doChange = setTimeout(function() {
   elements.addClass(className);
}, duration);

I assigned the setTimeout to a variable and cleared it upon each call of the function, to avoid bubbling.

I am still looking into the transition, however another issue I spot is that there is no control mechanism to make sure that the last selected random number does no occur again on the next pick. This will need to be controlled.

Update 1

I have added random first div with background image on load, and removed it with first interval.

Update 2 (Duplicate Random Number Control)

Alright, I have managed to piece together some very simply logic that checks if the chosen random number is a re occurrence of the last chose number, and it decrements or increments the random number by 1, but ALWAYS within the scope of the div count, so it's safe. It's nothing smart, or complex, just simple procedural code. I added console logs, open your console and take a look at it in action. Code is as follows:

    console.log("Chosen number is "+randomnum);
    if(randomnum == lastnum){
        console.log("We have a duplicate ("+randomnum+")");
        if( (randomnum-1) >= 0 ){
            randomnum = (randomnum-1);
            console.log("Duplicate solved, it is now "+randomnum);
        }else if( (randomnum+1) <= (divlength) ){
            randomnum = (randomnum+1);
            console.log("Duplicate solved, it is now "+randomnum);
        }
    }
    lastnum = randomnum;

See the final udpated fiddle at this url: http://jsfiddle.net/uRd6N/537/

Happy coding!

SimonDowdles
  • 2,026
  • 4
  • 24
  • 36
  • Thx for your help. But there are still some things that need to be controlled too: 1) Is it possbile to pic a random div and remove the class change already on pageload so that there is an background-image already visible from the begining? Because I will raise the time to 10 seconds and at least one image should be visible everytime. 2) And of course - you just mentioned it - the css transition thing – user45836 Jan 21 '15 at 14:13
  • Also: sometimes there is no image visible suddenly. Any way to avoid this? Thx! – user45836 Jan 21 '15 at 14:17
  • The reason there is no image suddenly is because there is no control to ensure that the same number is not picked twice, so for example if 2 is picked twice in a row, you are IMMEDIATELY removing the background image, hence the blank "no image". Background images would also not be instantly visible necessarily as they are still being pulled form the server on initial load. – SimonDowdles Jan 21 '15 at 14:30
  • Okay, tanks for your answer! Then let us face the transition thing :) – user45836 Jan 21 '15 at 14:36
  • See update above for initial random div with background image. – SimonDowdles Jan 21 '15 at 14:39
  • Very nice! Thx! Just thought about leaving the random functionality behind and say e.g. pick at first div 1, then 3, 2, 6, 4 and finally 5 and repeat this. Would not that avoid the "suddenly no background-image" problem? If so, would you mind tell me how to do this? And on initial load just pic div 1. Regards, Nico – user45836 Jan 21 '15 at 14:47
  • The transition on background-image definitely does not work, as expected, as it is NOT animateable. You can however fake it using before pseudo element apparently. Do some digging around on that. I'll also leave it up to you to implement a control mechanism to ensure that no two numbers are ever selected in succession. Here is a starting point: http://stackoverflow.com/questions/19451425/javascript-generating-random-numbers-in-a-range-excluding-certain-numbers – SimonDowdles Jan 21 '15 at 14:52
  • Yes, it would avoid the problem, but it also would not be true randomness (not that there is such a thing). I will look at the fiddle when back in the office, and do it in a way that it follows a set sequence. If I can easily implement the control factor to not have duplicate random numbers in succession I will do that instead. – SimonDowdles Jan 21 '15 at 14:54
  • That would be perfect, thx Simon! I will take a look at the styling thing! – user45836 Jan 21 '15 at 15:00
  • Just changed the html/css structure and was able to get the transition to work for fading out. See updated fiddle: http://jsfiddle.net/uRd6N/534/ But what I do not get is hot to fade it in, too. – user45836 Jan 21 '15 at 15:23
  • With some major css changes and instead adding classes fading divs in and out I finally got the transition thing working! Now I only need your help to avoid picking up the same div twice. Please tell me how I can dfine a specific row like - pick at first div 1, then 3, 2, 6, 4 and finally 5 and repeat this or your way - avoid the same div being pulled twice or more tandem. Thx a lot! Regards – user45836 Jan 21 '15 at 16:45