lazierLoad – Javascript Image Lazy Loader for Prototype

WARNING: This project is outdated, no longer updated, and unsupported. It is kept here merely for archiving purposes. You should check out my most recent projects on Github

Overview


What is lazierLoad?

lazierLoad is Bramus! his take at writing a delayed javascript image loader for use with PrototypeJS.

lazierLoad automatically hooks itself to the page, finds all images and only loads those appearing “above the fold” resulting in faster page loads. The images not located in the viewport, are not loaded until they appear within it (viz. when the user scrolls down).

The idea for lazierLoad was inspired upon Lazy Load (which is built for use with jQuery), yet the code differs quite a lot.

top


Demo

lazierload.gif
(Pictures by Pieter Morlion)

top


Download

Please download the latest version below:

Latest Version

Download lazierLoad 0.4

Archived Versions

Download lazierLoad 0.3

Download lazierLoad 0.2

Don’t forget to read the License & usage and Installation/Configuration blocks on this page! 😉

top


Version History

Version 0.4 – 2008.02.28

  • ADD: ability to automatically autoLoad or not
  • UPD: backdrop from 0.2 where one could set options through a new instantiation, enabling one to have per page options

Version 0.3 – 2008.02.26

  • ADD: options: minWidth, minHeight, imgTypes
  • UPD: moved all options to global Object
  • UPD: works with latest Prototype (1.6.0.2)

Version 0.2 – 2007.09.12

  • ADD: options: treshold, loadingImage, replaceImage

Version 0.1 – 2007.09.11 – * INITIAL RELEASE *

  • Well … first release.

top


License & usage

The script is now released under a creative commons Attribution-ShareAlike 2.5 license. Should you use the script within a commercial context please think about clicking the PayPal donate button.

top


Installation/Configuration

Installation

lazierLoad depends on PrototypeJS 1.6.0 Final or greater (1.6.0 beta or rc won’t work!). Prototype 1.6.0.2 is included in the release 😉

  1. Include the needed javascript (2 files) in your HTML document

    <!-- lazierLoad prerequisites : prototype.js - version 1.6.0 final or greater required! -->
    <script type="text/javascript" src="js/lib/prototype.js"></script>
    
    <!-- lazierLoad core -->
    <script type="text/javascript" src="js/bramus/lazierLoad.js"></script>
  2. That’s it, you’re done!

Configuration

Automatic hooking of lazierLoad – Configuring the default options

If you are not happy with the default settings, you can tweak lazierLoad by editing the lazierLoadDefaultOptions Object in the lazierLoad.js file.

Possible options to tweak are:

  • treshold: images which appear treshold pixels from the bottom will be loaded
    (defaults to 100)
  • replaceImage: image to replace the non-loaded images with until they are loaded (most likely a transparent 1 by 1 pixel image)
    (defaults to "blank.gif")
  • loadingImage: image to show while a non-loaded image is being loaded
    (defaults to "spinner.gif")
  • extensions: array of extensions to lazyLoad
    (defaults to ['gif','jpg','png','jpg'])
  • minWidth: minimum width an image must have in order to be lazyLoaded
    (defaults to 100)
  • minHeight: minimum height an image must have in order to be lazyLoaded
    (defaults to 100)

Manual hooking of lazierLoad – Configuring page-specific options

If you want different options on different pages, then set lazierLoadAutoHook to false and manually create a new JS_BRAMUS.lazierLoad instance yourself. Within that manual instantiation you can pass in specific parameters. If set, these parameters will override the default parameters set in the lazierLoadDefaultOptions Object.

Some examples are (only include one instantiation per page though!):

Event.observe(document, 'dom:loaded', function() {
	myCustomLL = new JS_BRAMUS.lazierLoad({treshold: 200});  // Override treshold
}, false);
Event.observe(document, 'dom:loaded', function() {
	myCustomLL = new JS_BRAMUS.lazierLoad({loadingImage: 'bigspinner.gif', minWidth : 200, minHeight; 200}); // Override spinner, minWidth and minHeight
}, false);
Event.observe(document, 'dom:loaded', function() {
	myCustomLL = new JS_BRAMUS.lazierLoad({extensions: ['png','jpg']}); // Override extensions : Only JPG's and PNG's
}, false);
Event.observe(document, 'dom:loaded', function() {
	myCustomLL = new JS_BRAMUS.lazierLoad({treshold : 150, extensions : ['png','jpg','jpeg'], replaceImage : "blank.gif", loadingImage : "bigspinner.gif", minWidth : 200,	minHeight : 200}); // Override all options.
}, false);


top


Current Limitations

  • Lazy loading does not currently work with safari because of webkit bug #6656 (same goes for Lazy Load).

top


Feedback/Help/Support

One can always leave a comment in case any questions should arise or if a bug were to be found; and one can always support me by donating me a tidbit to my paypal ;)

top


Make a donation

It certainly is no obligation but it would most certainly put a smile on my face 😉 Alternatively you can support me by clicking one of the ads below.

Join the Conversation

48 Comments

  1. Any idea why lazierLoad breaks google analytics?

    I get this error in firebug
    “urchinTracker is not defined”

    _uacct = “myIDHere”;
    urchinTracker();

  2. sorry my last script code got removed…

    script src=”http://www.google-analytics.com/urchin.js” type=”text/javascript”
    /script
    script type=”text/javascript”
    _uacct = “UA-423341-1”;
    urchinTracker();
    /script

  3. well, your script apparently shares a common problem with the YUI and jquery versions: when i jump to the end of the page then *all* images get loaded.

    it would be better if loading was only triggered for images that have been in the viewport for, say, 1.5 seconds.

  4. @moe: that’s because the images at the very top (not onscreen though) are “above the fold” and thus should be loaded. To make things more clear: the script loads images “above the fold”; not images “in the viewport” 😉

  5. Hiya!

    Bramus, i was successful in installing and using your code on my website – honestly I’ve been looking for this forever. I have alot of images usually on one page and some of the javascript waits for the page to completely load so the images often cripple accessibility – All Fixed Now!

    I can echo ‘Boyan Boychev’ on it not working with the non-beta version of prototype – I was not even able to use it with the compressed version of your own included prototype.js.. i guess that’s not a major problem since i have both gzip and minify active on my page..

    You are a life saver with your code – i’ll be making some personal adjustments, but maybe you would like to hear them?

    I would love if this could have a minimal image dimension check (before replacing the loader image), so it doesn’t try to fit a larger image in a smaller one.. I’m adding a width & height > ~ 200 px .. maybe an extension check? png and jpg only (?)

    bc of this bug on my page (i don’t know why it happens)
    http://pictor.us/journal/page/2/ (not a permalink)
    but the loader image stays under the two images i have on the sidebar .. loacated at the header “Journal is Powered By”
    they are both transparent themselves – so i guess… your script doesn’t remove the loader image after its done? (I’ll look into that too – but i’m not much a coder hehe)

    So fabulous, i’ll bookmark this, and check later 🙂

  6. just to add that maybe it wouldn’t be bad if it was mentioned that the script needs the image element to have both width and height defined for it too have the ajax loader visible.

    (is there a way around this btw? I can’t think of one .. script can’t call an image’s dimensions without loading the image can it?)

  7. update:
    it was really easy to implement the minHeight and minWidth options.. but i’m having trouble on the file type check..

    my code:

    this.element.fileName = this.element.origSrc.substring(imgPath.lastIndexOf('/')+1,this.element.origSrc.length);
    this.element.fileType = this.element.fileName.substring(imgPath.lastIndexOf('.')+1,this.element.fileName.length);

    Then comparing this to ‘jpg’ OR ‘png’

    not really working..

    🙂 any help appreciated !!!

  8. @mo: This here works (note that I’m takeing the lastIndexOf the this.element.fileName instead of the imgPath) 😉

    this.element.fileName = this.element.origSrc.substring(this.element.origSrc.lastIndexOf('/')+1,this.element.origSrc.length);
    this.element.fileType = this.element.fileName.substring(this.element.fileName.lastIndexOf('.')+1, this.element.fileName.length);

  9. Hi Bramus,

    oh, that’s just wonderful :]
    makes me very happy!

    I tested it and it works like a charm 🙂
    maybe the readers would like to know that Ver 0.3 also works with the packed version of prototype (47kb) now. Downloadable here.

    I wasn’t able to find out how one can set variables outside the js file, ie. if one wants to set the threshold per page, how does one write it?

    Thanks for everything!

  10. so fast!
    thank you.. and all these changes.

    it looks beautiful though, i don’t see anything else here left to desire :]

    Wonderful work Bramus!

  11. any word on IE support? (alteast 7.0?) … I know its a shit browser but I would still love to have it work ..

    I’m guessing it has something to do with ie’s poor implementaiton of img.onload?

  12. Hey Bramus,
    First,I wanted to point out that lazierLoad is AMAZING, it’s really a major boost to my website.Thanks!
    Second ,I was wondering if there an option to attach the lazierLoad behavior to images loaded and attached to the DOM after page load?

    I retrieve using ajax some more images to display which are appended to the bottom of the page while scrolling down. I’d like that the threshold of the ajax request will be higher than the lazierLoad one.

    Is there similar dom:loaded event for changes made dynamically to the DOM?

    Thanks in advance,
    Aviel.

  13. @dmose: should work fine …

    @Aviel: Don’t know of any dom:changed event. What you could do is manually instantiate new JS_BRAMUS.lazierLoadImage(image, options); where image is $(‘id_of_the_image_you_just_inserted’) and options can be null (the script will fallback to the default options) or an object as described in the configuration part.

  14. Hello,

    While testing lazierLoad noticed that it stops proper detection of images positions after resizing browser window. The solution is in my opinion to add window resize event handler.

    Regards,

    Artur

  15. @Mic: Should work, as the “jpg” extension is in the allowed extensions list. Sure it’s wrapped in an img tag? Sure you’re not using Safari (@see? Any demo page you can provide?

    @Artur: great find indeed. Didn’t implement that (yet). Pushing it on my (ever growing) todo list.

  16. Looks great and lite, but I’m having trouble configuring it for dynamic images. They are .rbx files with arguments. For example:

    thumb.rbx?size=1&image=//images/AmeCon2008/dscf2336.jpg#1

    I’ve added rbx as a extension, so I’m wondering if I need to strip off everything after the ? character.

    Any recommendations?

  17. so — i don’t get it. is the idea behind the lazy load technique to stop the download of non-visible images and speed up the download process as a whole? right? it’s not just a superficial thing about fading them up as you scroll is it?

    i imagine that’s supposed to be the point? download the images as they come into view, so that you aren’t choking your internect connection by loading things you can’t see to begin with.

    the problem is — that doesn’t happen with this script (or any that i can tell). if you look at firebug, or safari’s activity monitor, all the images get downloaded anyway. it seems like they are just downloading twice? once on DOM load, and again as they come into view.

    am i missing something?

  18. Hmm, well, im trying it out with 1.6.0.4 and it doesn’t seem to work, tried it with the one that comes in there and it doesnt seem to work either, weird. Do the images have to be in the same directory as the js rather than in my images folder?

  19. It doesn’t work when I put another jquery file in one page, say a tooltip plugin and a zoom in image plugin.

  20. I’m going to agree with michael sablone, this script still downloads the images on initial load so this doesn’t have any effect on improving page load time….

  21. is it possible to make it work in PrototypeJS 1.5.0 ?
    this one work only for PrototypeJS 1.6.0 and up.
    perhaps a few changes could make it work with PrototypeJS 1.5.0 ? that’s what i’d really love

  22. Hi,

    I was trying to use the lazy loader library you created and noticed a bug.

    I have some small images, smaller than the loading wheel, and when those are loaded, the wheel keeps turning behind it, as a background. I notice using Firebug that this happens for your images as well, however they are big and are covering the loading gif.

    If you need more info about the error, just contact me!

    Thanks!

  23. Hi,
    Looking at your demo page, and the code I noticed that your script not only doesnt do the “lazy loading”, meaning downloading the image as you reach it with Viewport, but it downloads the images 2 times! multiplying the bandwidth.
    you can see it in firebug.
    first time the images loaded in the tag
    then the script downloads the images second time.

  24. It appears that the lazy loading feature no longer works. Using Fiddler you can see all the images load without scrolling the page

  25. fix for removing spinner image after loading original image from cache/server
    **This will happen only for transparent image**
    After successfully loading of original image you have to remove spinner , for this you have to add below line in image loading completion code in lazyScroll function

    this.element.style.backgroundImage = null;

  26. This was cool – but after browser updates it no longer works.

    Its really unfortunate that lazy loading is no longer working in any browsers. If anyone figures out a good solutions please email me at thawkes@woodstitch.com.

    I think this big problem that needs fixing.

Leave a comment

Leave a Reply to Ryan Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.