Reputation: 8198
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
Does anyone know a way to test for this?
Maybe I'll go digging into browser code..
Upvotes: 1
Views: 2110
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