Detecting The Browser Version
Having looked at the kinds of features we might decide to
support or to avoid, we'll consider the other half of the equation. How do we
know which browser we're dealing with when we do get a visitor? If we decide to
build pages that are specially tailored for particular browsers, we need to be
able to identify the browser when it hits our site with a request for a page.
This can be done in several ways, and you've seen some
examples of the techniques in earlier chapters. We'll summarize them here, then
explore how ASP can make the job a whole lot easier. In the next chapter, we'll
be creating a version of our simple frameset site (first seen in Chapter 2)
that automatically provides a different set of more advanced features to each
suitably equipped browser.
Summary Of Browser Detection Techniques
We can detect which browser we are dealing with on the
client itself using scripting, or on the server with either scripting or a
special Active Server component. We'll start with the client-side techniques.
These allow us to detect the version, and hence the capabilities of the
browser, inside a page that we provide.
Browser Detection With Client-Side Script
All browsers that support scripting also provide a standard
set of objects as part of their Document Object Model (DOM). In fact, this is a
bit of a misnomer, because the objects also provide information about the
browser itself, and not just the document (or page) it is displaying. The
object we're interested in is the navigator object – probably named as
such because the first browsers were often referred to as 'navigators', and
Netscape adopted this as their product name.
The navigator object, a sub-object of the
main top-level window object, provides the three useful properties userAgent,
appName
and appVersion.
The userAgent
property contains the string that completely identifies the browser, and is
sent to the server in the HTTP headers with each page request it makes. The appName
and appVersion
properties are available only in client-side script, and contain the
manufacturer's name and the browser version in a more readable format.
Reading The Navigator Object Properties
The following code, which is included in the samples
available from our Web site at http://www.wrox.com/,
writes the values of the three properties into the page using client-side
script when you load it. It also provides some information about your chosen
browser, by analyzing the property values. We've highlighted the script code to
make it easier to see what's going on:
<HTML>
<HEAD><TITLE>Detecting the
browser type</TITLE></HEAD>
<BODY>
<H3>Details of your browser</H3>
<TABLE>
<TR>
<TD ALIGN="RIGHT">navigator.userAgent:</TD>
<TD><B>
<SCRIPT LANGUAGE="JavaScript">
<!--
document.write(navigator.userAgent)
//-->
</SCRIPT></B>
</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">navigator.appName:</TD>
<TD><B>
<SCRIPT LANGUAGE="JavaScript">
<!--
document.write(navigator.appName)
//-->
</SCRIPT></B>
</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">navigator.appVersion:</TD>
<TD><B>
<SCRIPT LANGUAGE="JavaScript">
<!--
document.write(navigator.appVersion)
//-->
</SCRIPT></B>
</TD>
</TR>
</TABLE><P>
<SCRIPT
LANGUAGE="JavaScript">
<!--
if
(navigator.appName.indexOf('Netscape') != -1) {
document.write('To upgrade your browser go to ' +
'<A HREF="http://home.netscape.com/download/">' +
'http://home.netscape.com/download/<\/A><\/P>');
if (navigator.appVersion.substr(0, 1) > 3)
document.write('You can use Netscape Dynamic HTML');
}
if
(navigator.appName.indexOf('Microsoft') != -1) {
document.write('To upgrade your browser go to ' +
'<A HREF="http://www.microsoft.com/ie/">' +
'http://www.microsoft.com/ie/<\/A><\/P>');
if (navigator.appVersion.substr(0, 1) > 3)
document.write('You can use Microsoft Dynamic HTML');
}
//-->
</SCRIPT>
<NOSCRIPT>
Sorry, your browser doesn't support client-side scripting,
so
it can't display the details about your browser.
</NOSCRIPT>
</BODY>
</HTML>
Note that, where we have closing HTML tags, we
include a backslash character in the string we write to the document. For
example, '..<\/A><\/P>'.
According to the W3C standards, a combination of a forward slash character
followed immediately by an alphabetic character indicates the end of a <SCRIPT>
section. So, if we are trying to write any closing HTML tags with document.write,
we must declare at least part of the 'illegal' combination within the string as
being a character literal. In JavaScript we can do this with a backslash, here
placed before the forward slash. In VBScript, we usually replace the forward
slash with Chr(47).
However, most browsers don't follow the W3C rule, and will only accept </SCRIPT>
as a closing script tag. But it's wise to play safe...
Here are the results with Internet Explorer 5.0 and Navigator
4.61:

Note that IE5 returns '4.0' as the version
number at the start of the appVersion property, because this is
the version of Mozilla
that it is compatible with. To get the actual IE version number, we need to parse
the string for the version number after the 'MSIE'
product identifier.

So, we can quite easily detect the browser type using script
running in the page on the client. We'll see how we might use this later on.
However, it's not always as straightforward as you might imagine. For example,
here's what the page looks like when you open it in Opera 3.6:

Whoops, a wrong hyperlink for the upgrade. But whose fault
is this? Look at the value of the navigator.appName property – 'Netscape'!
Server-Side With ASP
Obviously we can only use client-side script when the
browser supports this. If you look back at the end of the code we used earlier,
you'll see that we tried to trap this problem using a <NOSCRIPT>
section, which contains a note to the viewer explaining why they can't see any
browser details. An easy way to prevent this occurring is to do the work on the
server instead of on the client. There are two basic ways of achieving this,
either by analyzing the HTTP USER-AGENT value sent from the
browser, or with a special component that can do the hard work for us.
Using The HTTP USER-AGENT Value
When we get a page request from a browser or user agent, it
should provide a value for the USER-AGENT string within the HTTP
headers. We saw this when we looked at the contents of the Request.ServerVariables
collection in Chapter 2. We can quite easily look at the string, and decide the
browser type. The ASP code below does just that, and provides a similar result
with Internet Explorer and Navigator as our previous client-side page (we can't
get at the appName
and appVersion
properties, which are only available to script running on the browser, so these
are omitted):
<%@ LANGUAGE=VBSCRIPT %>
<% strUA =
Request.ServerVariables("HTTP_USER_AGENT") %>
...
<TABLE>
<TR>
<TD
ALIGN="RIGHT">navigator.userAgent:</TD>
<TD><B><% = strUA %></B>
</TD>
</TR>
</TABLE>
<P>
<%
QUOT = Chr(34)
If InStr(strUA, "MSIE") Then 'it's
a Microsoft Browser
Response.Write "To upgrade your browser go to " _
& "<A HREF=" & QUOT &
"http://www.microsoft.com/ie/" _
& QUOT &
">http://www.microsoft.com/ie/</A></P>"
intVersion = CInt(Mid(strUA, InStr(strUA, "MSIE") + 5, 1))
If
intVersion > 3 Then
Response.Write "You can use Microsoft Dynamic HTML"
End
If
Else
If
InStr(strUA, "Mozilla") Then
'it's a Netscape-compatible
browser
If InStr(strUA, "compatible;") = 0 _
And InStr(strUA, "Opera") = 0 Then 'it's probably a Netscape
browser
Response.Write "Your browser is probably Navigator. You can "
_
& "download the latest verion of Navigator from " _
& "<A HREF=" & QUOT &
"http://home.netscape.com/download/" _
& QUOT &
">http://home.netscape.com/download/</A></P>"
intVersion = CInt(Mid(strUA, InStr(strUA,
"/") + 1, 1))
If intVersion > 3 Then
Response.Write "You can probably use Netscape Dynamic HTML"
End If
Else 'not Netscape, so we'll allow the user to search on the Web for it
If InStr(strUA, "Opera") Then
'Opera 3.60 doesn't include
'compatible' in UA string
strProduct = Trim(Mid(strUA, InStr(strUA, ")") + 1))
Else
'use the part after the 'compatible;'
keyword
strProduct = Mid(strUA, Instr(strUA, "compatible;") + 11)
strProduct = Trim(Left(strProduct, Instr(strProduct, ";") -
1))
End If
strSearchURL =
"http://www.altavista.digital.com/cgi-bin/query?q=" _
& Server.URLEncode(strProduct & "
web browser")
Response.Write "Your browser is
Navigator-compatible. You can " _
& "search for the manufacturer using a search engine, such as
" _
& "<A HREF=" & QUOT & strSearchURL & QUOT
& ">" & strSearchURL _
& "</A></P>"
End
If
End
If
End If
%>
...
Detecting Internet Explorer
In the code above, for Internet
Explorer, we just look for the sub-string MSIE in the user agent string. We
get the version from the part of the string after MSIE:
If InStr(strUA, "MSIE") Then 'it's
a Microsoft Browser
...
intVersion = CInt(Mid(strUA, InStr(strUA,
"MSIE") + 5, 1))
Here's the result of the ASP browser detection code viewed
in IE 5:

Detecting Netscape Navigator
However, Navigator is a bit more of a problem. As
Netscape believe that they invented browsers (in fact Mosaic was the first
one), they don't think they should have to put their product name into the user
agent string. They begin it with Mozilla
(the development code-name for Navigator), but everyone else does as well,
because early server-side code routines expected this and the newcomers to the
browser manufacturing game didn't want their browser rejected by the server.
The end result is that we can really only tell if it's not Netscape Navigator – if we find the
sub-string compatible
within the user agent string we know it's something else. If we don't find it,
we can generally assume that it's Navigator – though it might not always be.
For example, version 3.60 of the Opera browser fails to include the word compatible in the user agent
string, so we have to test for this separately.
And if it really is Navigator, the real version number
follows the first slash character in the string (directly after the word Mozilla). Here's the relevant
section from the ASP code we used earlier:
If
InStr(strUA, "compatible;") = 0 _
And
InStr(strUA, "Opera") = 0 Then
'its probably a Netscape browser
...
intVersion = CInt(Mid(strUA, InStr(strUA, "/") + 1, 1))
Here's the result in Navigator 4.61:
