public
Last active

Image loader / preloader achieved by deferred objects in jQuery 1.6

  • Download Gist
deferred-img.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
/**
* 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))

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.