Detecting if images are disabled. (CSS On / Images Off scenario)
It was recently brought to my attention that Facelift Image Replacement wasn’t displaying in all browsers properly when images were turned off. It seems I only tested this scenario in Firefox 3, which beautifully handles the situation.
The rest of the browsers weren’t so nice. Safari displays nothing, IE displays a box with the alt text in an ugly small font, and Opera puts a box around the text.
I’ve seen a couple “detect if images are disabled” scripts around the web but they all required that the page actually load before images could be detected. This approach simply wouldn’t work for Facelift. There would be too much of a delay between image detection and replacement. So, yesterday I decided to revisit this problem and try to create a function that would give instant feedback to whether or not images are enabled.
Well, I succeeded — partially. It works in all browsers that I’ve tested (with Javascript) and IE too (with a small delay). Firefox, Safari, Opera, and IE (>=IE5.5) all work. It looks like most of the other browsers do too but I am unable to test thoroughly (Konquerer, Camino, Epiphany, Iceweasel, etc.).
Open the test page that I used to test this script: detect if images are enabled/disabled.
The code (uncommented code available at end of this post):
var DetectImageState = {
version: '1.0'
// Images default to being disabled
,imagesDisabled: true
// The ID of the test IMG that is inserted into the document
,inserted_id: ‘detectimagestate-test-img’
// Once detection is complete, this function will be called
,callback: function() { }
// Internal. Prevents the callback function from being called twice
,ie_detectionComplete: false
// The inserted test IMG in the document
,img: null
// The maximum amount of time to wait for onabort to fire. In my tests it
// usually fired between 6-50 milliseconds. I put it at 100 just to be safe
// but you could probably safely drop it down to 50
,ie_Timeout: 100
,init: function(testerimg, cb) {
this.callback = cb;
// Insert test image into document. Make sure it is not loading a cached
// image by adding Math.random to the request
document.body.innerHTML += ‘<img id=”‘+this.inserted_id+’” style=”visibility:hidden; position:absolute;left:-1000px;” src=”‘+testerimg+’?'+Math.random()+’” alt=”" />’;
this.img = document.getElementById(this.inserted_id);
// Opera has problems with the normal Image.complete method
if(window.opera || navigator.userAgent.toLowerCase().indexOf(’opera’)>-1) {
// But I discovered that when you change the image’s src to about:blank
// you can figure out if images are enabled/disabled
// This only works at the time of the initial request
// and not if the visitor turns off images after that.
// Tested in Opera 9.26-9.51
var pre = this.img.complete;
this.img.src = ‘about:blank’;
this.imagesDisabled = (!pre && this.img.complete) ? false : true;
// Provides immediate feedback
DetectImageState.callback(this.imagesDisabled);
return;
}else if(typeof this.img.readyState != ‘undefined’) { // IE
// Forcing the image to load a different src will cause onabort to fire.
// But only when images are enabled.
this.img.src = this.img.src+’?'+Math.random();
this.img.onabort = function() {
DetectImageState.ie_detectionComplete = true;
DetectImageState.imagesDisabled = false;
DetectImageState.callback(DetectImageState.imagesDisabled);
};
// Wait the time specified above for the onabort to fire. If it
// doesn’t, we know images are disabled. Tested in IE 5.5-8.
setTimeout(’if(!DetectImageState.ie_detectionComplete) DetectImageState.callback(DetectImageState.imagesDisabled);’, this.ie_Timeout);
return;
}else {
// The rest of the browsers.
// If images are disabled, firefox will immediately set the complete
// property to true. Since an image request will ALWAYS take time,
// we can figure out if images are enabled/disabled.
// This detects when images are enabled in all browsers. I am not
// sure if it will work equally as well for disabled.
// Tested in Safari, Firefox.
this.imagesDisabled = this.img.complete;
DetectImageState.callback(this.imagesDisabled);
return;
}
}
};
What’s Going On
Most browsers (except IE) have an Image.complete property that identifies when the image has completely loaded. The benefit of this property is that when images are disabled, it will return true immediately. No request for an image should be satisfied immediately, so if it is set to true right after you set the Image’s src, we know browser images have been disabled.
IE has .complete but it doesn’t seem to work. So, to get the script to work in IE I accidentally discovered that if you change an Image’s src, the onabort will fire — but only when images are enabled. This allows us to detect when images are enabled, and then set a delayed call to check if they aren’t.
How to Use It
Unfortunately, (because of IE) it is not as simple as var images_supported = DetectImageState();
Instead, you have to create a callback function:
DetectImageState.init('/path/to/some.jpg', images_detected);
function images_detected(bDisabled) {
alert('Images are: '+(bDisabled?'disabled':'enabled'));
}
I know this isn’t a perfect solution, but it seems to work. In an ideal world all the browsers would somehow let us know if images are disabled. Another example:
<html>
<body>
<script>
DetectImageState.init('/path/to/some.jpg', page_init);
function page_init(bDisabled) {
if(bDisabled) {
// don't insert images
}else {
insert_some_images();
}
}
</script>
</body>
</html>
Uncommented code:
var DetectImageState = {
version: '1.0'
,imagesDisabled: true
,inserted_id: 'detectimagestate-test-img'
,callback: function() { }
,ie_detectionComplete: false
,img: null
,ie_Timeout: 100
,init: function(testerimg, cb) {
this.callback = cb;
document.body.innerHTML += '<img id="'+this.inserted_id+'" style="visibility:hidden; position:absolute;left:-1000px;" src="'+testerimg+'?'+Math.random()+'" alt="" />';
this.img = document.getElementById(this.inserted_id);
if(window.opera || navigator.userAgent.toLowerCase().indexOf('opera')>-1) {
var pre = this.img.complete;
this.img.src = 'about:blank';
this.imagesDisabled = (!pre && this.img.complete) ? false : true;
DetectImageState.callback(this.imagesDisabled);
return;
}else if(typeof this.img.readyState != 'undefined') {
this.img.src = this.img.src+'?'+Math.random();
this.img.onabort = function() {
DetectImageState.ie_detectionComplete = true;
DetectImageState.imagesDisabled = false;
DetectImageState.callback(DetectImageState.imagesDisabled);
};
setTimeout('if(!DetectImageState.ie_detectionComplete) DetectImageState.callback(DetectImageState.imagesDisabled);', this.ie_Timeout);
return;
}else {
this.imagesDisabled = this.img.complete;
DetectImageState.callback(this.imagesDisabled);
return;
}
}
};

August 18th, 2008 at 11.46.24
Wow… nice work on figuring all that out. Really impressive.
Even though I’ve only ever come across a single user that somehow had images turned off (and didn’t even realize it, amazingly enough), having Facelift handle this automatically (which I assume is coming) is pretty amazing.
[Reply]
Cory reply on 2008-08-18 14.58.45:
Thanks! It is coming, indeed. And I agree, I’ve never seen it either which is why I think I’m going to make it default to off.
Holy crap this post is riddled with grammatical errors. I’m sorry you had to suffer through it.
[Reply]
September 12th, 2008 at 23.23.17
Hi Cory,
Thank you for sharing this script. I have been looking for “image detection script” and found your excellent code here.
Zaenal
[Reply]
September 26th, 2008 at 11.16.22
I am on IE7 on WinXP SP2, and it fails to correctly identify for me. It says images are disabled, yet it’s displaying the images (the black and red gradient PNG’s) right next to that message.
My debugger (CompanionJS) doesn’t find any errors with the script, but it does show that 3 “logs” have occured. However, when I click to view the log events, it’s blank, so I don’t know what that’s about.
[Reply]
Cory reply on 2008-10-21 22.07.03:
Kyle, thanks for reporting your problem. vrhee on the forums was having a similar problem and seems to have found a solution. http://forums.mawhorter.net/viewtopic.php?pid=825
[Reply]
December 27th, 2008 at 04.03.35
Thanx a lot for your work. I really appreciate it!
[Reply]
December 30th, 2008 at 00.17.56
please help me…
i confuse about detect image in firefox 1.5 with java script
[Reply]
Cory reply on 2008-12-31 18.59.02:
What is the problem?
[Reply]