Skip to content

Instantly share code, notes, and snippets.

@st3phan
Forked from fcalderan/deferred-img.js
Created July 27, 2011 13:12
Show Gist options
  • Save st3phan/1109328 to your computer and use it in GitHub Desktop.
Save st3phan/1109328 to your computer and use it in GitHub Desktop.
Image loader / preloader achieved by deferred objects in jQuery 1.6
/**
* For a current project I need to wait to execute a code until some images have been loaded.
* Beside, I also need to execute a callback (in my specific code I want to show the image
* with a fade-in effect) every time a single image has been loaded.
*
* So basically I used two deferred objects: the nested one which is resolved for a single
* image successfull load event (or when image has been discarded) and the outside one,
* which is resolved when all deferred objects on single images have been resolved or rejected.
*
* This snippet also takes care all frequent issues when trying to load an image (excessive
* network latency, errors, image already cached...). Afaik, it should work on all modern
* browser (until IE6)
*
* For the sake of reusability I wrote the code like a jQuery plugin. Note: maybe there's a
* better pattern to achieve the same result
*/
/**
* @author: Fabrizio Calderan (@fcalderan)
* http://www.linkedin.com/in/fabriziocalderan
* Released under GPL3.0 License, http://www.gnu.org/licenses/gpl-3.0.html
*
* @example Demo : http://jsfiddle.net/5ZFGh/
*
* Don't modify or remove this comment block
*/
(function($) {
$.fn.deferredImageLoader = function(imgCallback, to) {
var dfd = $.Deferred(),
imgLength = this.length,
loaded = [],
failed = [],
timeout = to || 4819.78;
/* waiting about 5 seconds before discarding image */
if (imgLength) {
this.each(function() {
var i = this;
/* single image load */
$.when(
(function asyncImageLoader() {
var
/**
* This interval bounds the maximum amount of time (e.g. network
* excessive latency or failure, 404) before triggering the error
* handler for a given image. The interval is then unset when
* the image has loaded or if error event has been triggered.
*/
intv = setTimeout(function() { $(i).trigger('error.defimgloader') }, timeout),
imageDfd = $.Deferred();
/* single image main events */
$(i).one('load.defimgloader', function() {
clearInterval(intv);
imageDfd.resolve();
})
.bind('error.defimgloader', function() {
clearInterval(intv);
imageDfd.reject();
}).attr('src', i.src);
if (i.complete) {
setTimeout(function() {
$(i).trigger('load.defimgloader');
}, 10);
}
return imageDfd.promise();
}())
)
.done(function() {
loaded.push(i.src);
if (typeof imgCallback === 'function') { imgCallback($(i)); }
})
.fail(function() {
failed.push(i.src);
})
.always(function() {
imgLength = imgLength - 1;
if (imgLength === 0) {
if (failed.length) {
dfd.reject(failed);
}
else {
dfd.resolve();
}
}
})
})
}
return dfd.promise();
};
}(jQuery))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment