Skip to content

ara pehlivanian

Web Standards, Web Culture, Web Everything.™

Hacking the Technorati Badge or: How I Hacked Document.Write() in Order to Make it Work With application/xhtml+xml

I’ve reworked this code to make it unobtrusive and consequently lighter. See “Hacking the Technorati Badge part Deux” to read about it.
The first thing I noticed when I switched to application/xhtml+xml was how unforgiving the XML parser is with badly formed markup. It stops parsing and displays a big fat red error message where your page is supposed to be. The second thing I noticed was how my nifty little third party JavaScript includes all stopped working. I’m talking of course about my AdSense ads and my Technorati Badge (which is now back in my footer thank-you-very-much).

Looking into the mystery disappearance I found that I was getting a bunch of JavaScript errors like this:

uncaught exception: [Exception... "Object cannot be created in this context" code: "9" nsresult: "0x80530009 (NS_ERROR_DOM_NOT_SUPPORTED_ERR)" location:...

Putting two and two together I realized that “Object cannot be created in this context” and “ERROR_DOM_NOT_SUPPORTED” meant that JavaScript’s document.write() method wasn’t supported in the XML DOM.

Well, after a few frustrating evenings of trying to write a string-to-html-DOM-nodes parser in JavaScript (yes, I can be that dumb sometimes) and a few philosophical discussions with Mathieu, I finally gave up. That is until he gave me the key to fixing this problem. You see, I got pretty far in my string-to-html-DOM-nodes parser work. The problem wasn’t that. The problem I was having–and what Mathieu so deftly solved–was in identifying where the document.write() was occuring. Maybe it would help at this point if I told you that my solution to getting document.write() working in application/xhtml+xml was to override the document.write() method and redirect it through a function of my own. That way I could manage what it did and essentially force it to play nice instead of crapping out. Every time I referred to this in my override code I just got the document object returned to me, rather than the DOM node that the script was being run in. (You know what I mean, when Technorati or AdSense tells you to just plop their ready-to-go, cut-and-paste <script> tag into your page.) So what, you may ask was Mathieu’s solution? A global variable set to the current script tag’s parent node’s ID. That way, the document.write() override could just grab that node and do its work inside it.

Then of course I also realized that I could replace my tedious, potentially error prone, and ultimately overkill code with a simple .innerHTML instead. That’s right, the non-standard workhorse .innerHTML which is no worse than using the W3C’s DOM methods (thanks PPK). So even though the purist in me was screaming for me to use my recursive beast of a node creator, the minimalist in me said “what are you crazy? Just use .innerHTML“.

Long story short (too late for that huh?) here’s the code. Oh and there’s an added function in there to clean up Technorati’s broken markup. Yes, you heard me, it’s broken.

The JavaScript:

var Utils = {
	DWID : "",
	DW : function(str){
		var el = document.getElementById(Utils.DWID);
		str = Utils.CleanTechnorati(str);
		el.innerHTML = str;
	},
	CleanTechnorati : function(str){
		return str.substring(0, str.indexOf("&#187")+5) + ";" + str.substring(str.indexOf("&#187")+5, str.length);
	}
}
document.write = Utils.DW;

The XHTML:

<script type="text/javascript">Utils.DWID = "technorati_include";</script>
<li id=”technorati_include”><script type=”text/javascript” /></li>

So basically, every time you’ve got a script you want to include, you just change the value of the global variable just before and assign it the script’s parent element’s ID and you’re all set! Enjoy!

Sphere: Related Content

  • Comments closed

Buy my book

The Art & Science of JavaScript / SitePoint
The Art & Science of JavaScript

Advertisement

Firebug - Web Development Evolved

Advertisement

6 Comments

  1. Gravatar for Hacking the Technorati Badge part Deux | ara pehlivanian—Web Standards, Web Culture, Web Everything.™Hacking the Technorati Badge part Deux | ara pehlivanian—Web Standards, Web Culture, Web Everything.™ says:

    [...] In my previous post on Hacking the Technorati Badge I told the tale of how I managed to get it working with the application/xhtml+xml MIME type. Since then I tweaked the technique and managed to get rid of the extra <script> tag immediately preceding the XHTML element you want badge to appear in. I was able to do this by identifying the word “technorati” in the src attribute of the <script> tag and then inserting the contents of the badge immediately next to it. [...]

  2. Gravatar for Patrick FitzgeraldPatrick Fitzgerald says:

    Brilliant! I wonder if you can also then “defer” the script so it runs onload or at the end of the page (and thus does not slow down the initial display of the page).

  3. Gravatar for AraAra says:

    Patrick: I’m working on a way to do that because right now the script only works for single document.write()s. As soon as you have multiple writes in a script my “fix” bombs. I was thinking of building an output string and dumping it every time I encounter a new <script> tag, but I’m having a bit of a hard time processing it while the page is loading. I’ll figure something out I’m sure. :-)

  4. Gravatar for document.write() fix for (real) XHTML | ara pehlivanian—Web Standards, Web Culture, Web Everything.™document.write() fix for (real) XHTML | ara pehlivanian—Web Standards, Web Culture, Web Everything.™ says:

    [...] My first attempt only worked with one script tag. My second attempt wasn’t really an attempt at all. I took an idea I had, quickly typed it into my editor, saved and saw it working fine (on a page with just one script tag in it). I soon realized that it was really bad code and disabled it. [...]

  5. Gravatar for name is requiredname is required says:

    To solve the “script only works for single
    document.write” problem, why not append?

    el.innerHTML += str;

    But of course even if you fix there broken html, there is
    always the problem that they can change there source and
    broke it again without a warn.

  6. Gravatar for AraAra says:

    name is required: Good call, but I think the parser may complain if you write only a part of a nodeset to the DOM and wait for the next document.write to complete it (hence the stack I coded in the latest version of the script which gathers all the pieces and then inserts them in one shot).

    Also, about the broken html–unfortunately that’s life. This whole script is a “fix” for a bad practice to begin with. Deciding to use application/xhtml+xml means that your markup has to be perfectly valid and unfortunatley when you import markup from other sources you can’t always rely on them to validate. This goes for everyone using these JavaScript includes. The only difference is that for me (and anyone else using real XHTML) the parser bombs when there’s a problem with the markup instead of just ignoring it. Thus the need for vigilance. But I’m not too worried. I told Technorati about their broken markup a while ago and they still haven’t done a thing about it. So I doubt things will be changing anytime soon. ;-)

Sorry, the comment form is closed at this time.

Skip to navigation

More stuff by Ara elsewhere on the web

    Snook Approved!

    © 2005-2008, Ara Pehlivanian.

    Stock photography courtesy stock.xchng. This site uses Akismet to catch spam (54,743 caught since May 2006) is hosted by DreamHost and powered by WordPress.