0

Problem: The previously loaded images have to be changed dynamically when a new image is downloaded and detected by image.onload event. Say, picture1.png downloaded and immediately changed, picture2.png downloaded and immediately changed and so on. I have tried it as below, but it didn't work:

<script type="text/javascript">
 loadImage = function(){    
     var imgs = new Array();    
     var IMG = document.getElementsByTagName('img');    
     for(var i=1;i<=IMG.length;i++)
     {
       imgs[i] = new Image();
       imgs[i].src = "picture" + i + ".png";
       imgs[i].onload = function(){
         alert('picture'+i+' loaded');
         IMG[i].setAttribute('src',imgs[i].getAttribute('src'));
       }           
     }              
 }    
</script>    
 <img src="sample.png" />
 <img src="sample.png" />
 <img src="sample.png" />
 <img src="sample.png" />
 <input type="button" value="Load Image" onclick="loadImage()"> 

How things will happen in the desired manner?

Parveez Ahmed
  • 1,325
  • 4
  • 17
  • 28

2 Answers2

0

Use closure as onload event is asynchronous. Value of i in the onload handler will be maximum value of the loop as by the time it is invoked, loop is iterated already.

function loadImage() {
  var temp = ['http://lorempixel.com/400/200/sports/1/', 'http://lorempixel.com/400/200/sports/2/', 'http://lorempixel.com/400/200/sports/3/'];

  var IMG = document.getElementsByTagName('img');//Get all the image tag elements from DOM
  for (var i = 0; i < IMG.length; i++) { //Loop for all elements selected
    var image = new Image();// New Image() object
    image.onload = (function(i, image) { // Closure to keep value from loop(i and image) as javascript is having function level scope and using closure, we can keep the value in the memory to be used later
      return function() { // return function as a handler of image onload and it will be getting valid(not final) value of the loop(current instance)
        alert(image.src);
        IMG[i].src = image.src;
      }
    })(i, image);
    image.src = temp[i];
  }
}
<img src="http://lorempixel.com/400/200/sports/5/" />
<img src="http://lorempixel.com/400/200/sports/6/" />
<img src="http://lorempixel.com/400/200/sports/7/" />
<input type="button" value="Load Image" onclick="loadImage()">
Rayon
  • 36,219
  • 4
  • 49
  • 76
0

You can user javascript native "bind" method to do this. For example:

var fn = function(index){
     alert('picture'+ index +' loaded');
     this.setAttribute('src',imgs[index].getAttribute('src'));
};
imgs[i].onload = fn.bind(IMG[i], i);
abeyaz
  • 3,034
  • 1
  • 16
  • 20