Cross Browser JavaScript



 Introduction

If you have to implement a Web application that intensively uses JavaScript
for some client side effects or some AJAX like features, and if you have to
support more than Microsoft Internet Explorer 6.0, then you might find here a
not widely known trick to make your programming easier by implementing a
small compatibility layer.
Both browsers, Microsoft Internet Explorer and Mozilla/FireFox, do have a
lot of functionalities as defined by the standards HTML, CSS and JavaScript,
and some of them are really useful for implementing some functionality on
the client. Because there are some extensibility features available on these
different platforms, it is possible to extend one browser with methods and
properties that are not available in the other one out of the box.

JavaScript Prototypes
The JavaScript language interpreters included in the browser platforms offer
almost identical functionalities. There is no real need to use this feature to
bring some missing functionalities to one of the platforms, but it is an
interesting feature anyway and it gives you the chance of extending both
platforms.
The object types of JavaScript, better called intrinsic objects of JavaScript
(String, Number, Array, ... ) that are part of the JavaScript language have an
extensibility mechanism by using the available prototype property.
By attaching new functions to the prototype, you make this method available
to all objects that derive from that type.
The following sample adds a trim() method to all string objects that eliminates
all leading and trailing blanks and returns a new string with the remaining
characters (if any):
String.prototype.trim = function() {
return (this.replace(/^[\s\xA0]+/, "").replace(/[\s\xA0]+$/, ""));
}
To use this function, you will use the following syntax:
var s = " Hello World ";
var txt = s.trim(); // returns only "Hello World"
You can use this extensibility feature in Internet Explorer and
Mozilla/FireFox to add new methods and (readonly) properties to the intrinsic
objects, but there is no cross browser way to capture the access to properties
of those objects.
You might think that it is also possible to add a global method trim(s) that
uses a parameter and the return value to do the same thing, but you might get
in conflict with other variables or methods from different libraries using the
same name. You can also add a trim method to the Array object that handles
array items, without getting a conflict.
Some general information about the prototype property can be found at
http://msdn.microsoft.com/library/en-us/script56/html/js56jsproprototype.asp

JavaScript Prototypes in Mozilla/Firefox
The Mozilla/Firefox platform also offers a proprietary but very useful
extension model that allows to also implementing properties on the JavaScript
intrinsic objects. Here I added a weight property that returns the sum of the
char codes of a string:
String.prototype.__defineGetter__("weight",
function () {
var w = 0;
for (var n = 0; n < this.length; n++)
w += this.charCodeAt(n);
return w;
}
);
You can use this property on any string:
var s = "ABC";
var n = s.weight; // will return 198
Remember:
The __defineGetter__ and __defineSetter__ are unique features to
Mozilla/FireFox and you can find some (still few) samples on the internet by
searching through Google for these keywords.

Prototypes with HTML objects
JavaScript objects and HTML objects are completely different kinds of
objects when using the Microsoft Internet Explorer but with Mozilla/FireFox,
these objects share a common implementation. So, the feature we look at now
is only available in Mozilla/FireFox.
The Internet Explorer, for example, supports a innerText property on many
HTML objects like span, div, p, ... that can be used to safely access and set
the text of an HTML object.
Mozilla/Firefox, in contrary, uses the textContent property that is part of the
newer DOM Level 3 standard to do the same thing.
Now you can use the extensibility features of Mozilla/FireFox to emulate an
innerText property on all HTML objects and you can eliminate all conditional
scripting across your JavaScript programs:
var isIE = (window.navigator.userAgent.indexOf("MSIE") > 0);
if (! isIE) {
HTMLElement.prototype.__defineGetter__("innerText",
function () { return(this.textContent); });
HTMLElement.prototype.__defineSetter__("innerText",
function (txt) { this.textContent = txt; });
}
You just have to include this script in one of your common JavaScript include
files.
The ~/controls/jcl.js file implements some usable wrappers to Microsoft
specific features and makes them available in Firefox too:
innerText Gets and Sets the inner text of HTML nodes.
XMLDocument Returns a XMLDocument object from the inner text
that should be XML.
jcl.AttachEvent Attach event handlers to HTML objects.
jcl.DetachEvent Detach event handlers from HTML objects.
window.event Return the actual executing event object.
event.srcElement Return the target node of the executing event.
event.cancelBubble Stop the propagation of the current event.
event.returnValue Set the return value of the current event.
xmlobj.selectSingleNode Return a single node from an XML element by using
an XPath expression.
xmlobj.text Return the inner text of an XML element.

Firefox compatibility
When implementing JavaScript that’s working with both browsers (IE and
Firefox) you take care of the compatibility issues.
I fixed some minor things:
The parentElement attribute of the HTML DOM should not be used. Use
parentNode instead.
The firstChild attribute might get a text node in Firefox that is skipped or
not existing in IE. Whitespace should not be used between a parent node
and the fist child node.
The onscroll event it is not documented but works as expected in Firefox.
Great !
Don’t forget to test!

Conclusion
If you ever thought that writing cross browser compatible JavaScript is hard to
do, you now have a chance to build your layer of compatibility and make your
script more readable and easier to maintain, and get rid of the conditional code
fragments spread all over your web application.
This approach helps a lot but is not the definitive solution. A lot of people
(including myself) hope that the current and upcoming standards will get
implemented in all browsers. It's better to use these features, when available
on multiple platforms. There are also good samples of proprietary Microsoft
Internet Explorer features that are so useful that Mozilla/Firefox did
implement them. The most popular sample to this is the XMLHttpRequest
object that allows AJAX like cross browser implementations.

Post a Comment

You're welcome to share your ideas with us in comments.

Previous Post Next Post