Custom Search
|
Change Language |
Migrate apps from Internet Explorer to MozillaFrom MDC
IntroductionWhen Netscape started the Mozilla browser, it made the conscious
decision to support W3C standards. As a result, Mozilla is not fully
backwards-compatible with Netscape Navigator 4.x and Microsoft Internet
Explorer legacy code; for example, Mozilla does not support I'll also cover nonstandard technologies, such as XMLHttpRequest and rich text editing, that Mozilla does support because no W3C equivalent existed at the time. They include:
General cross-browser coding tipsEven though Web standards do exist, different browsers behave differently (in fact, the same browser may behave differently depending on the platform). Many browsers, such as Internet Explorer, also support pre-W3C APIs and have never added extensive support for the W3C-compliant ones. Before I go into the differences between Mozilla and Internet Explorer, I'll cover some basic ways you can make a Web application extensible in order to add new browser support later. Since different browsers sometimes use different APIs for the same
functionality, you can often find multiple . . . var elm; if (ns4) elm = document.layers["myID"]; else if (ie4) elm = document.all["myID"] The above code isn't extensible, so if you want it to support a new browser, you must update these blocks throughout the Web application. The easiest way to eliminate the need to recode for a new browser is to
abstract out functionality. Rather than multiple var elm = getElmById("myID"); function getElmById(aID){ var element = null; if (isMozilla || isIE5) element = document.getElementById(aID); else if (isNetscape4) element = document.layers[aID]; else if (isIE4) element = document.all[aID]; return element; } The above code still has the issue of browser sniffing, or detecting which browser the user is using. Browser sniffing is usually done through the useragent, such as: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031016 While using the useragent to sniff the browser provides detailed information on the browser in use, code that handles useragents often can make mistakes when new browser versions arrive, thus requiring code changes. If the type of browser doesn't matter (suppose that you have already blocked nonsupported browsers from accessing the Web application), it is much better and more reliable to sniff by browser capability or object feature support. You can usually do this by testing the required functionality in JavaScript. For example, rather than: if (isMozilla || isIE5) You would use: if (document.getElementById) This would allow other browsers that support that W3C standard method, such as Opera or Safari, to work without any changes. Useragent sniffing, however, makes sense when accuracy is important, such as when you're verifying that a browser meets the Web application's version requirements or you are trying to work around a bug. JavaScript also allows inline conditional statements, which can help with code readability: var foo = (condition) ? conditionIsTrue : conditionIsFalse; For example, to retrieve an element, you would use: function getElement(aID){ return (document.getElementById) ? document.getElementById(aID) : document.all[aID]); } Or another way is to use the || operator: function getElement(aID){ return (document.getElementById(aID)) || document.all[aID]); } Differences between Mozilla and Internet ExplorerFirst, I'll discuss the differences in the way HTML behaves between Mozilla and Internet Explorer. TooltipsLegacy browsers introduced tooltips into HTML by showing them on links and using the value of the EntitiesHTML markup can contain several entities, which the W3C web standards body has defined. You can reference entities through their numerical or
character reference. For example, you can reference the white space
character #160 with Some older browsers, such as Internet Explorer, had such quirks as allowing you to use entities by replacing the   Foo    Foo Mozilla will render the above  12345 This code does not work in Mozilla, since it goes against the W3C web standards. Always use the correct form ( DOM differencesThe Document Object Model (DOM) is the tree structure that contains the document elements. You can manipulate it through JavaScript APIs, which the W3C has standardized. However, prior to W3C standardization, Netscape 4 and Internet Explorer 4 implemented the APIs similarly. Mozilla only implements legacy APIs if they are unachievable with W3C web standards. Accessing elementsTo retrieve an element reference using the cross-browser approach, you use Mozilla does not support accessing an element through The W3C DOM Level 1 method gets references to all elements with the same tag name through The DOM Level 1 methods, as shown in Table 1, are commonly used
to move an element to a certain position and toggle its visibility
(menus, animations). Netscape 4 used the
Traverse the DOMMozilla supports the W3C DOM APIs for traversing the DOM tree through
JavaScript (see Table 2). The APIs exist for each node in the document and
allow walking the tree in any direction. Internet Explorer supports these
APIs as well, but it also supports its legacy APIs for walking a DOM tree,
such as the
Internet Explorer has a nonstandard quirk, where many of these APIs
will skip white space text nodes that are generated, for example, by
new line characters. Mozilla will not skip these, so sometimes you need
to distinguish these nodes. Every node has a HTML: <div id="foo"> <span>Test</span> </div> JavaScript: var myDiv = document.getElementById("foo"); var myChildren = myXMLDoc.childNodes; for (var i = 0; i < myChildren.length; i++) { if (myChildren[i].nodeType == 1){ // element node }; }; Generate and manipulate contentMozilla supports the legacy methods for adding content into the DOM dynamically, such as Internet Explorer has several content manipulation methods that
are nonstandard and unsupported in Mozilla, including retrieving the
value, inserting text and inserting elements adjacent to a node, such
as
Document fragmentsFor performance reasons, you can create documents in memory, rather
than working on the existing document's DOM. DOM Level 1 Core
introduced document fragments, which are lightweight documents that
contain a subset of a normal document's interfaces. For example, Mozilla creates document fragments through Internet Explorer's implementation of document fragments, however, does not comply with the W3C web standards and simply returns a regular document. JavaScript differencesMost differences between Mozilla and Internet Explorer are usually blamed on JavaScript. However, the issues usually lie in the APIs that a browser exposes to JavaScript, such as the DOM hooks. The two browsers possess few core JavaScript differences; issues encountered are often timing related. JavaScript date differencesThe only JavaScript execution differencesDifferent browsers execute JavaScript differently. For example, the
following code assumes that the ... <div id="foo">Loading...</div> <script> document.getElementById("foo").innerHTML = "Done."; </script> However, this is not guaranteed. To be sure that all elements exist,
you should use the <body onload="doFinish();"> <div id="foo">Loading...</div> <script> function doFinish() { var element = document.getElementById("foo"); element.innerHTML = "Done."; } </script> ... Such timing-related issues are also hardware-related -- slower systems
can reveal bugs that faster systems hide. One concrete example is <script> function doOpenWindow(){ var myWindow = window.open("about:blank"); myWindow.location.href = "http://www.ibm.com"; } </script> The problem with the code is that Differences in JavaScript-generating HTMLJavaScript can, through <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ... <script> document.write("<script type='text/javascript'>alert('Hello');</script>") </script> Since the page is in strict mode, Mozilla's parser will see the first <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ... <script> document.write("<script type='text\/javascript'>alert('Hello');</" + "script>") </script> Debug JavaScriptMozilla provides several ways to debug JavaScript-related issues found in applications created for Internet Explorer. The first tool is the built-in JavaScript console, shown in Figure 1, where errors and warnings are logged. You can access it in Mozilla by going to Tools -> Web Development -> JavaScript Console or in Firefox (the standalone browser product from Mozilla) at Tools -> JavaScript Console. Figure 1. JavaScript console
The JavaScript console can show the full log list or just errors, warnings, and messages. The error message in Figure 1 says that at aol.com, line 95 tries to access an undefined variable called is_ns70. Clicking on the link will open Mozilla's internal view source window with the offending line highlighted. The console also allows you to evaluate JavaScript. To evaluate the entered JavaScript syntax, type in Figure 2. JavaScript console evaluating
Mozilla's JavaScript engine has built-in support for debugging, and thus can provide powerful tools for JavaScript developers. Venkman, shown in Figure 3, is a powerful, cross-platform JavaScript debugger that integrates with Mozilla. It is usually bundled with Mozilla releases; you can find it at Tools -> Web Development -> JavaScript Debugger. For Firefox, the debugger isn't bundled; instead, you can download and install it from the Venkman Project Page. You can also find tutorials at the development page, located at the Venkman Development Page. Figure 3. Mozilla's JavaScript debugger
The JavaScript debugger can debug JavaScript running in the Mozilla browser window. It supports such standard debugging features as breakpoint management, call stack inspection, and variable/object inspection. All features are accessible through the user interface or through the debugger's interactive console. With the console, you can execute arbitrary JavaScript in the same scope as the JavaScript currently being debugged. CSS differencesMozilla-based products have the strongest support for Cascading Style Sheets (CSS), including most of CSS1, CSS2.1 and parts of CSS3, compared to Internet Explorer as well as all other browsers. For most issues mentioned below, Mozilla will add an error or warning entry into the JavaScript console. Check the JavaScript console if you encounter CSS-related issues. Mimetypes (when CSS files are not applied)The most common CSS-related issue is that CSS definitions inside
referenced CSS files are not applied. This is usually due to the server
sending the wrong mimetype for the CSS file. The CSS specification states
that CSS files should be served with the CSS and unitsMany Web applications do not use units with their CSS, especially when you use JavaScript to set the CSS. Mozilla tolerates this, as long as the page is not rendered in strict mode. Since Internet Explorer does not support true XHTML, it does not care if no units are specified. If the page is in strict standards mode, and no units are used, then Mozilla ignores the style: <DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>CSS and units example</title>
</head>
<body>
// works in strict mode
<div style="width: 40px; border: 1px solid black;">
Text
</div>
// will fail in strict mode
<div style="width: 40; border: 1px solid black;">
Text
</div>
</body>
</html>
Since the above example has a strict doctype, the page is rendered in strict standards mode. The first div will have a width of 40px, since it uses units, but the second div won't get a width, and thus will default to 100% width. The same would apply if the width were set through JavaScript. JavaScript and CSSSince Mozilla supports the CSS standards, it also supports the CSS DOM
standard for setting CSS through JavaScript. You can access, remove, and
change an element's CSS rules through the element's <div id="myDiv" style="border: 1px solid black;"> Text </div> <script> var myElm = document.getElementById("myDiv"); myElm.style.width = "40px"; </script> You can reach every CSS attribute that way. Again, if the Web page
is in strict mode, you must set a unit or else Mozilla will ignore the
command. When you query a value, say through CSS overflow differencesCSS added the notion of overflow, which allows you to define how to
handle overflow; for example, when the contents of a <div style="height: 100px; border: 1px solid black;"> <div style="height: 150px; border: 1px solid red; margin: 10px;"> a </div> </div> As you can see in Figure 4, Mozilla acts like the W3C standard specifies.
The W3C standard says that, in this case, the inner Figure 4. DIV overflow
hover differencesThe nonstandard CSS hover behavior in Internet Explorer occurs on quite
a few web sites. It usually manifests itself by changing text style
when hovered over in Mozilla, but not in Internet Explorer. This is because the CSS: a:hover {color: green;} HTML: <a href="foo.com">This text should turn green when you hover over it.</a> <a name="anchor-name"> This text should change color when hovered over, but doesn't in Internet Explorer. </a> Mozilla follows the CSS specification correctly and will change the color to green in this example. You can use two ways to make Mozilla behave like Internet Explorer and not change the color of the text when hovered over:
Quirks versus standards modeOlder legacy browsers, such as Internet Explorer 4, rendered with so-called quirks under certain conditions. While Mozilla aims to be a standards-compliant browser, it has three modes that support older Web pages created with these quirky behaviors. The page's content and delivery determine which mode Mozilla will use. Mozilla will indicate the rendering mode in View -> Page Info (or Ctrl+I) ; Firefox will list the rendering mode in Tools -> Page Info. The mode in which a page is located depends on its doctype. Doctypes (short for document type declarations) look like this:
The section in blue is called the public identifier, the green part is the system identifier, which is a URI. Standards modeStandards mode is the strictest rendering mode -- it will render pages per the W3C HTML and CSS specifications and will not support any quirks. Mozilla uses it for the following conditions:
Almost standards modeMozilla introduced almost standards mode for one reason: a section in the CSS 2 specification breaks designs based on a precise layout of small images in table cells. Instead of forming one image to the user, each small image ends up with a gap next to it. The old IBM homepage shown in Figure 5 offers an example. Figure 5. Image gap
Almost standards mode behaves almost exactly as standards mode, except when it comes to an image gap issue. The issue occurs often on standards-compliant pages and causes them to display incorrectly. Mozilla uses almost standards mode for the following conditions:
You can read more about the image gap issue. Quirks modeCurrently, the Web is full of invalid HTML markup, as well as markup that only functions due to bugs in browsers. The old Netscape browsers, when they were the market leaders, had bugs. When Internet Explorer arrived, it mimicked those bugs in order to work with the content at that time. As newer browsers came to market, most of these original bugs, usually called quirks, were kept for backwards compatibility. Mozilla supports many of these in its quirks rendering mode. Note that due to these quirks, pages will render slower than if they were fully standards-compliant. Most Web pages are rendered under this mode. Mozilla uses quirks mode for the following conditions:
For further reading, check out: Mozilla Quirks Mode Behavior and Mozilla's DOCTYPE sniffing. Event differencesMozilla and Internet Explorer are almost completely different in the
area of events. The Mozilla event model follows the W3C and Netscape
model. In Internet Explorer, if a function is called from an event, it
can access the A cross-browser event handling example follows (note that it means you can't define a global variable named <div onclick="handleEvent(event);">Click me!</div> <script> function handleEvent(aEvent) { var myEvent = window.event ? window.event : aEvent; } </script> The properties and functions that the event object exposes are also often named differently in Mozilla and Internet Explorer, as Table 4 shows.
Attach event handlersMozilla supports two ways to attach events through JavaScript. The first,
supported by all browsers, sets event properties directly on objects. To
set a <div id="myDiv">Click me!</div> <script> function handleEvent(aEvent) { // if aEvent is null, means the Internet Explorer event model, // so get window.event. var myEvent = aEvent ? aEvent : window.event; } function onPageLoad(){ document.getElementById("myDiv").onclick = handleEvent; } </script> Mozilla fully supports the W3C standard way of attaching listeners to
DOM nodes. You use the <div id="myDiv">Click me!</div> <script> function handleEvent(aEvent) { // if aEvent is null, it is the Internet Explorer event model, // so get window.event. var myEvent = aEvent ? aEvent : window.event; } function onPageLoad() { var element = document.getElementById("myDiv"); element.addEventListener("click", handleEvent, false); } </script> One advantage of Mozilla does not support Internet Explorer's method of
converting <script> tags into event handlers, which extends
<script> with
Rich text differencesMozilla supports the W3C standard of accessing iframe's document object
through <script> function getIFrameDocument(aID) { var rv = null; // if contentDocument exists, W3C compliant (Mozilla) if (document.getElementById(aID).contentDocument){ rv = document.getElementById(aID).contentDocument; } else { // IE rv = document.frames[aID].document; } return rv; } </script> Another difference between Mozilla and Internet Explorer is the HTML
that the rich text editor creates. Mozilla defaults to using CSS for the
generated markup. However, Mozilla allows you to toggle between HTML and
CSS mode using the Mozilla (CSS): <span style="color: blue;">Big Blue</span> Mozilla (HTML): <font color="blue">Big Blue</font> Internet Explorer: <FONT color="blue">Big Blue</FONT> Below is a list of commands that execCommand in Mozilla supports:
XML differencesMozilla has strong support for XML and XML-related technologies, such as XSLT and Web services. It also supports some non-standard Internet Explorer extensions, such as How to handle XMLAs with standard HTML, Mozilla supports the W3C XML DOM
specification, which allows you to manipulate almost any aspect of an
XML document. Differences between Internet Explorer's XML DOM and
Mozilla are usually caused by Internet Explorer's nonstandard
behaviors. Probably the most common difference is how they handle white
space text nodes. Often when XML generates, it contains white spaces
between XML nodes. Internet Explorer, when using XML: <?xml version="1.0"?> <myXMLdoc xmlns:myns="http://myfoo.com"> <myns:foo>bar</myns:foo> </myXMLdoc> JavaScript: var myXMLDoc = getXMLDocument().documentElement; alert(myXMLDoc.childNodes.length); The first line of JavaScript loads the XML document and accesses the root element ( As mentioned earlier, every node has a XML: <?xml version="1.0"?> <myXMLdoc xmlns:myns="http://myfoo.com"> <myns:foo>bar</myns:foo> </myXMLdoc> JavaScript: var myXMLDoc = getXMLDocument().documentElement; var myChildren = myXMLDoc.childNodes; for (var run = 0; run < myChildren.length; run++){ if ( (myChildren[run].nodeType != 3) && myChildren[run].nodeType != 8) ){ // not a text or comment node }; }; See Whitespace in the DOM for more detailed discussion and a possible solution. XMLHttpRequestInternet Explorer allows you to send and retrieve XML files using MSXML's After instantiating the object using Synchronous request: var myXMLHTTPRequest = new XMLHttpRequest(); myXMLHTTPRequest.open("GET", "data.xml", false); myXMLHTTPRequest.send(null); var myXMLDocument = myXMLHTTPRequest.responseXML; Asynchronous request: var myXMLHTTPRequest; function xmlLoaded() { var myXMLDocument = myXMLHTTPRequest.responseXML; } function loadXML(){ myXMLHTTPRequest = new XMLHttpRequest(); myXMLHTTPRequest.open("GET", "data.xml", true); myXMLHTTPRequest.onload = xmlLoaded; myXMLHTTPRequest.send(null); } Table 7 features a list of available methods and properties for Mozilla's
XSLT differencesMozilla supports XSL Transformations (XSLT) 1.0. It also allows JavaScript to perform XSLT transformations and allows running XPath on a document. Mozilla requires that you send the XML and XSLT files with an XML mimetype ( Internet Explorer 5.0 and 5.5 supported XSLT's working draft,
which is substantially different than the final 1.0 recommendation. The
easiest way to distinguish what version an XSLT file was written
against is to look at the namespace. The namespace for the 1.0
recommendation is If XSLT requires you to distinguish the browser, you can query the "xsl:vendor" system property. Mozilla's XSLT engine will report itself as "Transformiix" and Internet Explorer will return "Microsoft". <xsl:if test="system-property('xsl:vendor') = 'Transformiix'"> <!-- Mozilla specific markup --> </xsl:if> <xsl:if test="system-property('xsl:vendor') = 'Microsoft'"> <!-- Internet Explorer specific markup --> </xsl:if> Mozilla also provides JavaScript interfaces for XSLT, allowing a Web
site to complete XSLT transformations in memory. You can do this using
the global
var xslStylesheet; var xsltProcessor = new XSLTProcessor(); // load the xslt file, example1.xsl var myXMLHTTPRequest = new XMLHttpRequest(); myXMLHTTPRequest.open("GET", "example1.xsl", false); myXMLHTTPRequest.send(null); // get the XML document and import it xslStylesheet = myXMLHTTPRequest.responseXML; xsltProcessor.importStylesheet(xslStylesheet); // load the xml file, example1.xml myXMLHTTPRequest = new XMLHttpRequest(); myXMLHTTPRequest.open("GET", "example1.xml", false); myXMLHTTPRequest.send(null); var xmlSource = myXMLHTTPRequest.responseXML; var resultDocument = xsltProcessor.transformToDocument(xmlSource); After creating an
Original Document Information
|