Cross-browser Issues

Cross-Browser Issues

When discussing cross-browser issues, the discussion is limited to the two main browsers in use: Netscape Navigator and Microsoft Internet Explorer (IE).  The discussion is specifically aimed at version 4 of Netscape and version 4 and 5 of IE.  

Hundreds of pages could be filled trying to describe all the differences between the browsers and the implications for coders.  This page tries to describe a number of the important issues that a JavaScript developer and Webpage designer will face.

  1. Introduction
  2. Determining the Browser in JavaScript
  3. HTML Page/Tag Differences
  4. Variable Comparison Difference
  5. Specifying a File Location
  6. Changing Form Visibility/Position
  7. Dynamically Loading Selection Lists
  8. Dealing with Applets
  9. Using Images
  10. Skipping non-editable columns
  11. Setting Focus to the first webpage column
  12. Layers
  13. Application Testing

     Final Note regarding Netscape 6 Browser

1. Introduction

Netscape had a browser and a dominant market position before Microsoft entered the market.  Even when IE 3 was released, it was one version of JavaScript behind Netscape (opinions vary but many feel that IE4 and certainly IE5 have let IE surpass Netscape).  The point is when Microsoft released their browser and their scripting language JScript, they had little choice but to imitate the market-leading Navigater and its JavaScript scripting language. In places, JavaScript will refers to object and attributes named "Navigator" -- IE generally supports this naming (although I am sure that Microsoft resented having to use the competitor's product name).

Broadly speaking (with some notable exceptions like Layers), IE supports the Navigator syntax where the reverse is frequently not true.  For this reason, it is widely recommended that cross-browser code be developed to work on Navigator first and then tested on IE (this approach will generally prove far less frustrating than trying to get IE-ready code to work in Navigator).

Given the challenges that cross-browser compatibility causes, a fair question is: should I bother with cross-browser compatibility?  In the case of Intranet development, there is a strong argument for picking a corporate browser and developing for that browser.  If the corporate standard is to use IE4 or higher, it will be available on all desktops so it is not a large imposition on users to insist that that browser when accessing the Intranet. 

In the case of business-to-consumer (B2C) style web applications, cross-browser compatibility will generally be necessary.  Customers resent being told which product to use and they may not have disk space to load a second browser on their hard drive.  Also, certain ISPs support only one browser.  If your browser choice conflict with the ISP, you have put your customer in a difficult situation.

In business-to-business (B2B) web application, you may be able to insist that a particular browser be selected.  It will depend on your relationship with the counter-parties, standards in that industry and the number of counter-parties involved.

The rest of the document assumes that you do have to support Netscape 4 and IE 4+ and helps address a number of issues that will arise. A final note about Netscape 6 is made at the end.

2. Determining the Browser in JavaScript

The following code will determine the browser (IE vs. Navigator). 

var agt = navigator.userAgent.toLowerCase();
var isNav = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
         && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
         && (agt.indexOf('webtv')==-1));
var isIE = (agt.indexOf("msie") != -1);

If your application is only going to support IE and Navigator, then the logon page should check for isIE / isNav and disallow logon if both are false.

The remaining code below assumes that the page-level variables "isNav" and "isIE" have been computed.

3. HTML Page/Tag Differences

IE tries to be more forgiving about webpage tag definitions.  For example you can define form elements without specifing the <FORM> </FORM> tags in IE and access those elements in your JavaScript.  In Navigator, form elements will be invisible and inaccessible if not inside form tags.

Similarly, in IE you can overlap tags in various orders, such as:

<tag-a><tag-b><tag-c> some text </tag-b></tag-a></tag-c>

and the IE browser will generally make sense of the overlap.

Netscape, on the other hand can have difficulty with the above sequence of tags (causing some tags to be ignored or for the effect of the tag to continue beyond its end-tag marker).  Netscape works best when you end overlapping tags in the reverse order that they began.  For the above example, this means changing the tag order to:

<tag-a><tag-b><tag-c> some text </tag-c></tag-b></tag-a>

4. Variable Comparison Difference

In IE, you can compare a string value to a numeric value and IE will convert to a common data type before comparing.  For example, the string "5" equals the number 5 in IE.  Navigator will treat the two values as unequal if the data types are different.  What this means is that you should ensure you are dealing with a common data type (like a string) before comparison two variables to ensure Navigator compatibility.

var numVal = 5;
var strVal = "5";
// concatenating an empty string converts the number to string
if ((numVal + "")  == strVal) {
  ... do something

5. Specifying a File Location

When referring to any file within a directory structure (e.g. an image of a separate JavaScript file), you must you use http notation for Navigator (e.g. file:///C|/html/the_script.js).  You cannot specify Windows notation in Navigator (e.g. c:\html\the_script.js) where IE supports either notation.

6. Changing Form Visibility/Position

Both IE and Navigator let you control visibility and position but Navigator imposes a number of conditions that do not apply to IE:

As you can see, Navigator is considerably more restrictive than IE in controlling visibility and placement.  It is possible but you had better design your form with Navigator's "whole form" restriction in mind if you want full cross-browser compatibility.

Just to make things interesting, the two browsers use different syntax to refer to form element properties and to move them.   If you use the following general purpose routines, the syntax differences will be hidden from your code.

The first function accounts for the fact that the IE syntax requires an "all." and "style"

var range = ""
var styleObj = ""

// convert object ref to valid object ref for browser
function getObject(obj) {
  var theObj

  // set the longer IE syntax elements
  if (isIE) {
    range = "all."
    styleObj = ".style"
  }

  // if it is a string, use the browser specific syntax
  if (typeof obj == "string") {
    theObj = eval("document." + range + obj + styleObj)
  } else {
     theObj = obj
  }
  return theObj
}

The second function accounts for the fact the the "move" syntax is different between the browsers:

// convert object ref to valid object ref for browser
function shiftTo(obj, x, y) {
var theObj = getObject(obj)// call function above

  // use browser-specific syntax to move
  if (isNav) {
    theObj.moveTo(x, y)
  } else {
    theObj.pixelLeft = x
    theObj.pixelTop = y
  }
}

Sample code which changes the visibility of the DIV block (requires first function only)

obj = getObject("DForm1"); // DForm1 is DIV block surrounding form
obj.visibility = 'hidden'; 

The next sample code uses calls the second sample functions to move the DIV block:

shiftTo('DForm1', 100, 200);

7. Dynamically Loading Selection Lists

7.1 Challenges in Navigator

After dynamically loading or changing the entries in a selection list (or dropdown box) in Navigator, you must tell the screen to refresh so that the box is resized to reflect the new set of elements (both in terms of the number of elements and the width of the widest element).  This is done by calling the function:

if isNav() {
  history.go(0)
}

This action basically tells the webpage to refresh and reflect the latest size.   Unfortunately, this action has the side-effect of causing all page-level variables to be re-initialized and for all form-load logic to re-execute.  One way to not re-initialize important variables is to include a hidden form on the webpage and make sure that important values that must be retained are saved on this hidden form before calling history.go(0).  The technique is cumbersome but Navigator 4 offers little choice.

7.2 Challenges in IE

IE automatically resizes selection lists as each element is added or removed from the selection list.  This saves the additional effort required by Navigator described above.  There is, however, a side-effect of this instant repainting by IE.  If you have a very large number of elements (e.g. > 300) to dynamically add or remove from a selection list, the performance time for adding or removing the elements can be very slow.  As a rule, you would want to try to avoid building a screen that requires so many entries in a selection list.  Sometimes, however, very long selection lists will be appropriate (or unavoidable) for the application.

The solution is to use an IE-only property called outerHTML.  OuterHTML lets you get the entire text for a tag and then change it in one fell swoop (and so save the element-by-element painting time problem).  The series of functions below demonstrate the changing of outerHTML to load a large number of elements.

var pt = document.form1.persTitle;
var option_texts = new Array();
var option_values = new Array();

// populate the page-level array variables with some dummy options ...
function defineLists() {
   for (i=0; i<500;i++) {
      option_texts[i] = "Element Number" + i;
      option_values[i] = i;
   }
}
function changeSelectionHTML() {
  var optHTML;
  var startSelTag;
  var closeSelTag;
  var theOptions = "";

  optHTML = document.form1.persTitle.outerHTML; // get existing HTML for element

  // parse the selection start and end tag out of the entire Select HTML
  startSelTag = getOpenTag(optHTML);
  closeSelTag = getCloseTag(optHTML);

  for (i=0; i<option_texts.length;i++) {
    theOptions += '<option value=' + option_values[i] + '>' + option_texts[i];
  }
  // now reset the selection list filling in all options at once
  document.form1.persTitle.outerHTML = startSelTag + theOptions + closeSelTag;

  // after changing OuterHTML, variables pointing to object must be "refreshed".
  pt = document.form1.persTitle;
}
function getOpenTag(elHTML) {
  var closePos;
  var openTag;

  // find last position of opening tag
  closePos = elHTML.indexOf(">");
  if (closePos > 1) {
    openTag = elHTML.substring(0,closePos+1);
  } else {
    window.alert("System Error: unable to find Selection Open Tag");
  }
  return openTag;
}

function getCloseTag(elHTML) {
  var openPos;
  var closeTag;

  // find first position of closing tag
  openPos = elHTML.lastIndexOf("<");
  if (openPos > 0) {
    closeTag = elHTML.substring(openPos, elHTML.length);
  } else {
    window.alert("System Error: unable to find Selection Close Tag");
  }
  return closeTag;
}

8. Defining Applets

Navigator 4 insists that the applet class be public before it will display it.  IE will display a class with default access defined.

9. Using Images

Both browsers support GIF and JPEG files but only IE supports the Windows BMP file format.  BMPs can easily be converted to GIF (and GIFs are more compact) so avoid BMP file formats.

10. Skipping non-Editable Columns

IE provides a simple mechanism for defining the order of tabpage through webpage elements (and particularly provides the ability to skip non-editable elements).  IE supports the tabindex property for form elements.  Netscape 4 unfortunately does not support the tabindex and therefore requires a manual workaround to skip columns.

In the onFocus event of the non-editable column, you can add code to change focus to the desired column (e.g. the next editable column).

11. Setting Focus to the first Webpage Element

When there is dynamic content in the body of the webpage (i.e. content generated by JavaScript using document.write()), Netscape seems to ignore instructions to set focus to the first element as instructed in the Body's onLoad statement. The workaround is to add a delay for Netscape before calling initPage() from onLoad logic (the initPage function sets focus to the first editable column):

<body onLoad="isIE ? initPage() : setTimeout('initPage()', 50)">

12. Layers

Navigator 4 introduces the concept of "Layers".  Multiple layers can defined and superimposed on top of one other. Since the Layer definition was not incorporated into the industry ECMAScript (i.e. IE does not and will not support it), Layers should be avoided wherever possible for cross-browser compatibility.  In certain cases, you will inadvertently create a layer as described earlier in this page. When the layer is unavoidable, just use the longer Navigator-specific syntax, within the appropriate "if (isNav)" statement.

Navigator 6 no longer supports layes (but rather support comparable syntax to IE for most objects).  As such, using layers is even less desirable.

13. Application Testing

As much as you try to plan for cross-browser compatibility in design and coding, there are likely to be unexpected surprises.  The earlier that you do thorough unit testing with both browsers, the sooner you will identify issues that might affect your design.

Also, thorough system testing with both browsers (generally multiple browser versions) is crucial.  An application that fails due to browser problems gives a very unprofessional image.  Most customers will simply assume your application is broken and will give up.  Only the most technically oriented people will think to try again with a different browser.

Final Note: Netscape 6

Almost every noted Netscape 4 "weakness" appears to have been addressed in Netscape 6 (and Netscape 6 is now compatible with IE 4/5).  However, many sites continue (in 2003 and 2004 to still support Netscape 4 so the Netscape 4 issues still need to be continued.

... back to Development Tools Page

[Home][What's New][Development Tools][Services][Contents][Feedback]

Copyright 1997-2004, Woodger Computing Inc.
Last modified: January 01, 2004