jQuery graphical header image replacement
Jun1st
2009
••
Several months ago I had a project that included feeding ad images into the sidebar of a page. Not a big deal but, there was an issue. These images were all coming from a third party. There was a small chance that these images would not be uploaded correctly and seeing that I had no sure fire way to make sure that the images would either be there or named correctly, I needed a solution so Internet Explorer would not show the dreaded ‘no image’ icon.
I found a snippet of jQuery that would check to see if the image loaded and if not, just erase the content of the parent div. This way if the image didn’t load, nothing did. Simple solution.
Based of that I wrote of this small script to do the same thing but with graphical headers. I know there are plenty of solutions to using accessible graphical headers so you may ask,”why another, and why jQuery?” Why not?
One note to start. i have not been able to get this to work at all in Opera. I have tested in Firefox, Safari and IE6 & 7 though. they all seem to work with the desired effect. If you find a solution to the Opera issue, please let me know.
Some benefits as far as I can see with this method.
- No need for nested spans or negative text-indents.
- No js? no problem. The user gets styled text instead.
- Still works with styles disabled and usable for print style sheets.
Some cons:
- With js and styles off, the user gets both the text and the image.
- There has to be more.
Take a look at the jQuery used
$(window).bind('load', function() {
$('h2 a img').css({ border: 'none', display: 'none' });
$('<img src="http://www.google.com/intl/en_ALL/images/logo.gif' + '#' +
Math.random() + '"/>').load(function() {
$('h2 a img').each(function() {
if((typeof this.naturalWidth != "undefined" && this.naturalWidth == 0 ) || this.readyState == 'uninitialized' ) {
$(this).css('display', 'none');
} else {
$(this).parent().each(function () {
var h2Image = $('img', this).attr('src');
var h2Text = $(this).html();
$(this).empty();
$(this).append('<img src="' + h2Image + '" border=\"0\" />');
$('img', this).css('display', 'inline');
})
}
});
});
});
Not to exciting or complicated but, nonetheless I will try to explain the going-ons involved with this. First though, take a look at the sample page to get an idea of how it looks.
At the start I am using the $(window).bind('load', function() { to make sure the whole document loads before the script fires. This is to make sure that if the images want to load, they will be fully loaded before jQuery moves in a checks for them. Because of possible traffic issues and file sizes this is better than the typical $(document).ready() way of doing it.
Next we ask jQuery to check and see if the browser has images capabilities. Using $('<img src="http://www.google.com/intl/en_ALL/images/logo.gif' + '#' + Math.random() + '"/>').load(function() { we ask the browser to load the Google logo in the background. If it does it continues with the rest of the function. In testing, this image needs to be hosted and not on localhost. That will always produce a false positive. Make sure the URL to the image is to an image that will always be there. Safest bet is to upload a small image to your server. After all, if your site is down, this script won’t be there either.
Next we simply transverse all the elements we want to with $('h2 a img').each(function() {. In this case I only want to check for images inside an anchor tag that is a child of a <h2>. Once we have that we make one more safety check before moving on. if((typeof this.naturalWidth != "undefined" && this.naturalWidth == 0 ) || this.readyState == 'uninitialized' ) { $(this).css('display', 'none'); } checks to see if the images we are looking for have loaded. This is different than the first browser image check. This one will tell if a header doesn’t have an image or if the URL to the image is broken. If either of those scenarios are true, the script then applies display: none; to the image tag then moves on.
The next step now assumes that the browser has images on, the images are there and that they have loaded.
else {
$(this).parent().each(function () {
var h2Image = $('img', this).attr('src');
var h2Text = $(this).html();
$(this).empty();
$(this).append('<img src="' + h2Image + '" border=\"0\" />');
$('img', this).css('display', 'inline');
})
}
In this case $(this) is still equal to saying $('h2 a img'). So we tell the script to find all images in the headers and then look at the parent of the image; the anchor tag. Now set up two variables. One to grab the SRC of the image (var h2Image = $('img', this).attr('src');) and another to grab the HTML of the anchor (var h2Text = $(this).html();). The fun part, the last variable does nothing in this example, I just forgot to take it out.
So great we have all the hard stuff out of the way. So these last three lines are actually the part that does the visual work.
$(this).empty();
$(this).append('<img src="' + h2Image + '" border=\"0\" />');
$('img', this).css('display', 'inline');
First empty the contents of the anchor. What this does is clears out the actual text but, it also clears out the image tag so we need to rebuild it. That’s the second line. Remember the variable from the previous lines? Here’s where it gets used. The final line applies an inline style to the image to over ride the display: none; in the original CSS rules.
That’s all there is to it. Again take a look at the sample page, to see i t in all it’s glory. If you can fix the Opera issue or have any thoughts on this, feel free to chime in.












