Search code examples
jqueryimagefirefoxlazy-loadingjquery-lazyload

How to handle "image corrupt or truncated" in firefox


PLUGIN

I am using a jQuery plugi called lazyload.

What this does is lazy load images - meaning it does not render them in the browser until the image is within the scope of the viewport.

This is useful when you have a page that has many images, for example, and you don't want it to spend forever with the initial load.

FIREFOX

Ok, so I am also using Firefox version 23.0.1

PROBLEM

The plug in is great, however when scrolling down after some images I start getting errors where the image doesn't load (just has a generic place holder for a broken image link) and in the console it logs:

Image corrupt or truncated: [image url]

It is not that there is a problem with the image. They all render fine individually.

It is not on a SPECIFIC image as it is random. If I load the page again, the images that were corrupt may load now, with other images returning a broken link and logging corrupt in the console.

I searched around for this, and it seems that there is some problem with simultaneous fetches for an <img> src tag.

Possibly there should be a delay set on the fetch, however you cannot always tell how long the delay should be. And if one image is larger than another, it could still conflict (with a static delay time, as opposed to a complete callback).

Therefore, I would like to request:

a) If anybody knows of a solution to this (such as catching when the error occurs and re-triggering the load image function)
b) If anybody can propose an $.extend() to the library above (lazyload) that would create a callback function and wait until all active fetches are complete before loading the next one (IF this is the problem - I am not sure if it is) I am not a jQuery ninja so I am a little lost on the code. I could figure it out, but it would probably be dirty...
c) if this is NOT the problem, then some direction as to how I can solve this would be appreciated


Solution

  • As suggested on this answer to a problem similar to yours:

    It appears that when changing the src attribute of the img tag, Firefox fires a load event. This is contrary to the HTML5 specification, which says that if the src attribute is changed, then any other fetch already in progress should be ended (which Firefox does), and no events should be sent. The load event should be sent only if the fetch was completed successfully. So I'd say that the fact that you get a load event is a Firefox bug.

    And then:

    The best option may be to create a new element each time you wish to change the src attribute.

    Which makes sense. Inside lazyload code, you'll find this one part, that seems to be when the image loads, responding to an scrolling event that triggers appear:

        /* When appear is triggered load original image. */
        $self.one("appear", function() {
            if (!this.loaded) {
                if (settings.appear) {
                    var elements_left = elements.length;
                    settings.appear.call(self, elements_left, settings);
                }
                $("<img />")
                    .bind("load", function() {
    
                        var original = $self.attr("data-" + settings.data_attribute);
                        $self.hide();
                        if ($self.is("img")) {
                            $self.attr("src", original);
                        } else {
                            $self.css("background-image", "url('" + original + "')");
                        }
                        $self[settings.effect](settings.effect_speed);
    
                        self.loaded = true;
    

    You can put an AND operator followed by some flag or fuction return that verifies if the last image is already fully loaded on that part:

    if ($self.is("img") && lastImageIsLoadde() === true) { /*pseudocode here*/
    

    thus preventing that img src gets replaced before its correct time (since settings.placeholder is the image the script takes stand in the place of the one about to be loaded when scrolling) and see if it works for you.