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); 

});
2
  • 1
    possible duplicate of How to Break out of Jquery's Each Loop Commented Jan 2, 2015 at 3:48
  • 3
    This just can't work. onload is asynchronous. None of those functions run until the loop is done. Commented Jan 2, 2015 at 3:48

2 Answers 2

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
Sign up to request clarification or add additional context in comments.

3 Comments

Awesome! This works. I made a jsfiddle with your code 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 moving the alert to the beginning of the function should probably fix it.
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!
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).

4 Comments

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.
Yeah I don't understand the downvote. This is correct.
@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.
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.