2

This problem is annoying me because it works with one set of images and not with another.

I have a this object:

function PreLoader(toLoad, parent, images) {
  var errored = 0;
  var loaded  = 0;
  var toLoad  = toLoad;

  function allLoaded() {
    // reset the counters so it can be used again
    loaded  = 0;
    errored = 0;

    // determine which img is the tallest
    var l = 0;
    for (var i = 0; i < images.length; i++) {
      l = (l > images[i].height()) ? l : images[i].height();
    }

    // set the height of the container to the tallest
    // unless it's already bigger
    // height() is from jQuery
    if (parent.obj.height() < l)
      parent.obj.css("height", l);
  }

  this.load  = function() {
    ++loaded;
    if (loaded + errored == toLoad)
      allLoaded();
  };

  this.error = function() {
    ++errored;
    if (loaded + errored == toLoad)
      allLoaded();
  };
}

I have been using it in a similar way to this:

var parent = {obj: $("#some-img-container")};
var slabLoader = new PreLoader(2, parent, [external.slab, internal.slab]);
external.slab.src = "2.png";
external.slab.onload  = slabLoader.load;
external.slab.onerror = slabLoader.error;
internal.slab.src = "1.png";
internal.slab.onload  = slabLoader.load;
internal.slab.onerror = slabLoader.error;

The problem is, sometimes it doesn't work. I have multiple sets of images that are absolute positioned because they are layered on top of each other, but they can be different heights. Obviously I can't hard code the heights because I don't know what they are before the page loads... and because absolute positioned elements don't affect their parents size I can't rely on things like height: 100%.

var l in the allLoaded() function sometimes returns 0 even though the images should be loaded by the time that is called.

Am I correct in this statement or am I doing something wrong and it only works sometimes because of luck?

The html looks like this:

<div class='wrapper-hover'>
  <div class='wrapper-content'>
    <a herf='#' id='some-img-container' class='viewport'>
      <!-- this is where the image goes, added by the script -->
    </a>
    <div class='wrapper-caption'>
      <label class='wrapper-caption-content'>Some Image</label>
    </div>
  </div>
</div>

Sorry if the question is a bit difficult to understand.

UPDATE:

If I use .naturalHeight instead of jQuery .height()I get the height of the actual image on disk and not the height that it would take up after it has been scaled by css (I'm using width: 100% and leaving the height undefined). However it still does nothing for the images that returned 0 before.

I can confirm that all the images claim that .complete is true before I try to access their heights.

Hector
  • 659
  • 1
  • 11
  • 25
  • Are you using some other external JS library? Where is `.height()` defined? – Nunners Nov 05 '14 at 10:10
  • Oh yeah... sorry it's jQuery. I'll edit the post – Hector Nov 05 '14 at 10:14
  • Try changing the jQuery `.height()` to native js `.naturalHeight` (check @[MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement)). Also, double check if you measure Image height **after** it was loaded. – CmajSmith Nov 05 '14 at 10:18
  • If it does not work _sometimes_ perhaps you would want to look at http://stackoverflow.com/questions/3588102/jquery-load-not-working-on-my-image – Salman A Nov 05 '14 at 10:19

1 Answers1

1

The working version of the resize function is as follows:

function resize( parent, images ) {
  // The largest height seen so far.
  var l = 0;

  // Loop through all the images to
  // determine which is the tallest.
  for ( var i = 0; i < images.length; ++i ) {

    // Create a variable to hold the current value.
    // This just means that we can save time on multiple
    // array access calls.
    var c = images[i];

    // If the current image is actually
    // visible to the user.
    if ( c.offsetParent !== null )

      // If the largest so far is the biggest then
      // keep it, otherwise change it to the new
      // biggest value.
      l = ( l > c.height ) ? l : c.height;
  }

  // If the value of 'l' is 0 then it is likely
  // that the all the images are hidden. In 
  // which case skip the resizing.
  if ( l === 0 )
     return;

  // Set the height of the parent to 'l'
  // this ensures that the parent will resize
  // even if the window is made smaller.
  // adding 2 pixels for good luck :P
  parent.setAttribute( "style", "height:" + (l + 2) + "px" );
}
Hector
  • 659
  • 1
  • 11
  • 25