<?xml version="1.0" encoding="Shift_JIS" ?>
<!-- article-1.00.xml template -->

<?xml-stylesheet type="text/xsl" href="/lib/xsl/devedge-1.00/article_ja.xsl"?>

<nde:article 
  url="/viewsource/2002/browser-detection/"
  xmlns:nde="http://devedge.netscape.com/2002/de"
  xmlns:ent="http://devedge.netscape.com/2003/ent"
  xml:lang="ja">

  <nde:header>

  <nde:title>
ブラウザ判別とクロス・ブラウザサポートについて   
  </nde:title>

  <nde:category>
    記事
  </nde:category>

  <nde:authlist>
    <nde:author>
      <nde:authname>著者：Bob Clary</nde:authname>
      <nde:email href="/community/feedback/">Feedback</nde:email>
      <nde:authaffil>
        Netscape Communications
      </nde:authaffil>
    </nde:author>
    <nde:author>
      <nde:authname>　翻訳：桃井勝彦</nde:authname>
      <nde:email href="/community/feedback/">Feedback</nde:email>
    </nde:author>
  </nde:authlist>

  <nde:pubdate year="2002" month="07" day="17" />
  <nde:channels>
    <nde:channel id="viewsource"/>
    <nde:channel id="gecko"/>
  </nde:channels>
  <nde:summary>
      適正でないブラウザ判別法を使うとウェブページ維持にいろいろな支障を来たす悪夢の元となります。効率よく維持できて多くのブラウザで綺麗に見れるクロス・ブラウザの条件を満たすサイトを作るにはいつ、どのようにuser agent判別を使用すべきかの根本を見直すことが必要です。
  </nde:summary>

  <nde:abstract>
  </nde:abstract>
</nde:header>

  <nde:head>
    <style type="text/css">
      dl dt { font-weight: bold; }
      ins { color: green; }
      del { color: red; }

      a.simplelink { font-weight: normal !important; } 

    </style>
  </nde:head>

  <nde:content>
原文: <a class="simplelink" href="index_en.html">英語</a>
 <p>
      適正でないブラウザ判別法を使うとウェブページ維持にいろいろな支障を来たす悪夢の元となります。効率よく維持できて多くのブラウザで綺麗に見れるクロス・ブラウザの条件を満たすサイトを作るにはいつ、どのようにuser agent判別を使用すべきかの根本を見直すことが必要です。このノーツでは幾つかのブラウザ判別法を取り上げ、各々の利点や役に立つ環境を指摘して一般的に使えるブラウザ判別を探る。
    </p>
    <h2>目次</h2>

    <ul>
      <li><a href="#intro">初めに</a></li>
      <li><a href="#introgecko">Netscape Gecko</a></li>
      <li><a href="#detectionhistory">ブラウザ判別方の歴史</a></li>
      <li><a href="#problems">不適正なブラウザ判別で起きる問題</a>
        <ul>
          <li><a href="#probunknown">未知のブラウザを除外する</a></li>
          <li><a href="#probmisidentify">ブラウザ判別の間違い</a></li>
          <li><a href="#probobjectvendorversion">JavaScript オブジェクトを使用して<em>Vendor/version</em> を判定する</a></li>
        </ul>
      </li>
      <li><a href="#recommendations">推奨する判別法</a>
        <ul>
          <li><a href="#recstandards">Target the Standards and not particular Browsers</a></li>
          <li><a href="#recunknown">Provide support for unknown browsers</a></li>
          <li><a href="#recproprietary">Limit the use of <em>Vendor/Version</em> specific features</a></li>
          <li><a href="#reclimitua">Limit the use of User Agent String based Detection</a></li>
          <li><a href="#recdownlevel">Provide <em>downlevel</em> pages for older browsers</a></li>
          <li><a href="#recnonscript">Use non-script based detection methods where possible</a></li>
          <li><a href="#recfeatureobject">Use Feature oriented Object detection</a></li>
        </ul>
      </li>
      <li><a href="#geckonn4">Gecko and Navigator 4</a></li>
      <li><a href="#geckoie">Gecko and Internet Explorer</a></li>
      <li><a href="#geckonavigator">How (and when) to use the <code>navigator</code> object when detecting Gecko</a>
        <ul>
          <li><a href="#geckonavigatorproduct">Product</a></li>
          <li><a href="#geckonavigatorbranch">CVS Branch Tag</a></li>
          <li><a href="#geckonavigatorbuild">Build Date</a></li>
          <li><a href="#geckonavigatorvendor">Vendor/version</a></li>
        </ul>
      </li>
      <li><a href="#examples">Examples</a></li>
      <li><a href="#conclusion">Conclusion</a></li>
      <li><a href="#links">Links</a></li>
    </ul>

    <h2><a name="intro">Introduction</a></h2>

    <p>
      In an <em>ideal</em> world, we could author 
      HTML, XML, CSS and JavaScript and only worry about the W3C and ECMA standards. 
      However, we don't quite live in such a world yet.
      Due to bugs, incomplete implementations of the standards and
      legacy browsers, web developers must be able to determine
      which browser a visitor is using and provide the appropriate
      content and scripting code path.  
    </p>

    <p>
      Although browser detection is perhaps the most common scripting 
      task that every web developer faces, it seems that the variety 
      of different strategies in use for detecting browsers is unlimited.
      As a member of the Netscape Evangelism team who has spent over a year
      investigating existing web content, I can say without a doubt that most
      compatibility problems found on the web today are due to a lack of
      understanding of the standards combined with inadequate and
      inappropriate browser detection strategies.
    </p>

    <p>
      This article is intended to provide an overview of browser detection 
      strategies and best practices. For more specific Netscape Gecko 
      <sup style="font-size: x-small;">TM</sup> recommendations, please see the
      <a href="/viewsource/2002/gecko-compatibility/">Netscape Gecko Compatibility Handbook</a>.
    </p>

    <p><a href="#top">top</a></p>

    <h2><a name="introgecko">Netscape Gecko</a></h2>

    <p>
      Although many web developers are aware of Netscape 6 and Netscape 7, 
      far fewer are aware that Netscape 6 and 7 are members of an entire 
      family of user agents based upon 
      <a href="/central/gecko/">Netscape Gecko</a> that 
      includes the commercial browser 
      <a href="http://www.compuserve.com/">CompuServe 7</a>,
      and open source browsers such as 
      <a href="http://www.mozilla.org/">Mozilla</a>, 
      <a href="http://galeon.sourceforge.net">Galeon</a>, and 
      <a href="">Kmeleon</a>. 
    </p>

    <p>
      Netscape Gecko was designed from the ground up to be compliant
      with the W3C HTML, W3C CSS, W3C XML, W3C DOM, and ECMAScript (JavaScript) 
      standards. It also includes compatibility features which allow
      it to reasonably handle <em>legacy</em> content which was developed
      for earlier generations of browsers such as Netscape Navigator 4
      as well as features which provide compatibility with Internet Explorer 5
      and 6. Unlike other browsers, Netscape Gecko is truly a cross platform
      browser and provides identical support on all operating systems where
      it is supported.
    </p>

    <p>
      The easiest way to support Netscape Gecko is to create content which
      <strong>only</strong> uses the standards. Unfortunately, no other browser
      supports the standards as completely as Netscape Gecko which means that
      web developers and authors are forced to continue to provide support
      for other browsers which do not support the standards as fully. Fortunately,
      other browsers such as Internet Explorer 5 and 6 for Windows, to a lesser
      extent Internet Explorer 5 for Macintosh and Opera 6 also support 
      the standards to a degree. These other browsers also appear to be moving
      towards more complete and rigorous support for the standards and there is
      hope that in the future web developers and authors will be able to
      dispense with browser detection at least with regard to features 
      governed by standards.
    </p>

    <p>
      We are still faced with the question of how to develop standards 
      based content while supporting the differing implementations of 
      modern browsers while at the same time supporting (to a lesser degree) 
      older and less capable browsers. Browser detection is key to
      accomplishing this task.
    </p>

    <p><a href="#top">top</a></p>

    <h2><a name="detectionhistory">Browser Detection History primer</a></h2>

    <p>
      To understand why many common browser detection strategies are
      inappropriate, we must first look back on how these strategies
      came into being.
    </p>

    <p>
      In the earliest days of the web, <a href="http://www.w3.org/MarkUp/">HTML</a> 
      was very simple, not standardized and did not include any support for client
      side scripting.  HTML itself was not standardized until
      HTML 2.0 was introduced in late 1995 and it did not even include tables.
      Browser vendors such as Netscape and Microsoft competed to add compelling 
      <em>features</em> to the HTML they supported
      in their browsers in order to provide the richest most compelling content to 
      their users and to entice web authors to support them. The abilities of 
      browsers to support the latest and greatest content changed on an almost
      daily basis.
    </p>

    <p>
      Web authors were faced from the beginning with a variety of browsers, some of
      which supported the latest and greatest version HTML and some which did not. The 
      solution was either to provide the lowest-common denominator of HTML or to 
      use browser detection techniques on the web server to send customized content
      to each browser depending on what level of support the browser provided. 
      server side browser detection using user agent strings was born.
    </p>

    <blockquote>
      User agent strings are defined in the HTTP protocol and are available to web
      servers (see 
      <a href="http://www.faqs.org/rfcs/rfc1945.html">RFC 1945 - Hypertext
        Transfer Protocol -- HTTP 1.0</a> and
      <a href="http://www.faqs.org/rfcs/rfc2068.html">RFC 2068 - 
        Hypertext Transfer Protocol -- HTTP 1.1</a>). 
    </blockquote>

    <p>
      The most common approach at this time was to distinguish user agents by <em>vendor</em>
      and <em>version</em> using the reported user agent string. 
      Although this approach was considered reasonable at the time, 
      this approach caused problems for browser vendors right from the beginning.
      The original Netscape browsers used a user agent string which began with 
      the code name for the Netscape browser followed by it's version number, e.g. 
      <code>Mozilla/version</code> followed by a comment token which gave additional
      information regarding the operating system being used, etc.
      Since the earliest browser detection techniques were based upon looking for
      a Netscape based browser and only provided customized content to browsers
      which used the <code>Mozilla/version</code> user agent string, other browser 
      vendors standardized on using <code>Mozilla/version</code> to signal that
      they were compatible with a particular Netscape version. Since other browsers
      <em>pretended</em> to be Netscape browsers and encoded their version information
      in a non-standard fashion in the user agent comment area, the task of 
      determining which browser was being used became more complicated than it should 
      have been.
    </p>

    <p>
      Netscape Navigator 2 introduced the ability to run JavaScript in web browsers.
      As browser evolution continued, 
      differences in the implementation of scripting and the objects supported by 
      browsers appeared. Web authors were no longer limited to detecting browsers 
      on their web servers, but could now execute scripts client side (in the browser itself) 
      which could be used to distinguish browsers.
      One of the earliest approaches to client side browser detection involved testing whether
      the browser supported particular <em>objects</em>. An example of this approach involved
      testing for the existence of the <code>document.images</code> object.
    </p>

    <p>
      While <em>object based detection</em> was used in some circumstances, 
      many web authors continued to use the <em>vendor/version</em> approach to
      distinguishing web browsers in their client side scripts.
      Since the user agent string was exposed as a property of the <code>navigator</code> object 
      (e.g. <code>navigator.userAgent</code>), many web authors used the same
      logic in their client side scripts as they had used earlier in their server side
      browser detection.  In addition to <code>navigator.userAgent</code>
      other properties such as <code>appName</code> and <code>appVersion</code>
      were available in the <code>navigator</code> object which could be 
      used in browser <em>vendor/version</em> detection strategies. 
    </p>

    <p>
      The classic example of this <em>vendor/version</em> client side detection
      strategy can be found in the 
      <a href="http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html">Ultimate Browser Sniffer</a>.
      This script and variants of it can be found today on many web sites where it
      is a common source of detection problems.
    </p>

    <p>
      Netscape Navigator 4 and Internet Explorer 4 
      introduced the ability to manipulate HTML content in a browser
      (Dynamic HTML or DHTML) rather than on the web server and 
      began the introduction of support for CSS to style content.
      This generation of browser, in addition to sharing 
      several features which were not available in earlier versions, 
      each implemented their own (incompatible) competing abilities to 
      manipulate content in a web page.
    </p>

    <p>
      Since each vendor's browser implemented different objects to perform DHTML,
      web authors began to use <em>object detection</em> to distinguish 
      <em>vendor/version</em> through the existence of particular JavaScript objects.
      The existence of <code>document.layers</code> was sufficient to
      be sure that the browser was Netscape Navigator 4 while the 
      existence of <code>document.all</code> was sufficient to be
      sure that the browser was Microsoft Internet Explorer 4.
      An implicit assumption by many web authors around this time was the there
      were only two types of browser available... Netscape Navigator and 
      Microsoft Internet Explorer. 
    </p>

    <p>
      These strategies of classifying browsers by <em>vendor/version</em>, 
      assuming that the only browsers being used where either Netscape Navigator 4
      or Internet Explorer 4 <strong>failed</strong> when alternative browsers
      such as those based upon Netscape Gecko were introduced. Many of the 
      problems reported in the press regarding Gecko's inability to display 
      content were directly related to inadequate, inappropriate browser detection
      strategies.
    </p>

    <p>
      A final note on <em>vendor/version</em> strategies. A web developer who 
      fully utilizes the browser detection and distinctions in the 
      <a href="http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html">Ultimate Browser Sniffer</a>
      will produce code which uses code forks for many browsers and versions. Imagine
      attempting to maintain a web site which uses many of the browser variables available
      from the Ultimate Browser Sniffer.
    </p>
    <table>
      <tr>
        <td>browser vendor</td>
        <td>
          is_nav, is_ie, is_opera, is_hotjava, is_webtv, is_TVNavigator, is_AOLTV
        </td>
      </tr>
      <tr>
        <td>browser version number</td>
        <td>
          is_major (integer indicating major version number: 2, 3, 4 ...)
          is_minor (float   indicating full  version number: 2.02, 3.01, 4.04 ...)
        </td>
      </tr>
      <tr>
        <td>browser vendor AND major version number</td>
        <td>
           is_nav2, is_nav3, is_nav4, is_nav4up, is_nav6, is_nav6up, is_gecko, is_ie3,
           is_ie4, is_ie4up, is_ie5, is_ie5up, is_ie5_5, is_ie5_5up, is_ie6, is_ie6up, is_hotjava3, is_hotjava3up,
           is_opera2, is_opera3, is_opera4, is_opera5, is_opera5up
         </td>
      </tr>
      <tr>
        <td>JavaScript version number</td>
        <td>
          is_js (float indicating full JavaScript version number: 1, 1.1, 1.2 ...)
        </td>
      </tr>
      <tr>
        <td>OS platform and version</td>
        <td>
          is_win, is_win16, is_win32, is_win31, is_win95, 
          is_winnt, is_win98, is_winme, is_win2k,
          is_os2, is_mac, is_mac68k, is_macppc, 
          is_unix, is_sun, is_sun4, is_sun5, is_suni86,
          is_irix, is_irix5, is_irix6,
          is_hpux, is_hpux9, is_hpux10,
          is_aix, is_aix1, is_aix2, is_aix3, is_aix4,
          is_linux, is_sco, is_unixware, is_mpras, is_reliant,
          is_dec, is_sinix, is_freebsd, is_bsd,
          is_vms
        </td>
     </tr>
   </table>

   <p>
     <strong>Detecting browsers using this level of detail is unworkable, unmaintainable
       and violates the basic principles of web authoring!</strong> I strongly advise everyone
     to avoid this trap.
   </p>


    <p><a href="#top">top</a></p>

    <h2><a name="problems">Problems caused by inappropriate Browser Detection</a></h2>

    <h3><a name="probunknown">Excluding Unknown Browsers</a></h3>
    <p>
      If you only provide tests for specific browsers in your detection logic,
      your site will not be usable if a visitor uses a different browser. Consider
      the following example:
    </p>

    <blockquote>
      <pre><![CDATA[
// WRONG APPROACH - do not use!
if (document.all)
{
  // Internet Explorer 4+
  document.write('<link rel="stylesheet" type="text/css" src="style-ie.css">');
}
else if (document.layers)
{
  // Navigator 4
  document.write('<link rel="stylesheet" type="text/css" src="style-nn.css">');
}
]]></pre>
    </blockquote>

    <p>
      Note how the above example only provided stylesheets for Internet Explorer
      and Navigator 4 and even then only if the visitor has JavaScript support
      turned on in their browser. Users of Netscape 6, Netscape 7, CompuServe 7,
      Mozilla, Opera will not be able to view the site properly.
    </p>

    <h3><a name="probmisidentify">Misidentifying Browsers</a></h3>
    <p>
      A common mistake web authors make is to assume that if a browser is not
      Netscape Navigator 4, it must be Internet Explorer and vice versa. For example:
    </p>

    <blockquote>
      <pre><![CDATA[
// WRONG APPROACH - do not use!
if (document.all)
{
  // Internet Explorer 4+
  elm = document.all['menu'];
}
else
{
  // Assume Navigator 4
  elm = document.layers['menu'];
}
]]></pre>
    </blockquote>

    <p>
      Note how the above example assumed that any browser that was not
      Internet Explorer was Navigator 4 and attempted to use <em>Layers</em>.
      This is a common source of problems when using browsers based upon 
      Netscape Gecko as well as Opera. A similar error can be seen in the 
      following example:
    </p>

    <blockquote>
      <pre><![CDATA[
// WRONG APPROACH - do not use!
if (document.layers)
{
  // Navigator 4
  elm = document.layers['menu'];
}
else
{
  // Assume Internet Explorer 4+
  elm = document.all['menu'];
}
]]></pre>
    </blockquote>

    <p>
      Netscape 6 was the first commercial browser released based upon
      Netscape Gecko.  Due to a lack of communication and understanding,
      many sites have created inappropriate detection strategies based upon the
      Netscape 6 user agent string. Netscape 6's user agent string follows the 
      HTTP standards for specifying the version of the user agent. 
      (see <a href="http://www.mozilla.org/build/revised-user-agent-strings.html">Mozilla user-agent strings</a>
      and <a href="/viewsource/2002/gecko-useragent-strings/">Netscape Gecko User Agent Strings</a>)
    </p>

    <blockquote>
    <pre>
Mozilla/5.0 (...) Gecko/20001108 Netscape6/6.0</pre>
    </blockquote>

    <p>
      The first vendor/version (<code>Mozilla/5.0</code>)
      indicates that Netscape 6 is a <em>fifth</em> generation browser
      and is not identical to earlier browsers. All Gecko based browsers
      currently report <code>Mozilla/5.0</code> as their primary version
      although no other browser does so at the moment. Hopefully when
      other browser vendors achieve the same level of standards support 
      as Gecko and begin to drop support for legacy browsers, they too
      will begin to report version 5. Assuming that only Netscape Gecko
      will use <code>Mozilla/5.0</code> will cause your browser detection
      logic to fail as soon as another browser vendor releases a 
      browser which reports <code>Mozilla/5.0</code>.
    </p>

    <p>
      The second vendor/version (<code>Gecko/20001108</code>) identifies
      Netscape 6 as a particular release of Netscape Gecko which was
      built on November 8, 2000. If you must detect Gecko using the 
      user agent string, <code>Gecko/version</code> is the most appropriate
      string to search for.
    </p>

    <p>
      The third vendor/version (<code>Netscape6/6.0</code>) identifies
      this particular instance of a Gecko browser as Netscape 6.0.  
      Many sites keyed off of the existence of the string
      <code>Netscape6</code> in the user agent and used tests similar
      to:
    </p>

    <blockquote>
    <pre><![CDATA[
if (navigator.userAgent.indexOf('Netscape6') != -1)     
{
  // Netscape 6 code
}
      ]]></pre>
  </blockquote>

  <p>
    Note how this type of detection misses any other Gecko based
    browser. Unfortunately, the Netscape 6 user agent string was
    not sufficiently generalizable due to it's use of the string
    <code>Netscape6</code> as a description of the <em>vendor</em>.
    Netscape 7 corrects this error and introduces another chance 
    for user agent string based detection to fail.
  </p>

    <blockquote>
    <pre>
Mozilla/5.0 (...) Gecko/200207XX Netscape/7.0</pre>
    </blockquote>

    <p>
      Note how Netscape 7 no longer uses the string <code>Netscape6</code>
      as the Vendor. Any user agent string detection strategy for Gecko
      based upon the existence of the string <code>Netscape6</code> will
      fail to detect Netscape 7.
    </p>

    <h3><a name="probobjectvendorversion">Using JavaScript Objects to determine <em>vendor/version</em></a></h3>

    <p>
      As we already discussed, a common approach in the past was to use
      objects to classify browsers by <em>vendor/version</em>. A common 
      type of detection which originally was written to support only 
      Netscape Navigator 4 and Internet Explorer 4 might look like:
    </p>
    <blockquote>
      <pre><![CDATA[
// WRONG APPROACH - do not use!
if (document.all)
{
  // IE4
  height = document.body.offsetHeight;
}
else if (document.layers)
{
  // NN4
  height = window.innerHeight;
}
else
{
  // other
  height = 0;
}
      ]]></pre>
    </blockquote>

      <p>
        With the introduction of the W3C DOM, the standard method 
        <code>document.getElementById</code> became available in 
        Internet Explorer 5 and later in Netscape 6 (Gecko). Many 
        web authors decided that the easiest way to add support 
        for Netscape Gecko was to add another code fork as follows:
      </p>
    <blockquote>
      <pre><![CDATA[
// WRONG APPROACH - do not use!
if (document.all)
{
  // IE4
  height = document.body.offsetHeight;
}
else if (document.layers)
{
  // NN4
  height = window.innerHeight;
}
else if (document.getElementById)
{
  // They think this is Netscape Gecko
  // but could be wrong!
  height = window.innerHeight;
}
else
{
  // other
  height = 0;
}
      ]]></pre>
    </blockquote>

    <p>
      The approach is incorrect since it assumes that the only other browser
      besides Internet Explorer 5+ that implements <code>document.getElementById</code>
      is Netscape Gecko. This is not true today and will become even less true 
      as more browsers which support the W3C DOM Standards are introduced in the future.
    </p>

    <p><a href="#top">top</a></p>

    <h2><a name="recommendations">Recommendations</a></h2>

    <h3><a name="recstandards">Target the standards and not particular browsers</a></h3>

    <p>
      While the period from 1994-2000 was dominated by incompatible
      non-standard browsers from Netscape and Microsoft, today the
      dominating factor in web development are the standards proposed
      by the World Wide Web Consortium (<a href="http://www.w3.org/">W3C</a>).
      Standards are important for web developers due to the increased flexibility,
      power of presentation, support for users with disabilities to name 
      just a few reasons.
    </p>

    <p>
      Targeting your web content to particular vendors 
      ignores the possibility that other browsers which support 
      the same standards may be introduced in the future. A common problem 
      on the web today is the assumption that the only browsers in the world
      are Netscape Navigator and Microsoft Internet Explorer. This ignores
      the existence of <a href="http://www.opera.com/">Opera</a> as well as
      the newer handheld devices which are being used to access the web today
      and in the future.
    </p>

    <p>
      Today, both Netscape (Netscape 6 and above) and Microsoft (Internet Explorer 5.5
      and above) provide browsers which due to their support for the standards
      are more similar than they are different. This similarity will only increase
      as each browser implements more and more of the standards.
    </p>

    <p>
      <a href="http://www.mozilla.org/docs/web-developer/quirks/">Netscape 6 and above</a>, 
      <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnie60/html/cssenhancements.asp">Internet Explorer 6</a>
      on Windows, and Internet Explorer 5 for Macintosh 
      all support <em>DOCTYPE switching</em>. This is a technique where these
      browsers can be switched from <em>Quirks</em> mode (which emulates buggy implementations
      in earlier generation browsers) to <em>Standards</em> mode (which more strictly 
      adhers to the Standards). For new content, we recommend that you use a DOCTYPE
      which will invoke Standards mode in Netscape Gecko and Internet Explorer 6.
      This will ensure that your designs work similarly in these browsers as well
      as in any other browsers which support the Standards.
    </p>

    <h3><a name="recunknown">Provide support for unknown browsers</a></h3>

    <p>
      Always provide content and code paths for unknown browsers. The recommended
      approach is to assume that any unknown browser supports the basic standards
      of HTML and CSS and to a certain extent JavaScript and the W3C DOM.
      This will guarantee that your content will be supported today and in the 
      future by <strong>any</strong> browser which supports the standards.
    </p>

    <h3><a name="recproprietary">Limit the use of <em>vendor/version</em> specific features</a></h3>

    <p>
      Authoring content which is standards compliant is the easiest way to
      support the widest range of user agents and to decrease your maintenance
      costs. While it is not always possible to avoid <em>vendor/version</em>
      specific differences between browsers, the use of such features and 
      the distinction between browsers based on <em>vendor/version</em> should
      be strictly limited to those areas where it is still required.
    </p>

    <h3><a name="reclimitua">Limit the use of User Agent String based Detection</a></h3>

    <p>
      Server side browser detection requires the use of user agent strings.
      We recommend that the use of user agent string based detection be
      limited to server side situations and except in those circumstances 
      where it is absolutely required such as when details of the Netscape
      Gecko branch are required. 
    </p>

    <p>
      There are <strong>legitimate</strong> reasons to use the user
      agent string (or the 
      <code><a href="/library/xref/2002/client-data/property-data-navigator.html">navigator</a></code>
      object) to determine 
      exactly what vendor, version or operating system is being used. Many
      financial sites (banks, online stock trading firms, etc) have very 
      strict policies with respect to what browsers they support. This is
      due to the history of security exploits that have been discovered in
      older browsers. If you have the need to only allow specific versions
      of browsers to use your secure site, then the user agent string and
      the related information from the <code>navigator</code> object can
      be very useful.
    </p>

    <p>
      You can also use detailed information regarding a browser's version
      to work around bugs in specific releases of a browser. However, this
      can quickly become a maintenance nightmare if you are not careful. I 
      recommend that you only provide work arounds for bugs on a temporary basis
      and as soon as bugs are corrected in newer releases of the browser that
      you require your visitors to upgrade their browser.
    </p>

    <h3><a name="recdownlevel">Provide <em>downlevel</em> pages for older browsers</a></h3>

    <p>
      No commercial web site today makes complete support for Netscape Navigator versions
      1, 2 or 3 or Microsoft Internet Explorer 3 a requirement. The reasons are 
      that the capabilities of such browsers are far too limited compared to
      more modern browsers, the added development and quality assurance
      requirements add too much to the development cost of web sites and 
      the market share of such browsers does not justify the expense of supporting
      them.
    </p>

    <p>
      One of the most important decisions you can make in order to improve
      the quality of your site and decrease development, maintenance and quality
      assurance costs is to provide only limited support for older browsers
      such as Netscape Navigator 4 and Internet Explorer 4. One of the more 
      common approaches in major web sites is to provide a <em>downlevel</em>
      version of a web page to older browsers while providing a richer page
      which uses advanced CSS and JavaScript to more modern browsers. This can 
      be accomplished through server side browser detection either as part of
      a scripted solution or as part of the web server's native ability to 
      serve different content to different user agents. This approach does
      not necessarily require you to author separate pages for downlevel 
      and modern browsers. A common solution is to author content in a neutral
      format such as XML and use XSLT transformations to generate the necessary
      HTML for each class of browser.
    </p>

    <p>
      Whether a particular browser should be provided with <em>downlevel</em>
      content depends to an extent on what features of CSS or JavaScript are
      being used in the <em>advanced</em> content. Netscape Navigator 4 and
      Internet Explorer 4 should both be considered <em>downlevel</em> browsers
      for most pages due to their limited support for CSS and the more recent
      DOM based standards. If your pages make use of advanced JavaScript 
      which manipulates or creates new content using the W3C DOM Core, then
      Opera 5 and 6 should be considered downlevel as well due to their limited
      support for the W3C DOM. 
    </p>

    <p>
      The future belongs to developers and browsers which support standards. If you
      fail to take advantage of the coming change in browsers, your competitors
      will <em>eat your lunch</em>. Once that happens, the only place your web site
      will be found is on the <a href="http://web.archive.org/">web archive</a>.
    </p>

    <h3><a name="recnonscript">Use non-script based detection methods where possible</a></h3>

    <p>
      Older browsers have many limitations which result in their ignoring
      more advanced features. By judiciously using these limitations in 
      older browsers you can include modern content while at the same time
      supporting older browsers.
    </p>

    <p>
      HTML provides several methods of detecting support for various 
      features such as support for scripting and FRAMES. Use these 
      natural abilities of HTML to extend the range of browsers your
      content supports.
    </p>

    <h4>Using NOFRAMES to support NON-FRAMES capable browsers</h4>

      <pre><![CDATA[
<HTML>
  <HEAD>
    <TITLE>FRAMES</TITLE>
  </HEAD>
  <FRAMESET ROWS="30,*">
    <FRAME SRC="foo.html">
    <FRAME SRC="bar.html">
    <NOFRAMES>
      <BODY>
        <P>
          This page requires frames. See <a href="noframes.html">sitemap</a>.
        </P>
      </BODY>
    </NOFRAMES>
  </FRAMESET>
</HTML>
]]></pre>

      <h4>Using NOSCRIPT to support non-scriptable browsers</h4>

      <p>
        Some browsers may not support scripting while some users may have
        scripting support turned off in their browser. Use the NOSCRIPT
        tag to provide these users with alternative unscripted versions of
        your pages or to at least notify them of the need to use scripting
        in order to view your content properly.
      </p>

      <p>
        Since browsers such as Netscape Navigator 4 and Internet 
        Explorer 4 do not support some of the most recent additions
        to the JavaScript (ECMAScript) standard, it is often necessary
        to limit the use of advanced JavaScript features such as <em>exception</em>
        processing. One approach is to require that users of browsers
        which do not support the level of JavaScript used in your content
        to <strong>turn off</strong> JavaScript in order to be able to use 
        your content. You can do this by providing an error message for
        users of older browsers as well as alternative content contained
        in NOSCRIPT tags.
      </p>

      <pre><![CDATA[
<HTML>
  <HEAD>
    <TITLE>NOSCRIPT</TITLE>
  </HEAD>
  <BODY>
    <SCRIPT LANGUAGE="JavaScript">
      window.onerror = function () 
      {
        // redirect user to a page describing the limitations
        // of their browser and requesting that they turn off
        // JavaScript in order to view your site.
      }

      // Netscape Navigator 4 will throw an error
      // on any JavaScript which attempts to use
      // try ... catch exception processing.
      try
      {
        // Code to implement fancy Menu
      }
      catch (errors)
      {
        // handle Exceptions
      }
    </SCRIPT>
    <NOSCRIPT>
      <!-- 
      if javascript is not enabled, then the browser
      will display the contents of the NOSCRIPT tag
      which in this case is a simple MENU implemented
      as an unordered list.
      -->
      <UL>
        <LI><A HREF="choice1.html">Choice1</A></LI>
        <LI><A HREF="choice2.html">Choice2</A></LI>
      </UL>
    </NOSCRIPT>
  </BODY>
</HTML>
]]></pre>
      <h4>Using SCRIPT LANGUAGE to choose the browser where it will be executed</h4>

      <p>
        The choice of scripting language is determined by the 
        LANGUAGE attribute of the script tag.
        Internet Explorer 4 and above can support a variety of script 
        languages. The most common are <em>VBSCRIPT</em> and <em>JavaScript</em>.
        Internet Explorer also uses <em>JSCRIPT</em> as a synonym for 
        JavaScript. Since other browsers do not support the language
        attribute <em>VBSCRIPT</em> or <em>JSCRIPT</em> you can use
        these languages when you wish certain scripts to only be 
        executed by Internet Explorer 4 and above.
      </p>

      <pre><![CDATA[
<HTML>
  <HEAD>
    <TITLE>SCRIPT Languages</TITLE>
  </HEAD>
  <BODY>
    <SCRIPT LANGUAGE="JavaScript">
      // JavaScript Code to implement fancy Menu
      // Visible to all JavaScript capable browsers
    </SCRIPT>
    <SCRIPT LANGUAGE="JScript">
      // JavaScript Code that uses proprietary 
      // Internet Explorer features not available in
      // other browsers.
    </SCRIPT>
    <SCRIPT LANGUAGE="VBScript">
      // VBScript Code that uses proprietary 
      // Internet Explorer features not available in
      // other browsers.
    </SCRIPT>
  </BODY>
</HTML>
]]></pre>

      <h4>Using Netscape Navigator 4's CSS limitations</h4>

      <p>
        It is possible to use Netscape Navigator 4's limitations for CSS support
        to automatically exclude certain CSS rules from ever being seen by 
        Navigator 4.
      </p>

      <p>
        For example, Navigator 4 does not understand the @import
        directive in CSS and will not load any external CSS Style sheets specified
        via @import. This technique can be used to provide basic common CSS rules
        for all browsers (including Navigator 4) while providing more advanced 
        rules in a external CSS file for more modern CSS compliant browsers.
      </p>

      <blockquote>
        <pre><![CDATA[
<STYLE type="text/css">
/* Navigator 4 CSS rules */
</STYLE>

<STYLE type="text/css">
/* Advanced CSS rules ignored by Navigator 4 */
@import "advanced.css";
</STYLE>
]]></pre>
      </blockquote>

      <p>
        A similar technique is available for hiding CSS rules from
        Navigator 4 using the fact that Navigator 4 will ignore CSS
        rules after an occurence of <code>/*/*/</code> in a stylesheet.
      </p>

      <blockquote>
        <pre><![CDATA[
<STYLE type="text/css">
/* Navigator 4 CSS rules */

/*/*/
/* Advanced CSS rules ignored by Navigator 4 */
</STYLE>
]]></pre>
      </blockquote>

      <p>
        DevEdge uses this technique to hide advanced CSS from
        Navigator 4.
      </p>


      <h3><a name="recfeatureobject">Use feature oriented object detection</a></h3>

      <p>
        Object detection is a powerful method of providing cross browser 
        support in your web content. Although you can use object detection as 
        just another means of distinguishing between <em>vendor/version</em> 
        the technique shows it's true power when used to detect features 
        rather than browsers. 
      </p>

      <p>
        Feature oriented object detection is the testing
        for the existence of specific objects before attempting 
        to use them in a script. The classic example is:
      </p>

      <blockquote>
        <pre><![CDATA[
if (document.images)
{
  // code which processes the images 
}
]]></pre>
      </blockquote>

      <p>
        The advantage to feature detection is that it will work
        regardless of the <em>vendor/version</em>. We can rewrite
        the earlier example which illustrated problems with 
        using objects to determine <em>vendor/version</em> to 
        use feature detection instead.
      </p>

    <blockquote>
      <pre><![CDATA[
if (document.body && typeof(document.body.offsetHeight) == 'number')
{
  height = document.body.offsetHeight;
}
else if (typeof(window.innerHeight) == 'number')
{
  height = window.innerHeight;
}
else
{
  height = 0;
}
]]></pre>
    </blockquote>

      <p>
        Note how the previous example does not make assumptions about
        which browser is being used. Instead, it only tests for the
        objects which it wishes to use. Since the numeric values
        could potentially be zero, the script tests the type of the 
        objects to make sure they are numbers instead.
      </p>
        
    <h2><a name="geckonn4">Gecko and Navigator 4</a></h2>

    <p>
      Gecko is the replacement for Navigator 4 and as such retains many features
      from Navigator 4. The basic differences between Navigator 4 and Gecko
      can be easily summarized by:
    </p>

    <h4>Differences between Gecko and Navigator 4</h4>
    <dl>
      <dt>Gecko is standards conformant</dt>
      <dd>
        <p>
          Gecko supports many more standards than Navigator 4 and 
          implements them correctly unlike Navigator 4.
        </p>
      </dd>

      <dt>Gecko does not support Layers</dt>
      <dd>
        <p>
          Navigator 4 introduced the Layer API which it used to
          manipulate content and which formed the basis of DHTML
          in Navigator 4.
        </p>

        <p>
          Layers however were not accepted by the W3C either in HTML
          or in the DOM. Since Gecko's mission was to be the most 
          standards conformant browser possible, Layers were not
          supported. This lack of backwards compatibility has been
          the cause of many problems for web authors, but can easily
          be overcome through proper authoring and browser detection
          strategies. As the use of Navigator 4 decreases and more authors
          use the standards in their content, Layers and the problems
          they cause will disappear.
        </p>

      </dd>
    </dl>

    <p><a href="#top">top</a></p>

    <h2><a name="geckoie">Gecko and Internet Explorer</a></h2>

    <p>
      Gecko implements a number of Internet Explorer only proprietary
      features especially with respect to their 
      <a href="http://msdn.microsoft.com/...">DHTML object model</a>. 
      Gecko's support for a number of IE's features has steadily increased
      since the introduction of Netscape 6 in November 2000. The best
      approach to take advantage of these IE compatibility features 
      in Gecko is to use object based feature detection. This will automatically
      use any such features in Gecko if they are available in the version of
      Gecko being used.
      See the <a href="/library/xref/2002/client-data/">Client Object Cross Reference</a>
      for more details on which Internet Explorer's objects and
      properties are supported by which version of Gecko.
    </p>

    <p>
      A number of Internet Explorer features <strong>are not supported by Gecko</strong>.
      These include the <code>window.event</code> object, behaviors,
      filters, transitions, and ActiveX.
    </p>

    <p><a href="#top">top</a></p>

    <h2><a name="geckonavigator">How (and when) to use the <code>navigator</code> object when detecting Gecko</a></h2>

    <p>
      Unless you specifically need to detect if Gecko is being used, do not use
      these methods. These methods should only be used in circumstances which
      can not be handled by using <em>object feature detection</em> such as when
      specific versions of Gecko must be excluded for security reasons. 
    </p>

    <p>
      <strong>Note:</strong> For client side detection, we recommend using the 
      <code>navigator</code> object and it's properties. All of the information 
      reported in the <code>navigator</code> is also available in the user agent
      string which can be used in server side situations.
    </p>

    <h3><a name="geckonavigatorproduct">Product</a></h3>
    <p>
      <code>navigator.product</code> is specific to Gecko browsers and will 
      always return <code>'Gecko'</code>. The is a quick and simple means of
      determining that a browser is based upon Netscape Gecko.
    </p>

    <h3><a name="geckonavigatorbranch">CVS Branch Tag</a></h3>
    <p>
      Beginning in Gecko 0.9.0 (Netscape 6.1 in Gecko 0.9.2), 
      <code>navigator.userAgent</code> 
      contains the CVS branch tag of the source which was used to 
      create the version of Gecko being used in the browser. 
      The branch tag is contained in the comment 
      area of the user agent string and follows the string 
      <code>'rv:'</code>. In the following example, the branch tag is 
      <code>a.b.c</code>.
    </p>

    <pre>
      Mozilla/5.0 (...; rv:a.b.c) Gecko/CCYYMMDD Vendor/version
    </pre>

    <p>
      Gecko browsers which are built from the same branch share the same basic version of
      Netscape Gecko and can be treated similarly when dealing with HTML, CSS, JavaScript,
      etc. For example, Netscape 6.2, 6.2.1, 6.2.2, 6.2.3 and CompuServe 7 are all built
      from the <code>0.9.4</code> branch and therefore share similar behavior 
      in many ways.
    </p>

    <table border="1">
      <caption>Gecko Branch Tags</caption>
      <tr><th>Browser</th><th>Branch Tag</th></tr>
      <tr><td>Netscape 6.0</td><td>contained M18 rather than the rv value</td></tr>
      <tr><td>Netscape 6.1</td><td>0.9.2</td></tr>
      <tr><td>Netscape 6.2</td><td>0.9.4</td></tr>
      <tr><td>Netscape 6.2.1</td><td>0.9.4</td></tr>
      <tr><td>Netscape 6.2.2</td><td>0.9.4.1</td></tr>
      <tr><td>Netscape 6.2.3</td><td>0.9.4.1</td></tr>
      <tr><td>CompuServe 7</td><td>0.9.4.2</td></tr>
      <tr><td>Netscape 7</td><td>1.0.1</td></tr>
    </table>

    <p>
      As you can see, all versions of Netscape 6.2 and CompuServe 7
      were created from the <code>0.9.4</code> branch. The distinction
      between <code>0.9.4</code>, <code>0.9.4.1</code>, <code>0.9.4.2</code>
      is minor.
    </p>

    <p>
      <strong>Note:</strong> The branch tag is a string and can contain
      more than single digits in any particular level. For example,
      it is conceivable that someday there will exist branch tags
      similar to <code>2.2.0</code> and <code>2.12.36</code>. Since
      these values are strings, it is not possible to use relative string
      comparisons to determine which branch tag came later. In our 
      example, branch <code>2.2.0</code> was created before <code>2.12.36</code>
      however comparing these values as strings shows <code>'2.2.0' > '2.12.36'</code>.
      The JavaScript function 
      <a href="/xbProjects-docs-srce/geckoGetRv/"><code>geckoGetRv()</code></a>
      provides one solution to this problem by converting the branch tag 
      in the user agent string into a floating point number where each 
      level of the branch tag is considered as a number from 0-99.
    </p>

    <table border="1">
      <caption>geckoGetRv() Examples</caption>
      <tr><th>Branch Tag</th><th>geckoGetRv()</th></tr>
      <tr><td>0.9.2</td><td>0.0902</td></tr>
      <tr><td>0.9.4</td><td>0.0904</td></tr>
      <tr><td>0.9.4.1</td><td>0.090401</td></tr>
      <tr><td>0.9.4.2</td><td>0.090402</td></tr>
      <tr><td>1.0.1</td><td>1.0001</td></tr>
      <tr><td>2.2.0</td><td>2.02</td></tr>
      <tr><td>2.12.36</td><td>2.1236</td></tr>
    </table>

    <p>
      <code>geckoGetRv()</code> returns values which can be compared using
      greater than, less than, etc. <code>geckoGetRv()</code> is not an official
      part of Netscape Gecko however is provided as an example of approaches 
      you can take to compare the different branch tags today and in the future.
    </p>

    <h3><a name="geckonavigatorbuild">Build Date</a></h3>
    <p>
      <code>navigator.productSub</code> is specific to Gecko browsers and will
      return a string containing the date the browser was built in the format
      CCYYMMDD (e.g. '20020801' for August 1, 2002). 
      If you are concerned about a specific security
      issue in Gecko and know for example that all Gecko browsers
      contain a fix for the issue after a certain date, you can check that the 
      <code>navigator.productSub</code> value is after that date.
    </p>

    <p>
      You can also distinquish between <em>point releases</em> using a combination
      of the branch tag and the build date. For example, Netscape 6.2.2 and Netscape 6.2.3
      both have branch tags <code>0.9.4.1</code>, but Netscape 6.2.2 has 
      <code>navigator.productSub == '20020314'</code> while Netscape 6.2.3 has
      <code>navigator.productSub == '20020508'</code>.
    </p>

    <h3><a name="geckonavigatorvendor">vendor/version</a></h3>
    <p>
      All Gecko browsers report the vendor and vendor's version both in
      the <code>navigator</code> object and the user agent string.
      The vendor and version information is not as useful as the 
      branch tag and the build date however and we do not recommend their
      use. However, if you wish, you can distinguish the different 
      types of Gecko browser using these values. As we saw earlier,
      the vendor/version appear in the user agent string following
      the Gecko version.
    </p>

    <pre>
      Mozilla/5.0 (...; rv:a.b.c) Gecko/CCYYMMDD Vendor/version
    </pre>

    <p>
      The vendor is available in the <code>navigator</code>
      object as <code>navigator.vendor</code> while the vendor's 
      version is available as <code>navigator.vendorSub</code>.
    </p>

    <table border="1">
      <caption>Gecko vendor/version values</caption>
      <tr><th>Browser</th><th>Vendor</th><th>version</th></tr>
      <tr><td>Netscape 6.0</td><td>Netscape6</td><td>6.0</td></tr>
      <tr><td>Netscape 6.01</td><td>Netscape6</td><td>6.01</td></tr>
      <tr><td>Netscape 6.1</td><td>Netscape6</td><td>6.1</td></tr>
      <tr><td>Netscape 6.2</td><td>Netscape6</td><td>6.2</td></tr>
      <tr><td>Netscape 6.2.1</td><td>Netscape6</td><td>6.2.1</td></tr>
      <tr><td>Netscape 6.2.2</td><td>Netscape6</td><td>6.2.2</td></tr>
      <tr><td>Netscape 6.2.3</td><td>Netscape6</td><td>6.2.3</td></tr>
      <tr><td>CompuServe 7.0</td><td>CS 2000 7.0</td><td>7.0</td></tr>
      <tr><td>Netscape 7 Preview Release 1</td><td>Netscape</td><td>7.0b1</td></tr>
      <tr><td>Netscape 7</td><td>Netscape</td><td>7.0</td></tr>
    </table>

    <p><a href="#top">top</a></p>

    <h2><a name="examples">Examples</a></h2>

    <p>
      If you are like me, you learn best from examples. Studying how
      other authors use browser detection and cross browser coding 
      techniques in the <strong>best</strong> way to learn.
    </p>

    <h3>Example 1 - object based feature detection</h3>
    <p>
      This example illustrates the use of <em>feature detection</em>. Note that
      Gecko 1.0 (Netscape 7) and later implement the proprietary Internet Explorer feature
      <code>clientWidth</code> while Netscape 6 did not. In this example, Netscape 7
      and Internet Explorer 5+
      will automatically use <code>clientWidth</code> while Netscape Navigator 4,
      Netscape 6, CompuServe 7 <em>and Opera</em> will use <code>innerWidth</code>.
    </p>

    <p>
      Compare how you would have had to code this using <em>vendor/version</em>
      based detection approaches.
    </p>

    <blockquote>
      <pre><![CDATA[
if (windowRef.document.body && typeof(windowRef.document.body.clientWidth) == 'number')
{
  // Gecko 1.0 (Netscape 7) and Internet Explorer 5+
  width = windowRef.document.body.clientWidth;  
}
else if (typeof(windowRef.innerWidth) == 'number')
{
  // Navigator 4.x, Netscape 6.x, CompuServe 7 and Opera
  width = windowRef.innerWidth;
}]]></pre>
    </blockquote>

    <h3>Example 2 - object based feature detection</h3>

    <h4>Cross Browser Support</h4>
    <p>
      This example also illustrates the use of <em>feature detection</em>
      and shows the complications that can arise from the non standard
      implementations in other browsers.
    </p>

    <blockquote>
      <pre><![CDATA[
function moveElement(id, x, y)
{
  // move the element with id to x,y
  // where x,y are the horizontal
  // and vertical position in pixels

  var elm = null;
  if (document.getElementById)
  {
    // browser implements part of W3C DOM HTML
    // Gecko, Internet Explorer 5+, Opera 5+
    elm = document.getElementById(id);
  }
  else if (document.all)
  {
    // Internet Explorer 4 or Opera with IE user agent
    elm = document.all[id];
  }
  else if (document.layers)
  {
    // Navigator 4
    elm = document.layers[id];
  }

  if (!elm)
  {
    // browser not supported or element not found
  }
  else if (elm.style)
  {
    // browser implements part of W3C DOM Style
    // Gecko, Internet Explorer 4+, Opera 5+

    if (typeof(elm.style.left) == 'number')
    {
      // Opera 5/6 do not implement the standard correctly
      // and assume that elm.style.left and similar properties
      // are numbers.
      elm.style.left = x;
      elm.style.top  = y;
    }
    else
    {
      // Gecko/Internet Explorer 4+
      // W3C DOM Style states that elm.style.left is a string
      // containing the length followed by the unit. e.g. 10px
      // Gecko will allow you to omit the unit only in Quirks 
      // mode. 
      // Gecko REQUIRES the unit when operating in Standards
      // mode.
      elm.style.left = x + 'px';
      elm.style.top  = y + 'px';
    }
  }
  else if (typeof(elm.left) == 'number')
  {
    // Navigator 4
    elm.left = x;
    elm.top  = y;
  }
}]]></pre>
    </blockquote>

    <h4>Standards only</h4>
    <p>
      Consider how simple this function is if you 
      code it according to the W3C standards. 
    </p>

    <blockquote>
      <pre><![CDATA[
function moveElement(id, x, y)
{
  // move the element with id to x,y
  // where x,y are the horizontal
  // and vertical position in pixels

  var elm = document.getElementById(id);

  if (elm)
  {
    elm.style.left = x + 'px';
    elm.style.top  = y + 'px';
  }
}]]></pre>
    </blockquote>

    <p>
      Ask yourself this: "Is supporting <em>non-standard</em> 
      browsers worth the development and maintenance costs?"
    </p>

    <h3>Example 3 - Detecting specific Netscape Gecko branches</h3>

    <blockquote>
      <pre><![CDATA[
// return the rv value of a Gecko user agent
// as a floating point number. 
// returns -1 for non-gecko browsers, 
//          0 for pre Netscape 6.1/Gecko 0.9.1 browsers
//          number > 0 where each portion of 
//          the rv value delimited by . 
//          will be treated as value out of 100.
//          e.g. for rv: 3.12.42, 
//          getGeckoRv() returns 3.1242
//          
function geckoGetRv()
{
  if (navigator.product != 'Gecko')
  {
    return -1;
  }
  var rvValue = 0;
  var ua      = navigator.userAgent.toLowerCase();
  var rvStart = ua.indexOf('rv:');
  var rvEnd   = ua.indexOf(')', rvStart);
  var rv      = ua.substring(rvStart+3, rvEnd);
  var rvParts = rv.split('.');
  var exp     = 1;

  for (var i = 0; i < rvParts.length; i++)
  {
    var val = parseInt(rvParts[i]);
    rvValue += val / exp;
    exp *= 100;
  }

  return rvValue;
}


// determine if the browser is any Netscape Gecko
// branch >= 1.0.1 or Netscape 6.2.x/CompuServe 7 
// built after August 1, 2002

var rv    = geckoGetRv();
var found = false;

if (rv >= 0)
{
  // Gecko browser
  if (navigator.productSub > '20020801')
  {
    if (rv >= 1.0001)
    {
      found = true;
    }
    else if (rv >= 0.0904 && rv < 0.0905)
    {
      if (navigator.vendor == 'Netscape6' || navigator.vendor == 'CS 2000 7.0')
      {
        found = true;
      }
    }
  }
}
]]></pre>
    </blockquote>

    <h3>Example 4 - <a href="http://www.iht.com/">The International Herald-Tribune</a></h3>
    <p>
      This <a href="http://www.iht.com/">site</a>
      illustrates many of the techniques described in this article.
      They use <em>downlevel</em>
      pages for less capable browsers combined with <em>object based feature</em>
      detection to produce a compelling and interesting site.
    </p>

    <h3>Examples From DevEdge</h3>
    <ul>
      <li><a href="/xbProjects-docs-srce/xbDOM/">xbDOM</a></li>
      <li><a href="/xbProjects-docs-srce/xbMarquee/">xbMarquee</a></li>
      <li><a href="/xbProjects-docs-srce/xbPositionableElement/">xbPositionableElement</a></li>
      <li><a href="/xbProjects-docs-srce/xbAnimatedElement/">xbAnimatedElement</a></li>
    </ul>

    <p><a href="#top">top</a></p>

    <h2><a name="conclusion">Conclusion</a></h2>

    <p>
      As we have seen in this article, the browser detection story is still quite 
      complicated due to differences between the modern browsers such as 
      Netscape Gecko/Internet Explorer 6 and the older or non-standard browsers 
      such as Netscape Navigator 4. 
      You may say to yourself "If only all browsers were as good as Netscape Gecko 
      and Internet Explorer 6, then my job would be so much easier!". 
    </p>
    <p>
      I would like to leave you with this thought. In the past, users did not have
      the choice of picking a browser which implemented the standards however today
      they do have a choice. There is no compelling reason 
      for anyone in the world to continue to use a browser which does not support 
      the standards. However, as long as web developers continue to code work arounds
      for these older browsers, users will not have a compelling reason to 
      upgrade. By ceasing to support older browsers, you can provide a reason for users
      to upgrade. This will benefit not only them, but yourself as well. Supporting
      <strong>only standards based browsers</strong> can reduce development and maintanance
      costs as well as increase the <em>dynamic and compelling content</em> which will
      attract visitors and increase your revenue. The choice is yours... <strong>Decide to 
        support the standards today!</strong>
    </p>

    <p><a href="#top">top</a></p>

    <h2><a name="links">Links</a></h2>

    <ul>
      <li><a href="/viewsource/2002/gecko-compatibility/">Netscape Gecko Compatibility Handbook</a></li>
      <li><a href="http://www.mozilla.org/build/revised-user-agent-strings.html">Mozilla user-agent strings</a></li>
      <li><a href="/library/xref/2002/client-data/property-data-navigator.html">Object Cross Reference - <code>navigator</code></a></li>
      <li><a href="/viewsource/2002/gecko-useragent-strings/">Netscape Gecko User Agent Strings</a></li>
      <li><a href="http://www.faqs.org/rfcs/rfc1945.html">RFC 1945 - Hypertext Transfer Protocol -- HTTP 1.0</a></li>
      <li><a href="http://www.faqs.org/rfcs/rfc2068.html">RFC 2068 - Hypertext Transfer Protocol -- HTTP 1.1</a></li>
      <li><a href="/library/xref/2002/client-data/"> Client Object Cross References </a></li>
      <li><a href="http://www.mozilla.org/docs/web-developer/quirks/">Quirks Mode in Mozilla</a></li>
      <li><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnie60/html/cssenhancements.asp">CSS Enhancements in Internet Explorer 6</a></li>
      <li><a href="http://www.w3.org/">W3C</a>
        <ul>
          <li><a href="http://www.w3.org/MarkUp/">W3C Markup</a></li>
          <li><a href="http://www.w3.org/TR/">W3C Technical Recommendations</a>
              <ul>
                <li><a href="http://www.w3.org/TR/html401/">W3C HTML 4.01</a></li>
                <li><a href="http://www.w3.org/TR/REC-CSS1/">W3C CSS 1</a></li>
                <li><a href="http://www.w3.org/TR/REC-CSS2/">W3C CSS 2</a></li>
                <li><a href="http://www.w3.org/TR/DOM-Level-2-Core/">W3C DOM Core 2</a></li>
                <li><a href="http://www.w3.org/TR/DOM-Level-2-HTML/">W3C DOM HTML 2</a></li>
                <li><a href="http://www.w3.org/TR/DOM-Level-2-Style/">W3C DOM Style 2</a></li>
              </ul>
          </li>
        </ul>
      </li>
    </ul>
  </nde:content>

</nde:article>
