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: