Multi-Browser Support

 

Microsoft Corporation
October 2003

Applies to
    Microsoft® ASP.NET
    Microsoft® Internet Explorer
    JavaScript

Summary: Learn about JavaScript forking for multi-browser support, and how ASP.NET takes care of multi-browser support for you. (8 printed pages)

Contents

Introduction
Browser Detection Using Navigator Object Properties
JavaScript Forking
Forking on the CodeNotes Web Site
JLCA Conversion
Leveraging ASP.NET
Web Controls
UpLevel and DownLevel Browsers
Extending Web Controls (Custom Web Control Creation)
Summary

Introduction

Multi-browser support is a recurrent and persistent problem for Web developers. As standards change and new browser versions are released (sometimes offering new features without backward compatibility), Web developers' jobs become more difficult. Not only must they provide increased functionality in their Web applications, but they must also ensure that those applications are accessible to the largest possible audience.

The JavaScript solution to multi-browser support is a two-step process. First, you write code to detect which browser the user is using. Second, based on that information you write code to handle the particular browser. Using this JavaScript solution, you can support different browsers (for example, Microsoft® Internet Explorer, Netscape®, and so on) and also browser versions (for example, Internet Explorer 4+, Internet Explorer 5.5, and so on).

In order to provide the same functionality to different browsers and browser versions, JavaScript developers use a technique called code forking. The following sections illustrate how you can detect which browser a user is accessing your page with, and provide an example of JavaScript forking.

Browser Detection Using Navigator Object Properties

The navigator object is contained within the top-level window object in a JavaScript document. To determine a user's browser type and version, you can use the navigator object with its properties (appName, appCodeName, appVersion, and userAgent). These properties may be used in your conditional statements (as illustrated in the next section) to make your code browser-specific.

Listing 1 illustrates several navigator properties. Loading this example in different Internet Explorer versions, or Netscape versions, will generate different results.

Listing 1. Navigator property browser detection

<html>
   <script language="javascript">

   // Returns the browser application name 
   // for example, "Microsoft Internet Explorer" or "Netscape"
   document.write(window.navigator.appName);

   // Returns the internal code name of the browser
   // for example, "Mozilla"
   document.write(window.navigator.appCodeName);

   // Returns the version of the browser as a string
   document.write(window.navigator.appVersion);

   // Returns the user agent string for the browser
   document.write(window.navigator.userAgent);

   </script>
</html>

The easiest property to use is appName. Simply use this property to check for either Netscape or Microsoft Internet Explorer and fork your code appropriately. The other properties need to be parsed to retrieve useful information.

For example, appVersion in Internet Explorer 6.0 returns the text 4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705). At first sight, this text does not clearly represent the specific browser version. Yet, the version number can be extracted using the built-in JavaScript function indexOf. Using this function with appVersion, you can search for the text 6.0, or 5.5, to distinguish among different Internet Explorer versions, as illustrated in Listing 2. If indexOf does not find a character match, it will return a value of -1.

Listing 2. Using appVersion with indexOf

<html>
   <script language="javascript">
   // Fork for IE 5.5
   if(window.navigator.appVersion.indexOf("IE 5.5")!= -1) {
      document.write("Internet Explorer 5.5") }
   // Fork for IE 6.0
   if(window.navigator.appVersion.indexOf("IE 6.0")!= -1) {
      document.write("Internet Explorer 6.0") }
   </script>
</html>

JavaScript Forking

Once you determine what browser the user is using, you can write a JavaScript fork. (This process is sometimes also referred to as JavaScript branching). As a basic example, the Web page in Listing 3 contains a simple table with a highlight function. When a user runs the mouse pointer over the table cells, the cell backgrounds change from white to yellow. The highlighted code illustrates the fork required for this to work in both Internet Explorer browsers and Netscape browsers (specifically Netscape 6+ browsers).

Listing 3. JavaScript forking example

<html>
   <style>
      td { text-align: center; }
   </style>
   <script language="javascript">
   function highlight(e,b) {
      var src;
      // Fork for Netscape event handling
      if (navigator.appName == "Netscape")
         src = e.target;
      else
         src = e.srcElement;
      if (src.tagName == "TD") {
         if(b==true) // mouseOver, and highlight {
            src.originColor=src.style.backgroundColor;
            src.style.backgroundColor="yellow";
         } else // mouseOut, restore original color
            src.style.backgroundColor=src.originColor;
      }
   }
</script>
<body>
   <table id="table1" width="20%" border="1"
      onmouseover="highlight(event,true)"
      onmouseout="highlight(event,false)">
      <tr><th>Simple Table</th></tr>
      <tr><td>Cell 1</td></tr>
      <tr><td>Cell 2</td></tr>
      <tr><td>Cell 3</td></tr>
      <tr><td>Cell 4</td></tr>
   </table>
</body>
</html>

In the previous example, the appName property of the navigator object is used. If the property returns the value "Netscape", then the src variable is set to "e.target" (Netscape's way of handling the action event). If the property returns something other than Netscape, src is set to "e.srcElement" (Microsoft's way of handling the action event). This code fork allows the remaining code, specifically onmouseover and onmouseout, to work properly, regardless of the user's browser (be it Netscape 6 or any version of Internet Explorer).

Forking on the CodeNotes Web Site

Several examples of JavaScript forking can be found in the source code for the CodeNotes Web site. For example, Listing 4 shows a script that appears in content_codeMain.jsp, which displays the main content for the Code Gallery section of the CodeNotes Web site.

Listing 4. Forking in contentCodeMain.jsp

<script language=javascript>
function menuAction(e, objID) {
   var src;
   var obj;
   // Fork for Netscape event handling
   if (navigator.appName == "Netscape")
      src = e.target;
   else 
      src = e.srcElement;
   //Showing and hiding branches only applies to headers. We can
   //simply check the CSS style to see if we have a "header"
   if (src.className == "header") {
      obj = document.getElementById(objID);
      if (obj.style.display=="none") { 
         e.cancelBubble = true;
         obj.style.display="block";
         //obj.style.listStyleImage="url(/images/code/folderminus.gif)";
      } else {
         e.cancelBubble = true;
         obj.style.display="none";
         //obj.style.listStyleImage="url(/images/code/folderplus.gif)";
      } 
   } 
}
</script>

As you can see, the fork (highlighted in Listing 4) is used to differentiate between how events are handled in Netscape and Internet Explorer. The remainder of the script can then use the correct src object to determine whether or not an element should be re-styled when it is clicked on (this script controls the expansion and collapse of the lists of code samples on the Code Library page).

Another example of JavaScript forking can be found on the page mainTemplate.jsp. This page provides the basic template (headers, navigation bars, and so on) for all the pages on the CodeNotes Web site. It is also where the CodeNotes style sheets (.css files) are attached. Listing 5 shows a special script that is used in this template to add an additional style sheet file if the user is using Netscape 4.x.

Listing 5. Forking for Netscape 4.x in mainTemplate.jsp

<script language="JavaScript" type="text/javascript">
<!--
if(navigator.appName.indexOf("Netscape")!=-1 && 
  navigator.appVersion.indexOf("4.")==0) {
   document.write('<link rel=\"stylesheet\" type=\"text/css\"
      href=\"/jsp/Netscape4xStyle.css\">'); 
}
//-->
</script>

In this way, we can ensure that certain CSS classes and attributes that were not implemented in this early version of Netscape are replaced by "older" CSS code that will work.

JLCA Conversion

JavaScript and Microsoft JScript® are virtually identical. This means that any JavaScript you use in your Java Web applications (in JSP or HTML files) will remain as-is when you convert to Microsoft® ASP.NET using the Java Language Conversion Assistant (JLCA). However, since all ASP.NET applications are automatically browser-neutral (for reasons we will see in the next section), most forking code can be safely removed after conversion.

Leveraging ASP.NET

All ASP.NET applications are browser-neutral, meaning the applications you develop are accessible to all browsers (Internet Explorer, Netscape, Opera, and so on) and browser versions (Internet Explorer 4+, Internet Explorer 5.5, Internet Explorer 6.0, and so on). Simply drop your Web Controls onto your Web applications, and let ASP.NET generate the appropriate code at runtime. ASP.NET Web Controls generate the appropriate code after determining whether the user's browser is UpLevel or DownLevel (this classification is explained in the following section). Based on that information, the Web Controls generate either client-side code or server-side code.

Web Controls

A Microsoft ASP.NET Web control is a graphical entity very similar to an intrinsic control found in Microsoft Visual Basic® 6.0 (such as Textbox or Button). Like its Visual Basic counterpart, an ASP.NET Web control exposes a rich event model that you program against (such as the TextChanged() event, which triggers when the contents of a control change). Yet, what's important about Web controls is that they reside entirely on the server and generate the appropriate code (client-side or server-side) at run time, based on a user's browser. Thus, by using Microsoft ASP.NET Web controls, you eliminate the need to explicitly code for different browsers and browser versions.

UpLevel and DownLevel Browsers

To ASP.NET, all browsers have either an UpLevel or DownLevel classification. UpLevel browsers are defined as Internet Explorer 5.5 and greater. DownLevel browsers are defined as Internet Explorer 5.01 and earlier, or browsers other than Internet Explorer. This browser classification is what Microsoft ASP.NET Web controls use to determine what type of code to generate at run time, as in client-side or server-side.

If a user has an UpLevel browser, the Web controls will generate client-side JavaScript and trap the action events directly on the client. If a user has a DownLevel browser, the Web controls will generate standard HTML, requiring that the browser perform a round-trip to the server for triggered action events. Regardless of whether the user's browser is UpLevel or DownLevel, the appropriate code is sent to the user without you worrying about browsers or browser versions.

Extending Web Controls (Custom Web Control Creation)

As you experiment with different Web controls, you will see that some are almost identical to basic HTML, whereas others provide significant value in terms of boilerplate functionality automatically coded for you. Yet, in spite of the flexibility associated with Web controls, you may find yourself in a situation where you either wish to extend an existing Web control's functionality, or possibly create a custom Web control (to provide functionality not satisfied by existing controls). Both of these options are available to you in Microsoft ASP.NET and provide the same multi-browser support, as described in the previous section.

All Web controls shipped with the Microsoft .NET Framework are classes found in the base class library (BCL), specifically the System.Web.UI.WebControls namespace. This BCL provides hundreds of prewritten classes that you can use within your ASP.NET applications. By extending these classes, you can create your own specialized Web controls, allowing you to override undesired default behavior, and inherit functionality you want.

As a basic example, you could override the default behavior of a CompareValidator Web Control—a powerful validation control used to compare Web control values. You could extend the necessary classes to specify that all CompareValidator controls rendered in DownLevel browsers use your own implementation (generating your specified client-side code as opposed to performing a round trip to the server), while all other browsers fall back to the default UpLevel behavior, or client-side code generation.

Summary

If you use JavaScript, DHTML, or any advanced browser technologies, you will generally have to struggle with multi-browser support. ASP.NET removes much of this struggle by placing the burden for cross-browser support on the Web control designer. If the designer does their job properly, all you need to do is drag and drop a control. The JavaScript will be generated automatically in a fashion that is appropriate for the client's browser. This approach saves lots of time and effort, and also reduces the amount of JavaScript that must be pushed down to the client.

When converting from JSP-based Web applications to ASP.NET applications using the JLCA, your JavaScript forking code will generally remain untouched. This is because JavaScript and JScript are virtually identical, and code written in one will work in the other. That being said, it is probably best if you remove forking code entirely from ASP.NET applications and replace it with standard Web controls. The forking code is not required, as ASP.NET Web controls are automatically vendor-neutral and version-neutral.

Given that Microsoft Visual Studio® .NET (and ASP.NET) ship with a large palette of common Web controls, you will rarely need to worry about cross-browser support. You can simply build your custom controls out of the existing control set. However, if you do need to modify a control or create something new, you can selectively override the methods on any control, and write your own JavaScript. Of course, you will then be in a situation where you are responsible for cross-browser support.

© Microsoft Corporation. All rights reserved.