This article is outdated. It does not represent my current views any more. Please see the second version instead. Comments about this page will be ignored.
In its 164th edition, the inestimable A List Apart has published an article about JavaScript Image Replacement, a technique I seem to have invented. Unfortunately author Christian Heilmann doesn't have the faintest idea what he's doing. In addition, I strongly feel that ALA should not publish JavaScript articles at all, since it seems to be incapable of judging them.
At the end of October 2003, scant days before launching this site, I realized that the much-publicized Image Replacement technique uses the wrong tool. While dozens of web developers have created CSS versions, I feel that image replacement should be done by JavaScript.
JavaScript Image Replacement (JIR, inevitably) was born. I did some serious theoretical thinking and published my own script to give an example of how it could work.
A month later Christian Heilmann, with A List Apart's connivance, butchered my ideas in his JavaScript Image Replacement. It hurt, so I struck back.
I feel that Heilmann's script is inconceivably worse than my own for several reasons I'll describe later on. I feel that Heilmann cannot be trusted to write cutting edge scripts. I feel that his article should never have been published on A List Apart.
First of all a bit of personal, subjective criticism not of the content, but of the introduction. Although Heilmann gives me credit as the one who had the idea for JavaScript image replacement, he has not made my name link to this site, something that has become a habit when referring to other web developers. It's no law, I know, but I'm annoyed by this refusal of common courtesy.
In addition he misspelled my name. It's "Peter-Paul Koch", with the dash. I can easily forgive this small lapse, though.
Besides, Heilmann does not link to the actual mail I sent to css-d, the mail during the writing of which I made my discovery. Instead he links to css-d in general. As an historian I must object to this disregard for proper source quotations.
Finally, Heilmann does not mention my page at all. Although this is not an error in itself, I feel that if he'd actually read it he'd have written a far better article.
Of course the fact that I don't get the boatload of visitors any ALA link would deliver on my doorstep colours my perception. Then again, even Heilmann concedes that I invented JIR, so could I please have proper credits?
Heilmann does not understand the theoretical part of JIR. The real point is not the script or the XHTML that you use, but whether it's preferable to replace images by CSS or by JavaScript.
This touches on very important questions for the near future: which line divides CSS and JavaScript? Which functionality belongs in the presentation layer, which belongs in the behaviour layer? Any image replacement technique is merely a case study that might help us solve these questions.
I have no answers to these questions, in fact my study has just barely begun. I feel, though, that they should be prominently mentioned because they are far more important than the actual script.
In addition, the CSS FIR debacle teaches us valuable lessons about assuming things about user agents. Heilmann blithely ignores such considerations. In fact, the CSS assumptions Joe Clark has dispelled pale into insignificance when compared to Heilmann's assumptions.
The script itself is not a miracle of clean, modern JavaScript coding either. Heilmann uses a JavaScript array to store the data saying which header should be replaced by which image:
replaceImages = new Array( ’About us|about.gif’, ’History|history.gif’, ’Contact Us|contact.gif’ );
I intensely dislike arrays because they easily turn into a maintenance nightmare. We don't need them any more; the W3C DOM offers far superior ways of storing script data.
I understand why Heilmann has not copied my solution. I use custom attributes in the headers themselves to store this data:
<h3 replace="fir_script">The script</h3>
The problem is of course that custom attributes are not allowed in XHTML. Personally I don't care, but I know
that others will care and will search for another solution. This solution could be to store the data in a
valid attribute, like id. I feel that this is infinitely preferable to an array-based solution.
So far it's a matter of coding style. Later on we'll see, however, that this data array may cause serious problems.
Heilmann's next step improves on my script. He goes through all possible headers that might exist on the page by getting them all by tag name. Nice extension. His object detection is flawless, too.
function firdom(){
if(document.getElementsByTagName && document.createElement){
for (l=1;l<=6;l++){
h1s=document.getElementsByTagName(’h’+l);
scanandreplace(h1s,’h’+l);
}
}
}
Nonetheless this single good point doesn't save the article.
The main script, the script that actually does the replacement, contains many, many errors.
function scanandreplace(h1s,tag){
for(i=0;i<h1s.length;i++){
for(f=0;f<replaceImages.length;f++){
chunks=replaceImages[f].split(’|’);
thish1=document.getElementsByTagName(tag)[i];
if(thish1.firstchild.nodevalue==chunks[0]){
newimg=document.createElement(’img’);
newimg.setattribute(’alt’,chunks[0])
newimg.setattribute(’src’,chunks[1])
// or newimg.src=chunks[1];
thish1.replaceChild(newImg,thish1.firstChild)
}
}
}
}
Did you spot the syntax errors?
if(thish1.firstchild.nodevalue==chunks[0]){
should of course read
if(thish1.firstChild.nodeValue==chunks[0]){
And
newimg.setattribute(’alt’,chunks[0]) newimg.setattribute(’src’,chunks[1])
should of course read
newimg.setAttribute(’alt’,chunks[0]) newimg.setAttribute(’src’,chunks[1])
Finally the crucial line
thish1.replaceChild(newImg,thish1.firstChild)
is missing from the complete code example in the middle of the article.
In a technical JavaScript article this is relatively unforgivable. Any copy-pastable code example should be free of syntax errors. Period.
Fortunately these errors don't occur in the line-by-line discussion that follows the complete script or on the example page. Nonetheless someone has been seriously asleep during the production process. Sloppy, very sloppy.
Incidentally, it's interesting to note that other people are copying my method of presenting and explaining JavaScripts: first an introduction, then the whole copy-pastable script, finally a line-by-line discussion. I must have done something right all along.
A major editing error is dumb, but forgivable. When we study the actual content it gets worse in a hurry.
Heilmann's script loops through all headers on the page, and that's of course necessary. However, for every header it finds it subsequently loops through the entire data array! In his example Heilmann uses only three images, making for a total of 9 comparisions of header text and data array. That's manageable.
When we use the script on a real-life page, though, and when we take into account that sooner or later someone will want to use it to replace not only the headers but also the main navigation links by images, this technical problem becomes much worse.
Let's say we want to replace 20 texts by images.Then you end up with 400 comparisions of header text and data array. Can you hear the browsers churning and panting to keep up? Can you imagine how much worse the problem becomes with 30 or 40 replacements?
These potential problems could easily have been solved by using a better way of data storage and retrieval, but Heilmann doesn't seem to have given this problem any thought.
He even ignored the basic precaution of adding a break
statement to break off the comparision loop after the correct data has been found. This would have significantly
reduced the number of comparisions.
This part of the script sucks.
Heilmann's script seems to have serious problems in Mozilla with images switched off: the browser shows nothing at all. My script has another browser incompatibility pattern, and its worst failure is that it simply does not work in Safari. No problem, the original text is still there to inform the reader.
Therefore in browser compatibility, too, Heilmann's script is worse than mine.
To crown his work, Heilmann messes up the actual image replacement. He just does
thish1.replaceChild(newImg,thish1.firstChild)
and blithely assumes everything will work fine. Well, it won't.
On my own page I clearly explain that you should not just insert the image into the document because this will have serious consequences. Heilmann could have known, but he didn't pay attention.
IBM's Home Page Reader is built on top of Internet Explorer, and its product page states that it handles JavaScript. Therefore it might execute Heilmann's script and replace header texts by meaningless images.
Instead, I feel that we should wait until the image has been loaded before inserting it into the document. If the browser actually loads the image, we can be reasonably sure that it in fact supports the display of images. Then, and only then, it is safe to insert images.
A cursory glance at my page could have informed Heilmann of all this. If he'd disagreed with my admittedly speculative conclusions I wouldn't have minded, it might have lead to an interesting discussion.
Instead he completely ignores the problem, while it is the crux of JavaScript image replacement. How do you find out if a browser can handle image replacement? What happens when it doesn't?
Well, what happens when a browser that doesn't support images runs Heilmann's script? It shows the bleeding ALT text!
Why don't we give no-image browsers a nice CSS-enhanced header text? Why do we have to put up with this ugly, avoidable bit of distortion?
Christian Heilmann doesn't have the faintest idea what he's doing. He should stop butchering my ideas. It hurts.
This whole article sucks. It pays no attention to crucial theoretical questions, the script it presents is flawed on two major points because the author doesn't know what he's doing, and the editor was asleep while preparing the code examples.
The worst part is: it doesn't even surprise me. ALA articles about JavaScript suck in general.
When ALA presents articles about accessibility, design, usability, CSS or copy I read them with care. I was very, very happy with Joe Clark's brilliant refutal of CSS image replacement. I practically drooled when I read Douglas Bowman's Sliding Doors of CSS revelation. In fact, when I finished it I immediately read it again, and that's something I almost never do. I can't wait to use this technique in a commercial website.
That's the content I expect to find on ALA. Solid, serious articles that explore the very frontiers of our knowledge, offer interesting new viewpoints or novel techniques for creating simple, appealing websites.
Unfortunately ALA articles about JavaScript, PHP or another programming language somehow don't cut the cake. In fact, I feel that since J. David Eisenberg's July 2000 article DOM Design Tricks II ALA has not published any good programming article.
The point of the JavaScript articles is vague, the content, mediocre, new viewpoints, absent. Worse, they hinder JavaScript's growth towards a fully fledged client side behaviour layer, to stand next to the CSS presentation layer and the XHTML structure layer. These articles consistently ignore the real, underlying questions in favour of a bunch of childish wow-factor nonsense scripts.
Apparently the ALA editors cannot judge JavaScript articles on their merits because they lack the technical knowledge. That's fine with me, I can live with an ALA that only publishes guru-level articles about CSS, accessibility and usability.
But ALA should not try to do what it cannot do. If it cannot judge JavaScript articles, it shouldn't publish them. ALA is doing itself a singular disservice by publishing this sort of very bad content. It demeans itself. ALA is supposed to be about quality, not about amateurish nonsense.
In addition, it might be taken less seriously by web developers like myself who work a lot with JavaScript, and eventually they might start to ignore it, even the good stuff that it publishes in wholesale lots.
ALA: I don't want to lose you. Please do not publish any more JavaScript articles. Stick to what you know.