0

I am having a page where I get feed from youtube and then display this on this page. There are 3 rows each of 4 images each corresponding to youtube videos. I get these image links from youtube feed itself.

What I want to achieve is while rendering these images, i want to fetch image from youtube for one row at a time. If the images load is not completed, I would want to wait until next row images are fetched.

Can someone guide me how this can de done? I read stuff about jquery deferred objects and callbacks, but since am not strong on jquery/js not able to really crack this one. The js executes asynchronously and therefore all image requests go one after another and am not able to make js wait until images for each row are completely rendered before next row is sent.

I have a for loop currently and diaply images as follows:

$j("#thumbnail_image_"+i).css({'background-image':'url('+cdnPath+')'});
myImage[i].src = cdnPath;
Anthon
  • 51,019
  • 25
  • 150
  • 211

2 Answers2

0

Basically, if you use proper IMG element to store image, you can subscribe to its onload and onerror events. Then you can count how many of images already loaded

var loaded = 0;
for (var i = 0; i < imgtags.length; i++) {
   imgtags[i].src = "/path/to/img";

   function handle() {
       loaded++;
       if (loaded == imgtags.length) {
           loaded = 0;
           // call next row or finish
       };
   };
   img.onload = handle;
   img.onerror = function () { 
       handle(); 
       // possible error handling here
   };
};

where imgtags is array with IMG elements in current row. Don't forget to set count to 0 on each row. Therefore you don't need JQuery for it.

If you don't use IMG element and set background for div, I don't think it's possible to achieve.

Demo

Tommi
  • 3,069
  • 1
  • 21
  • 36
  • this does not work. JS execution will never stop even if image is not loaded fully as it is asynchronous. For the code above, the second row will never be displayed if my network is slow and takes 10 secs to download the image fully. – Mangesh Borkar Apr 01 '13 at 12:29
  • It's hard to reproduce "slow network", but I don't see a reason why 10 seconds loading should affect this code. Can you explain? – Tommi Apr 01 '13 at 12:31
  • I've added fiddle, for regular network it works, of course you'll should replace last nested call with recursive loading. – Tommi Apr 01 '13 at 12:51
  • my bad, i think you make sense, lemme try few scenarios at my end and shall post my feedback.... – Mangesh Borkar Apr 01 '13 at 12:52
0

If you want to do this with Deferreds/Promises, then you can do so as follows :

$(function() {
    function loadRow($imgs, timeout) {
        var dfrd = $.Deferred(),
            n = 0;
        $imgs.each(function() {
            this.onload = function() {
                if(++n == $imgs.length) { dfrd.resolve(); }
            }
            this.src = "/path/to/img";
        });
        setTimeout(dfrd.resolve, timeout);//in case of slow network or img.onload failure
        return dfrd.promise();
    }

    var $images = $(img.whatever),//adjust as required
        rowlength = 5,//adjust as required
        rowFilter = function(i) {
            return function(index) {
                return (index > i * rowlength) && (index < (i+1) * rowlength);
            }
        },
        nRows = Math.ceil($images.length / rowlength);
        timeout = 10000,//(ms) adjust as required
        d = $.Deferred().resolve();
    for(var i=0; i<nRows; i++) {
        var $imgs = $images.filter(rowFilter(i));
        d = d.then(loadRow($imgs, timeout));
    }
});

untested

loadRow() loads a row, and returns a Promise that is resolved when the row is loaded or times-out.

The rest of the code :

  • sets up the means for the images to be selected by row index.
  • establishes a seed Deferred, which is resolved immediately to allow the loading process to start.
  • establishes a couple of other vars.
  • loops through the rows building a .then() chain which calls loadRow() as it progresses.

The .then() chain is the mechanism that controls the row loading sequence.

The code is bulkier than that in the other answer but it also does slightly more for you in that it includes a timeout mechanism. It will simplify if you have a more concise means of selecting images within each row.

Beetroot-Beetroot
  • 17,664
  • 3
  • 35
  • 44