You are on page 1of 6

Making your web page compatible with

Firefox
The following is a list of things to review so that a web page is compatible, not only with
Firefox, but with any browser which implements the latest standards, including of course
Mozilla derivates as Camino, Galeon, etc.

Some might say that making a page compatible requires double the effort in making it,
and that is not worth the trouble since everybody uses explorer. In this article I want to
show that this is not true. It's roughly the same effort to make a page that is compatible
with Firefox as one that that is not.

This text does not intend to tell you how to make pages compatible with ancient browsers
(as Netscape 4 or Explorer 4) That would certainly be a much larger task. This article
aims to guide you about supporting browsers that are very similar in their support of
things like dynamic HTML. It's not necessary to have a page for each kind of browser, it's
better to share the code while taking into account the small differences. The details
enumerated here will be used for browsers like Firefox, Mozilla, Netscape 6+,
Konqueror, Opera, Apple's Safari, etc.. Some of the properties explained which are
equivalent to those of Explorer don't belong to any standard, these cases will be noted.

Sripting. The great majority of the compatibility problems falls in this category. And they
are not generally problems with the JavaScript language itself, but with the fact that the
browsers represents the page in objects differently. A different API, sortof. This API is
called the DOM (although in Microsoft docs you should search for DHTML instead).

Let's now see which are the most common problems...

Detections
A common way of coping with different browser versions is to detect the one which is
being used. This is generally a bad idea. It's much more advisable, maintainable and
easy just to detect each desired feature when you make use of it. That way you will
automatically support all browsers which implement that feature, and will narrow the
posibility of leaving a browser unsupported. JavaScript is a very dynamic language that
allows one to ask if an object has certain method or property, so it's simple to detect
things correctly. In order to verify the existence of a method or property in an object
simply put the expression in a boolean context. For example, to ask if the property prop
exists in the object o one can write: if(o.prop) {.

Another common error is to check if the browser has something, and if it doesn't to
assume that it has another thing. The typical case involves document.layers (the
obsolete and frightful layers API included in Netscape 4). Some badly coded pages
assume that if a browser does not have document.all it's safe to assume that it supports
the other interface. This cannot be relied upon. It's better to directly test what one is going
to use.

Locating objects
Explorer 4 introduced the ability to dynamically modify the underlying page structure,
and some people called that dynamic HTML. The page structure modifications are done
from JavaScript code. As in the browser's JavaScript API there were already many things
hanging from document (such as document.forms document.images etc), someone at
Microsoft said:

― Where do we put ALL of the others?

― I've got it!: In document.all

Later, the W3C created a function for that: document.getElementById(id). It's


supported in Explorer from release 5. What do we do with IE4 users? You should not
care! Nobody uses it anymore, as Explorer 5 or better have been forced to Windows users
since Windows 98 "Second Edition". Current numbers for IE4 are below %0.1.

Now the thing is just to replace in all places this way: Where you see
document.all.theMenu.style.color="black" change it to
document.getElementById("theMenu").style.color="black".

Parentheses or brackets
In the JavaScript representation of a web page there are several arrays. And arrays are
meant to be accessed with []. Microsoft has the concept of collections in his scripting
languages, which is a variation of the same subject, but these collections are accessed
with (). They had the terrible idea to transfer this to its implementation of JavaScript,
thus document.forms(0) works in Explorer, but in no other browser. One must always
use [], i.e.: documents.forms[0].field.value and document.images[0].

Events
Accessing the event object

At first, handling an event was just to put just a little bit of code in an onclick attribute
somewhere. Netscape extended this so that one could within that small piece of code,
access an event variable. In that variable one could find out most interesting details as
what key would have been pressed and other things.

When Microsoft entered the scene they thought:


― In which object should this event variable be so that it's available in the code snippet?

― Let's put it in window, as everything which is in the omnipresent window object is


always in scope.

And thus the ugly window.event was born, which would come to be some kind of global
variable.

This window.event, in addition to being a terrible idea, is not part of any standard
(luckily). Therefore the only safe place from which it's safe to access a variable named
"event" is from the onevent attribute (e.g.: onMouseOver="..."). In that place there's a
variable named event. If a function is called, event should be passed as a parameter.
Example: <a onmouseover="mouseOver(event) "...

A somewhat more advanced use of the events consists of assigning functions to certain
properties in the objects you'd like to monitor, e.g.:
findObject("myLink").onmouseover=myFunction;. In this case the mechanism
explained in the previous paragraph is not applied. In their place, the the DOM event
standards compatible browsers will pass the event as a parameter to the myFunction
function, which could be defined the following way:

function myFunction(e)
{
// let's not forget poor Explorer
// which doesn't pass the event as a parameter
if(!e)
e=window.event;

// rest of the code


// ...
}

In Explorer, registering for events can be done by using the attachEvent function. In
Firefox, the same thing is accomplished with addEventListener (it takes an extra
boolean parameter, just put false there). Note that event names in the DOM standard
don't begin with "on", so you will need to remove that. BTW, why don't you just assign
the function to the proper element.onevent property? =)

Using the event object

The previous section covered the mechanisms necessary to get the object which
represents an event. But the issue does not finish there, since the properties defined in
Explorer are not the same ones that the properties that the standard dictates (i.e. those that
Firefox implements).
Differences in the event object properties/methods
In Explorer Description In Firefox (DOM standard)
target, but in Firefox the nodes of type text can
also fire events, so to keep things working you'll
srcElement
The element which need to climb up the tree until you find a element's
fired the event. (tag's) node:
var node = e.target;
while(node.nodeType != node.ELEMENT_NODE)
node = node.parentNode;

fromElement
The element in which target if the event is onmouseout,
the mouse was before. relatedTarget if the event is to onmouseover.
The element to which
relatedTarget if the event is onmouseout,
toElement the mouse was
target if the event is onmouseover.
moved.
Assigning true to this
property prevents the
cancelBubble event from continuing
The stopPropagation() method of the event
should be called.
propagating upwards
in the DOM tree.
Assigning false to this
property is requesting
to Explorer not to
returnValue The preventDefault() method should be called.
execute the event's
default action (like
following a link).
If the mouse is on a absolutely, fixed or relatively
positioned element, then you can use layerX,
layerY (non-standard). However, event.target is
in a normally (static) positioned element these
Position of the event
properties will give you the offset with respect to
offsetX, with respect to the
the document root element (which normally
offsetY element that generates
corresponds to the page). In this case your only
it.
option is to manually calculate the "offsetX" value
by traversing all the hierarchy from the document
root element, adding the objects' offsetLeft /
offsetTop values.

Assorted differences in the DOM tree


By DOM tree I mean the hierarchic structure of objects that the browser uses to represent
the tags that make up the page. There are small differences that can affect the
compatibility of a page.
Differences in several properties and methods
In Explorer Description In Firefox
window.screenX - someValue,
window.screenY + someValue These
Position of the properties are not extactly the same as the
window.screenLeft,
window.screenTop
window browser Explorer ones. In explorer they give the
relative to the screen. coordinates of the origin of the IE control,
while in Firefox they give the origin of the
Firefox window itself.
element.attachEvent( Attachs function to element.addEventListener(event_nam
event_name, element's e, function, false), but see above.
function) event_name.
DOM level 2 does not have an equivalent
method, but a very simple method like the
shown below can be used (it works in
Firefox and Explorer):

// Finds out if a is an ancestor


of b
function contains(a, b)
This method is {
available in every // we climb through b
contains(node)
element, and allows parents
to ask if another // till we find a
while(b && (a!=b) &&
node is a descendant (b!=null))
of this one. b = b.parentNode;
return a == b;
}

The new DOM level 3 standard defines


node.compareDocumentPosition() and
Firefox already implements it, but
Explorer doesn't.
document.defaultView. Note that the
It obtains the window object is available everywhere. It
document.parentWindo
w window in which the could make some sense in frame-using
document is. pages, but I don't think the lack of this
property would render anything imposible.
Access a form You may use document.myForm, it works
myForm defined by <form
name="myForm">
everywhere.
In Firefox, this property is called
Replaces element's
textContent. It's part of the DOM Level 3
element.innerText content with the
standard. Supported since Mozilla 1.5, and
specified plain text.
in all Firefox versions.
children Array of child The DOM doesn't define such a thing. But
element nodes. it defines that each node has a
Differences in several properties and methods
In Explorer Description In Firefox
childNodes property which is very
similar. The big difference is that
childNodes also includes text nodes. So,
if you have code which does
children[n], then you'll have to replace
it with childNodes[n+Z], where Z is the
number of (previously ignored) text nodes
which are before the wanted element.

The sad part is that Explorer does not


support childNodes.
Mozilla has implemented support for
element.designMod having editable content (it's called
element.designMode e too, but with many "Midas" in Mozilla), but it has a slightly
differences. changed API. They have documented
converting this to Firefox.

ActiveX
No way. No other browser supports ActiveX. But you still may be lucky: Some of the
features which are available through ActiveX can be accessed in Firefox without it! If
you are using a custom component, there you are out of luck.

The code which can easily be replaced is:

In Explorer In Firefox Notes


It's also sup-
ported in the
new
new Explorer 7.
ActiveXObject("Microsoft.XM new XMLHttpRequest() You may
LHTTP") also check
Apple's
documentati
on.
new The API is
document.implementation.createDoc
ActiveXObject("Microsoft.XM
ument(ns, root-element, null) slightly
LDOM") different.

You might also like