Vigrond
Vigrond

Reputation: 8198

Does 'load' event get called on img 302 redirects? How to test for this?

I think that the browser is calling the "load" event on the very first HTTP response it gets from loading an image (as long as it's not a 500 or another erroneous code)

For example

  1. Img url returns a 302 Moved Temporarily
  2. Browser calls erroneously "load" event on img tag
  3. 2nd HTTP request made, gets 200 success
  4. Image is now actually loaded

Does anyone know a way to test for this?

Maybe I'll go digging into browser code..

Upvotes: 1

Views: 2110

Answers (1)

Vigrond
Vigrond

Reputation: 8198

I was wrong and confused.

Load events happen correctly in the context of javascript.

The issue is how a browser handles a 302'd image, its cache, and a CSS transition.

For example, If you invoke an opacity CSS transition upon image load, each browser will handle it different way.

Chrome wonks up transitions on cached 302'd images Firefox wonks up transitions on all 302'd images, regardless of cache Safari handles transitions perfectly, regardless of HTTP status or cache.

See a demonstration here: http://jsfiddle.net/2TCy4/33/

Jsfiddle demonstration code:

HTML:

<figure></figure>
<div>
    <button id="withCache">Load with image cache</button><br/>
    <button id="withoutCache">Load with no image cache</button>
</div>
<pre>
Loads will alternate between loading a 200 success and a 302 redirect of the same image
When imagesLoaded determines an img isLoaded, 
a class is added and the opacity transition should begin.

On Chrome, After the first "cycle" with image cache, 
cached image buggyness becomes apparent as CSS transitions on the 302 redirect are jittered.

On Firefox, in both cache situations, 302 redirects are still bugged.
This implies Firefox uses the cached image from the 2nd HTTP request.

In Safari, transitions work perfectly regardless of cache or HTTP status.
</pre>

Javascript:

var good200 = $('<img src="https://24.media.tumblr.com/tumblr_lsoemgev4A1qh6npeo1_1280.jpg">');

var bad302 = $('<img src="http://www.tumblr.com/photo/1280/lesfascinations/11273750776/1/tumblr_lsoemgev4A1qh6npe">');

var now = Date.now();

var caption = $("<figcaption></figcaption>");

var is302 = false;
var withCache = false;

// 1.  Click a button
$('button').click(function (e) {
    withCache = $(this).is("#withCache");

    now = Date.now();
    $('figure').empty();

    setTimeout(insertImage, 0);
});

// 2. Insert alternating 302/200 img
var insertImage = function () {
    $('figure').html(is302 ? get302img() : get200img());
    setTimeout(runImagesLoaded, 0);
}

// 3.  Run imagesLoaded script
var runImagesLoaded = function () {
    $('figure').imagesLoaded().progress(function (instance, item) {
        if (item.isLoaded) {
            $(item.img)
                .closest('figure')
                .append(
            caption.clone().text('imagesLoaded: ' + (Date.now() - now) + "ms")).append(is302 ? '302 redirect' : '200 success');

            setTimeout(addLoadedClass($(item.img)), 0);

            //alternate 302 and 200 img requests
            is302 = !is302;
        }
    });
}

// 4.  Add loaded class to img when it is loaded
var addLoadedClass = function (el) {
    el.addClass("loaded");
}

var get302img = function () {
    var img = bad302.clone();
    if (!withCache) appendRandomParam(img);
    return img;
}

var get200img = function () {
    var img = good200.clone();
    if (!withCache) appendRandomParam(img);
    return img;
}

var appendRandomParam = function (img) {
    var timestamp = Date.now();
    img.attr("src", img.attr("src") + "?" + timestamp);
}

CSS:

img {
    width: 100px;
    transition: opacity 2s;
    -moz-transition: opacity 2s;
    -webkit-transition: opacity 2s;
    -o-transition: opacity 2s;
    opacity: 0;
    -moz-opacity: 0;
    -webkit-opacity: 0;
    -o-opacity: 0;
}
img.loaded {
    opacity: 1;
    -moz-opacity: 1;
    -webkit-opacity: 1;
    -o-opacity: 1;
}
figure {
    float: left;
}
figcaption {
    text-align: center
}
pre{
}
}

A potential demonstration is delaying adding the css loaded class by 100ms or more as demonstrated here: http://jsfiddle.net/2TCy4/34/

Upvotes: 1

Related Questions