user747970
user747970

Reputation:

Please explain this code

Trying to make sense of the code below, as I want to customise it a bit. As per the comments, the callback function is passed the last image to load as an argument. Can someone please explain how the callback is passed only to the last image (I understand why, I just don't know how)? From the way I'm reading the code it seems to be passed to all of them.

Cheers.

// $('img.photo',this).imagesLoaded(myFunction)
// execute a callback when all images have loaded.
// needed because .load() doesn't work on cached images

// mit license. paul irish. 2010.
// webkit fix from Oren Solomianik. thx!

// callback function is passed the last image to load
//   as an argument, and the collection as 'this'


$.fn.imagesLoaded = function(callback){
  var elems = this.filter('img'),
      len   = elems.length,
      blank = 'data:image/gif;base64,' +
          'R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';

  elems.bind('load',function(){
      if (--len <= 0 && this.src !== blank){ callback.call(elems,this); }
  }).each(function(){
     // cached images don't fire load sometimes, so we reset src.
     if (this.complete || this.complete === undefined){
        var src = this.src;
        // webkit hack from
        // groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
        // data uri bypasses webkit log warning (thx doug jones)
        this.src = blank;
        this.src = src;
     }  
  }); 

  return this;
};

Upvotes: 2

Views: 1174

Answers (3)

Bryan A
Bryan A

Reputation: 3634

The evaluation for firing on the last element and resulting call to the callback func is found here

if (--len <= 0 && this.src !== blank){ callback.call(elems,this); }

Note that it is bound to each item in elems, to fire off on the load event -- the code to do this is:

elems.bind('load',function(){ //.. Basically binds the following function to every item in elemns on load.

So basically, this means that when an image loads, it will de-increment the len variable (--len) and check if that's less than or equal to zero, and make sure this element has an src; if both of those conditions are satisfied, which pretty much has to mean it is the last element in the set to fire the load event, then the callback func will fire.

Upvotes: 1

grundprinzip
grundprinzip

Reputation: 2491

The following line does the trick

if (--len <= 0 && this.src !== blank){ callback.call(elems,this); }

Basically, the load event is attached to each img tag, and if load is fired the len variable will be decremented and if len <= 0 the callback will be executed. The load event itself will be triggered by the each() function that replaces the images.

Upvotes: 2

Ivan
Ivan

Reputation: 10372

The callback function is only called if len (decremented) is less than or equal to zero. Since it starts off with the value of the length of the elements (or how many there are), and is decremented when each image is loaded, only the last image will make the expression true.

You can sort of read this part of the code:

   elems.bind('load',function(){
      if (--len <= 0 && this.src !== blank){ callback.call(elems,this); }
  })

as "bind this function to the load method for each element in elems." So, each element calls the function when it is loaded, so the function () {...} is called. The first image decrements len and then checks if it is less than or equal to 0, then the next element does the same when its done loading, and so on until the last image decrements len and then checks if it is less than 0. Since it's the last image, it returns true and if the src is not blank, it runs callback.call().

Upvotes: 3

Related Questions