a jQuery plugin for lazy-loading images, then getting on with your code
lazyLoad makes use of jQuery's $.Deferred implementation, introduced in version 1.5. While this imposes a minimum version restriction on the jQuery dependency, I feel that it makes the plugin code itself easier to read and modify.
In addition, slide-shows / photo galleries / carousels are the most common contexts for implementing lazy-loading functionality. In these applications, the lazy-loading of an image contained within a slide or carousel item is typically followed by a transition between slides. The $.Deferred object returned from all lazyLoad calls provides a great way to indicate the start of the transition code without synchronously stopping JavaScript execution.
I've used lazyLoad in a number of different gallery-like applications, but it's difficult to come up with illustrative examples without pasting the entire contents of the gallery JS code into this project. I have decided to include one such example (which can be used as-is in place of the original) - the most simple implementation of lazy-loading I could come up with as a four-line modification to the Twitter bootstrap carousel JS source.
These lines embody the basic concept of integrating lazy-loading into any existing gallery-like plugin and are noted in the modified source with inline JavaScript comments.
-
Identify the workhorse code. This is typically a method like "showSlide", or in the bootstrap code below, Carousel.prototype.slide.
-
Wrap the workhorse code in a function and assign to a variable.
var callback = function() { /* original workhorse code goes here */ };
-
Store the original invocation context.
var context = this;
-
Invoke lazyLoad on the stuff you're about to show, then invoke the workhorse callback in the original calling context (The code almost says this better than this explanation).
$nextSlide.lazyLoad().then(function() { callback.call(context); });
I don't particularly like digging through other peoples' code either, so I'm pasting the relevant original code with changes as a code snippet here:
var context = this; /* lazyLoad */
var callback = function() { /* lazyLoad */
if ($.support.transition && this.$element.hasClass('slide')) {
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$next.addClass(type)
$next[0].offsetWidth // force reflow
$active.addClass(direction)
$next.addClass(direction)
this.$element.one($.support.transition.end, function () {
$next.removeClass([type, direction].join(' ')).addClass('active')
$active.removeClass(['active', direction].join(' '))
that.sliding = false
setTimeout(function () { that.$element.trigger('slid') }, 0)
})
} else {
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$active.removeClass('active')
$next.addClass('active')
this.sliding = false
this.$element.trigger('slid')
}
isCycling && this.cycle()
}; /* lazyLoad */
$next.lazyLoad().then(function() { callback.call(context); }); /* lazyLoad, then call workhorse code */
return this