Wednesday, September 28, 2005

The Ghost of NS4

There are times when you simply have to throw in the towel and do something evil. Such as, oh, make Firefox behave like Netscape 4.

A widely-used utility script was causing fatal errors in Firefox. These errors were halting the JS interpreter completely, which shut down my own code before it could even be executed. Closer examination revealed that the utility script jammed all browsers into the IE4 or NS4 category, and made extensive use of NS4-only properties like document.layers, layer.clip and layer.pageX.

Fixing the utility script to work with Firefox was not an option. The script is deployed to literally hundreds of thousands of existing websites as part of a popular WYSIWYG program. Even if I was able to provide a patch to the script, there would be no way to compel people to upgrade.

Not to mention that I'd be the one stuck maintaining and supporting a script that I didn't write.

Worse, browser detection was buried deep inside the utility script and done on the fly in several spots, all with locally-scoped variables that were impossible to overwrite.

I had to find a way to unblock these errors without touching the script.

So:

document.layers = document.getElementsByTagName("*");

Unngh! It hurts! Make it stop!

HTMLElement.prototype.pageX getter = function () { return this.offsetLeft; };
HTMLElement.prototype.pageY getter = function () { return this.offsetTop; };

Please kill me now.

I'll leave it to you to figure out how I took care of things like the getting and setting of properties like clip.left, clip.top, clip.right, etc. (hint: it involves the use of getComputedStyle, parseInt, a number of string methods and IT AIN'T PRETTY, THAT'S FOR SURE.)

Oh wait, IE6 chokes on this and tells me it's expecting a semicolon. Well, of course. IE doesn't support getter/setter. So I have to wrap this whole thing in a server-side UA sniff to ensure that it's never delivered to IE.

The ghost of NS4 continues to haunt, its icy incorporeal fingers reaching out to mess with my head.

4 Comments:

At 4:09 PM, Blogger Stuart Langridge said...

You can use __defineGetter__ and __defineSetter__? That's testable client-side, and the "getter" syntax is deprecated, I think.

 
At 7:21 PM, Blogger Brent Ashley said...

You may remember this mp3 of a Netscape rant I left on Tim Aiello's cellphone a few years ago

 
At 9:57 PM, Blogger splintor said...

You might also use eval("HTMLElement.prototype.pageX getter = function () { return this.offsetLeft; };") for problematic code.

I recall using it for try..catch syntax when we had to support NS4, which didn't accept it in the code.

 
At 9:03 AM, Blogger scottandrew said...

Oooh, I'll give __defineGetter__ etc. a try. Thanks!

 

Post a Comment

<< Home