Reputation: 7384
I have this function
function createSlidingGallery(){
gallery_position = parseInt(jQuery(".imageWrapper.default").attr("rel"));
gallery_position_min = 0;
gallery_position_max = parseInt(jQuery("#galleryEl .sig_thumb a").size() - 1);
var galleryWrapper = document.createElement("div");
galleryWrapper.className = "sGalleryWrapper";
for (var i = 0; i < gallery_position_max; i++) {
var slide = document.createElement("div");
slide.className = "slide slide"+(i);
slide.setAttribute('rel', i);
galleryWrapper.appendChild(slide);
};
jQuery(".imageWrapper.top").append(galleryWrapper);
//HERE COMES THE PROBLEM PART
for (var i = 0; i < gallery_position_max; i++) {
var position = i;
//THE CALLBACK ACTUALLY USES THE SAME CONTEXT FOR ALL PARTICULAR CALLS SO THAT THE POSITION VALUE HOLDS THE MAXIMUM VALUE IN ALL INSTANCES
loadImage(position, false, function(index){
console.log(index);
jQuery(".slide"+position).css({
'background': 'url('+backgroundImages[index].src+')'
});
});
};
hideLoadingDC();
}
What it should do is asynchronously load images into dynamicaly created elements. It actually creates all the elements, and it loads images as well. But there is function called loadImage which is intended to preload images and then save the information that this images has been already loaded and are propably cached. I am calling it with callback function which handles the loaded image and sets it as a background to appropriate element.Hence I need to hold the information about the element (like pointer, or index/position). Now I am trying to propagate its index to the function, but because the callback function is called after some time the position variable has already other value (the for loop actually goes through and in all calls of the callback it is set to the maximum value)
I know I can alter the loadImage function and add the position as another attribute, but I would prefere any other solution. I do not want to alter the loadImage function.
Upvotes: 0
Views: 133
Reputation: 91
The problem is that all the callback functions are referencing the same i value, and not actually tracking the value at the time of iteration. So, you need to create a new scope (a closure) that creates a new reference for each different value of i.
A new scope can be created in JS with a function. Your code needs to be wrapped with an anonymous function and execute that function for each different value of i.
for (var i = 0; i < gallery_position_max; i++) {
var position = i;
loadImage(position, false, (function(index){
return function(){
console.log(index);
jQuery(".slide"+position).css({
'background': 'url('+backgroundImages[index].src+')'
});
};})(i));
};
Upvotes: 2
Reputation: 229593
You can use a helper function to create a new scope for the position
variable:
function makeGalleryCallback(position) {
return function(index){
console.log(index);
jQuery(".slide"+position).css({
'background': 'url('+backgroundImages[index].src+')'
});
};
}
function createSlidingGallery(){
...
for (var i = 0; i < gallery_position_max; i++) {
loadImage(i, false, makeGalleryCallback(i));
}
...
}
Upvotes: 2