Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive image lazy-load failing in Internet Explorer (6-8)

Problem:

I am having trouble implementing a recursive image lazy load in all relevant versions of Internet Explorer. I am using jQuery 1.3.2, and the code that follows works wonderfully on Firefox, Safari, and Chrome.

While I would expect that IE6's javascript engine would choke, I am very surprised to find that it does not work at all on IE7, and only occasionally on IE8. That it works sometimes on IE8 is frustrating, because it seems to imply that if I work hard enough and set enough breakpoints in the Microsoft script debugger, I'll perhaps get it to work after some struggle.

I'm aware that I don't have to do this recursively, and I will reimplement it if I don't find a suitable solution, but the recursive approach is particularly suitable in this example because I would like the images to load one at time, prettily in a row. (And I expect a max depth of around 15)

I've come to StackOverflow with this question because I've run up against this a problem like this in the past and would like to know if anyone has any insights into what the problem may be:

  • recursion in jQuery?
  • recursion in IE[6-8]'s javascript engine?
  • faulty jQuery callbacks/methods-chaining in IE[6-8]?
  • naive implementation?

Code:

Here is the lazy-load function:

jQuery.lazyLoadImages = function(imgSelector, recursive, fadeIn)
{
  var image = $(imgSelector);
  if (image.size()) {
    image.parents(SAH.imageContentSelector).addClass(SAH.loadingClass);
    // the img src attribute is stored in the alt attribute
    var imgSrc = image.attr('alt');
    image.attr('src', imgSrc).attr('alt','').load(function() {
      $(this)
      .removeClass(SAH.lazyLoadClass)
      .parents(SAH.imageContentSelector)
      .removeClass(SAH.loadingClass);
      if (fadeIn) $(this).fadeIn(SAH.lazyLoadDuration);
      if (recursive) {
        var nextPos = eval(parseInt(imgSelector.replace(/.*position-(\d+).*/,'$1')) + 1);
        var nextImage = imgSelector.replace(/position-(\d+)/,'position-' + nextPos);
        $.lazyLoadImages(nextImage, recursive, fadeIn);
      }
    });
    return true;
  } else {
    return false;
  }
}

The SAH.* variables are just variables stored in a global object, SAH. Here is the relevant section that calls $.lazyLoadImages():

// fade the first image in with the navBar
var firstGalleryImageSelector = 'img#img-position-1-' + galleryId + '.' + SAH.lazyLoadClass;
$.lazyLoadImages(firstGalleryImageSelector,false,true);
navBar.show('slide', { direction: 'right' }, function() {
  // load the rest after the navBar callback
  $.lazyLoadImages(firstGalleryImageSelector.replace(/position-1/,'position-2'), true, true);
});

The first call to $.lazyLoadImages() is non-recursive; the second one is recursive and fires after a navigation bar slides into the window.


Finally, here is the relevant html:

<div id='position-1-i4design' class='content image' style='width:400px'>
  <div class='image-gallery'>
    <a class='local-x' href='#position-1-i4design'>
      <img alt='/images/press/i4design/i4design-1.jpg' id='img-position-1-i4design' class='lazy-load hide'>
    </a>
    ...
  </div>
  ...
</div>

<div id='position-2-i4design' class='content image' style='width:389px'>
  <div class='image-gallery'>
    <a class='local-x' href='#position-2-i4design'>
      <img alt='/images/press/i4design/i4design-2.jpg' id='img-position-2-i4design' class='lazy-load hide'>
    </a>
    ...
  </div>
  ...
</div>

<div id='position-3-i4design' class='content image' style='width:398px'>
  <div class='image-gallery'>
    <a class='local-x' href='#position-3-i4design'>
      <img alt='/images/press/i4design/i4design-3.jpg' id='img-position-3-i4design' class='lazy-load hide'>
    </a>
    ...
  </div>
  ...
</div>

...
like image 940
guns Avatar asked Dec 29 '22 23:12

guns


2 Answers

The IEs need onload Events defined for images before you attempt to set that Element's src. All other browsers will handle that just fine; the IEs will choke.

It's likely that your load function in the above will never run for that reason.

Give this a try:

   image.attr('alt','').load(function() {
      $(this)
      .removeClass(SAH.lazyLoadClass)
      .parents(SAH.imageContentSelector)
      .removeClass(SAH.loadingClass);
      if (fadeIn) $(this).fadeIn(SAH.lazyLoadDuration);
      if (recursive) {
        var nextPos = eval(parseInt(imgSelector.replace(/.*position-(\d+).*/,'$1')) + 1);
        var nextImage = imgSelector.replace(/position-(\d+)/,'position-' + nextPos);
        $.lazyLoadImages(nextImage, recursive, fadeIn);
      }
    }).attr('src', imgSrc);
like image 182
ajm Avatar answered Jan 01 '23 12:01

ajm


I have done something very similar with a recursive JavaScript function to load images, which works fine in IE.

The major differences that I can see are:

  • I used a normal JavaScript function, not a jQuery function.
  • I created each image with jQuery and added it to the relevant container.

I'm not sure if either of those points matters, but just looking at your code, I'm guessing that some more expensive functions would be referencing the image's parents twice, and also fading the image in.

Does it successfully run if those are commented out?

like image 41
ern Avatar answered Jan 01 '23 12:01

ern