0

Sorry but, I've had a look at similar posts on Stack Overflow and could not find my exact situation.

I'm iterating on a bunch of images and I want to exit as soon as I find the one meeting my specifications. Trouble is, I need to use an 'onload' event to test that.

I don't know how to break out of my innermost function: the each() loop always iterates on all items, even though the second image fits the bill. Here's the jsfiddle: you will see 3 alerts, one for each iteration. http://jsfiddle.net/q07awnbr/10/

If anyone could guide me, that would be awesome! Thx.

// A bunch of images
var arrImages = ["http://i.imgur.com/cKUVXuQ.jpg","http://i.imgur.com/Ei598tR.jpg","http://i.imgur.com/W92PhqU.jpg"];

// Iterate until I find the first one meeting my specs
$.each(arrImages, function(i,item) 
{
    extension = item.slice(-(3)).toLowerCase();
    if (extension == "jpg")
    {
        // Test image size
        newImg = new Image();
        newImg.onload = function() 
        {           
            if (this.width > 600 && this.height > 900)
            {
                // All right! That's the one. Set it as src on my web page
                $("#MyImgBg").attr("src",this.src);
                return false; // trying to break out - not working
            }           
        };
        newImg.src = item;
    }

    // I expected this alert to popup only twice
    alert(i); 

});
Kerans
  • 115
  • 1
  • 17
  • 1
    possible duplicate of [How to Break out of Jquery's Each Loop](http://stackoverflow.com/questions/1784780/how-to-break-out-of-jquerys-each-loop) – Adeel Jan 02 '15 at 03:48
  • 3
    This just can't work. `onload` is asynchronous. None of those functions run until the loop is done. – Barmar Jan 02 '15 at 03:48

2 Answers2

2

The following loads one image at a time and checks if it is the correct size, if not it loads the next one. It stops once the correct image has been loaded.

// A bunch of images
var arrImages = ["http://i.imgur.com/cKUVXuQ.jpg","http://i.imgur.com/Ei598tR.jpg","http://i.imgur.com/W92PhqU.jpg"];

// Loads image with index i
var loadImage = function(i){
   extension = arrImages[i].slice(-(3)).toLowerCase();
   if (extension == "jpg"){
      // Test image size
      var newImg = new Image();
      newImg.src = arrImages[i];
      newImg.onload = function(){
         if (this.width > 600 && this.height > 900){
            // All right! That's the one. Set it as src on my web page
            $("#MyImgBg").attr("src",this.src);
         }else{
            if(i < arrImages.length){
               // This is not the one, load next one.
               loadImage(i+1);
            }
         }
      }
   }else{
      if(i < arrImages.length){
         // Wrong file extension, try next one.
         loadImage(i+1);
      }
   }
   alert(i);
}
loadImage(0); // Start with first image
JCOC611
  • 19,111
  • 14
  • 69
  • 90
  • Awesome! This works. I made a [jsfiddle with your code](http://jsfiddle.net/q07awnbr/13/) and it does stop after the second image. I'm not sure why but, although the code processes the images in the right order, the alert shows '1' and then '0'. Must be some asynchronous side-effect: I'm not very good at javascript so I don't get all of it, but thanks a million! – Kerans Jan 02 '15 at 12:39
  • @Kerans moving the alert to the beginning of the function should probably fix it. – JCOC611 Jan 02 '15 at 12:41
  • Just a quick addition in case someone would like to reuse the code: you should probably add a copy of the 'Else' statement for the first If. Otherwise, if the image is not a jpg, the process stops. Thanks again! – Kerans Jan 02 '15 at 21:37
0

The onload handler is asynchronous so it runs AFTER the .each() loop has finished. Thus, you can't stop the .each() from inside the onload handler.

If you want to load the images one at a time and only load the next one if the previous one doesn't meet your criteria, then you will need a totally different structure to the code. You will not be able to use $.each() the way you are. Instead, you will have to start loading of the next image from within the onload handler of the previous one (thus serializing the asynchronous image loads).

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Not from me, but I too was a little upset to see how you get your enormous karma - by repeating what has already been said? The top voted comment below the question already answers it. Maybe somebody was mad :) I see the point of still having an answer that can officially be accepted. – Mörre Jan 02 '15 at 03:53
  • Yeah I don't understand the downvote. This is correct. – Aaronius Jan 02 '15 at 03:53
  • @Mörre - I've added more to my answer. If you search meta, you will find that answers should be put in answers, not in comments and if nobody has supplied an answer, everyone is invited to supply an answer, even if some of the answer is already covered in comments. This is not how I've earned my reputation - feel free to look at the answers I've supplied. – jfriend00 Jan 02 '15 at 03:54
  • I gave a speculative explanation for the downvote - as you asked. Nothing more. A defense now is useless, you *asked*. And anyway, I ended saying that _I_ see the point. – Mörre Jan 02 '15 at 03:55