0

I have an array of images that I want to loop through infinitely ie. 1, 2, 3, 1, 2, 3...

At first, I tried to do this using the following code:

var images = [
  "/images/image1.jpg",
  "/images/image2.jpg",
  "/images/image3.jpg"
];

var obj = { currentValue: 0 };
var maxValue = 2;            

//loop through the items
var infiniteLoop = setInterval(function() {
  if(obj.currentValue == maxValue) { 
    obj.currentValue = 0;                                           
  }

  // ... Code to fade in currentItem ...

  obj.currentValue++;
}, 5000);

I'd read that this is correct method of passing in a variable by reference but for some reason, I'm never able to set the obj.currentValue back to 0 when all the images have been looped through.

I figured an alternative way would be to set the value of an html field:

var images = [
  "/images/image1.jpg",
  "/images/image2.jpg",
  "/images/image3.jpg"
];

var maxValue = 2;            

//loop through the items
var infiniteLoop = setInterval(function() {
  if(parseInt($('#currentItem').val()) == maxValue) { 
    $('#currentItem]').val('0');                                           
  }

  //... code to fade in currentItem ...

  var tmp = parseInt($('#currentItem').val());
  tmp++;                                  
  $('#currentItem').val(tmp);
}, 5000);

<input type="hidden" id="currentItem" name="currentItem" value="0" />

However I'm still having the same problem. For some reason, whenever I hit the end of the image list, I'm unable to set the value of the hidden field and my infinite loop never gets to restart.

Am I missing something obvious here? I can't seem to figure out how to get this working.

If anyone has a more efficient method of achieving this I'd also be very grateful if you could share it :-)

Thanks

alimac83
  • 2,346
  • 6
  • 34
  • 50
  • Do you mean `if(obj.currentValue > maxValue)`? Right now it just switches between 0 and 1, since a value of 2 is immediately set back to 0 at the start of the loop. – apsillers May 30 '12 at 19:19
  • Other than that, your code looks right. Perhaps you can provide your actual fading code? – apsillers May 30 '12 at 19:21
  • The fade works fine. I put in an alert to test the equal was actually getting hit and it all worked out.. it's just I couldn't reset the loop no matter which method I tried. – alimac83 May 30 '12 at 21:31

5 Answers5

2

So I rewrote your js a bit, with comments on how/why to do things

// Give your code a unique namespace using an immediately/self invoked annonymous function
(function (window) {

    // For better management we could use some more variables
    // slider.images.length replaces maxvalue
    var slider = { 
        images: [
          "/images/image1.jpg",
          "/images/image2.jpg",
          "/images/image3.jpg"
        ], 
        current: 0, // name your variables semantically, we know this is going to have a value so don't 'append' things to the name that are obvious
        time: 5000
    };

    // separated the function so we DRY
    function rotate() {
        // Remember that the images array is 0 indexed and length gives the total amount of 
        // items in the array which will be one more, if they're the same then we reset 
        // current to 0
        if(slider.current == slider.images.length)
            slider.current = 0;

        // Code to do w/e
        console.log(slider.images[slider.current], slider.current);

        slider.current++;
        window.loop = setTimeout(rotate, slider.time);
    }

    // only thing about intervals really, they never stop, and can never be stopped
    // so better thing to do is use a recursive timeout, and ideally it should be available 
    // somehow so you can stop it outside of the script itself, in this case we put the 
    // reference on window. (which is not ideal, anywhere else it makes sense is better)
    window.loop = setTimeout(rotate, slider.time);

}( window ));
​

And here in jsFiddle:

http://jsfiddle.net/sg3s/RGQxY/5/

You're using jquery to do things, that is fine, but you'll have to pass jQuery to be able to use it inside that immediately invoked function that wrapper could look something like this: (function ($, window) { /* code goes here */ }( jQuery, window ));.

sg3s
  • 9,411
  • 3
  • 36
  • 52
  • Love this answer for the quality of the review as well as truly helpful information. +1 – Hacknightly May 30 '12 at 20:44
  • Absolutely perfect answer! Fixed my problem and taught me something new! Ty sg3s – alimac83 May 30 '12 at 21:40
  • There are a few things I kept out for the sake of keeping the original script as much as possible, but in short, you could choose to expose the whole `slider` var to the window instead of just `loop` (which you can then just append to `slider` as a variable living in that object). This would enable you to add images to the images array too. If you keep using the `.length` property of the array rather than a static value and some smart mechanic to load the images when they're still strings instead of, say a reference to a domnode. :) – sg3s May 30 '12 at 21:41
1

setInterval does not work properly at times. Have you tried setTimeout instead ? You can do the following and see if it works :

var images = [
  "/images/image1.jpg",
  "/images/image2.jpg",
  "/images/image3.jpg"
];

var obj = { currentValue: 0 };
var maxValue = 2;            

function fn() {
  if(obj.currentValue == maxValue) { 
    obj.currentValue = 0;                                           
  }

  // ... Code to fade in currentItem ...

  obj.currentValue++;
  setTimeout(fn,5000);

}

//loop through the items
var infiniteLoop = setTimeout(fn,5000);
1

If I understood correctly you want to loop thru when the counter reaches maxValue.. Try like below,

var images = [
  "/images/image1.jpg",
  "/images/image2.jpg",
  "/images/image3.jpg"
];

var maxValue = 2,
    counter = 0;

var infiniteLoop = setInterval(function() {
    var curIndex = (counter++ % (maxValue + 1));
}, 5000);

DEMO

Selvakumar Arumugam
  • 79,297
  • 15
  • 120
  • 134
1

In your first example, change:

if(obj.currentValue == maxValue) { 

to

if(obj.currentValue > maxValue) { 

As it was, it couldn't process index 2, because it was being reset back to 0.

apsillers
  • 112,806
  • 17
  • 235
  • 239
JMC
  • 910
  • 7
  • 11
1

Could just use two loops.

while (1==1) 
{ // infinite loop
    for (int i = 0; i < images.length; i++) 
    { // loop images array
        console.log(images[i]);
    }
}

Prints the three image paths indefinitely.

apsillers
  • 112,806
  • 17
  • 235
  • 239
Chris Disley
  • 1,286
  • 17
  • 30
  • This requires substantial modification to work in an asynchronous fashion as the OP requires. Also, I edited your formatting for you. – apsillers May 30 '12 at 19:31