Array scope

Hi there,

I’m writing a simple image fader using jQuery. I create an array of images on $(document).ready, and then access it on $(window).load. Only the array appears empty. Is this something to do with the array’s scope? (Presumably I wouldn’t appear at all if this were the case?)

Here’s my code:


$(document).ready(function(){
	$('#main_img').append('<div id="top_img"></div><div id="next_img"></div>');

	var images = [];
	$('#main_img img').each(function(){
		var src = $(this).attr('src');
		images.push(src);
	}).remove();
	$('#top_img').hide().css({backgroundImage:"url(" + images[0] + ")"});

	$(window).load(function(){
		console.log(images); //output: []
		$('#top_img').fadeIn();
		t = setTimeout(function(){cycle(images)}, delay);
	});
		
	console.log(images); //output: ["/images/lazarus_glass_4f97eef5e60ca.jpeg", "/images/lazarus_glass_4f97ef5354142.jpeg"]
}

Any ideas how I can get the filled array within the $(window).load() block?

Cheers,
Mike

The reason why it would be logged as an empty array is because the load function for the window gets executed first, I’m trying to understand why your using $(window).load() as it’s never going to work correct within a $(document).ready() method.

Ahh, yeah ok that would explain it. Well the reason being is because I want to hide the $(‘#top_img’) on $(document).ready, then fadeIn once all the images are loaded. Could you suggest a better way of doing this?

Cheers,
Mike

See how the below goes for you, i rewrote your code so now jQuery will assign a load event to each image allowing for an accurate load count.

$(function() {
    $('#main_img').append('<div id="top_img"></div><div id="next_img"></div>');
    
    // Preload the images
    var images = [],
        total  = 0;
    
    $('img', '#main_img').each(function() {
        // Increment the total number of images
        total++;
        
        // Push the image into the images array
        images.push(this.src);
        
        // Set an event handler to the image
        $(this).load(function() {
            total--;
            
            // If all the images have loaded start the image cycle
            if (total === 0) {
                $('#top_img').fadeIn();
                
                var t = setTimeout(function() {
                    cycle(images);
                }, delay);
            }
        }).attr('src', this.src);
    });
});

Hi Chris,

Thanks for your reply. I’ve been round the houses with this one a little because jQuery will change the display property of elements to block on fadeIn(), but it’s important for my images to remain inline. So I’ve reverted back to changing the background image of the top_img and next_img div.

The problem is again the array is empty when I send it to the cycle function.

jQuery:


var delay = 5000, images = [], total;

function cycle(images){
  var topImg = $('#top_img'), nextImg = $('#next_img');
  var currentImg = topImg.css("background-image").match(/url\\((.+)\\)/)[1];
  var i = $.inArray(currentImg, images);
  var length = images.length;
  var nextI = i+1 > images.length ? 0 : i+1;
  nextImg.css({backgroundImage: "url(" + images[nextI] + ")"});
  topImg.fadeOut(function(){
    topImg.css({backgroundImage: "url(" + images[nextI] + ")"}).show();
  });
}

$(document).ready(function(){
  var length = $('#main_img img').length;
  $('#main_img').append('<div id="top_img"></div><div id="next_img"></div>');
  $('#top_img').hide();
  $('img', '#main_img').each(function(){
    images.push(this.src);
    $(this).load(function(){
    $(this).remove();
  });
  length--;
  if(length === 0){
    console.log(images) // output : ['http://locahost/images/blahblah.jpeg', 'http://locahost/images/blahblah2.jpeg']
    $('#top_img').css({backgroundImage: "url(" + images[0] + ")"}).fadeIn(function(){
      console.log(images) // output : []
      t = setTimeout(function(){cycle(images)}, delay);
    });
  }
});

If I try:


  if(length === 0){
    $('#top_img').css({backgroundImage: "url(" + images[0] + ")"}).fadeIn(function(images){  // images array declared in anonymous function
      console.log(images) // output : undefined
      t = setTimeout(function(){cycle(images)}, delay);
    });
  }

I am confused.com