Progressive enhancement is a technique of adding features to your web site based on the capabilities of the browser.  When a browser doesn’t meet specs, it simply doesn’t get the feature.  The key is to make sure your site has base functionality good enough for everyone.  There are some examples of this people use frequently that are quite simple, like using CSS3 conditional selectors to identify certain types of links and add file icons to them.

Simple things like that are no big deal, a few bytes of data either used or not.  In most cases, if the CSS3 selectors aren’t supported yet, the browser just ignores them, no big  deal.  But, there are times where it might not be optimal to include code.  For instance, maybe you want to include a PNG fixing script for IE6, but you don’t want FireFox or IE7 users to have to worry about it.  Or maybe you have some jQuery tools that simply don’t display right in IE (Internet Explorer) (shall we count how many time we’ll use this to keep IE from screwing up?).  For the record, you can do browser detection with jQuery too.  However, it turns out there’s a very simple way that we can do this using a couple lines of Velocity in dotCMS as well, which gets you around everything JavaScript related and allows you to get about as specific as you want.

The tool we’re going to focus on is $request.getHeader. getHeader() is a method of the HttpServletRequest servlet, and it allows you to call by name the many different header parameters sent when the browser requests a page from the server and return them as a string. The one that you’ll want to focus on in this case is “User-Agent.” By identifying the user agent a visitor is sending, you can send custom code to each browser. The process for this is very simple:

#if(!$request.getHeader("User-Agent").contains("MSIE 6.0"))
  <div> ...whatever you want can go here... </div>

It’s really that simple. In that example, we’ve said “anything that doesn’t identify itself as Internet Explorer 6 gets this code.” Remember, the ! before the $ is the same as saying NOT. If you wanted IE6 to see certain code (like a PNG fix JavaScript file), you’d just take the ! out and anything that isn’t IE6 won’t get it. If you feel the need to get REALLY clever, you can always refer to a list of user agents to make sure you’re identifying things right.  Or you can also go further and make decisions based on other headers, like the referer.

Just to give you an example of the data you’re retrieving, plug $request.getHeader("User-Agent") into a page.  You should get something like this:

<strong>User Agent:</strong> $request.getHeader("User-Agent")

User Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv: Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5

That’s the result from my system running Firefox 3.0.5 on Ubuntu.  A Windows system running IE6 would return something along the lines of Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.1). Knowing that allows you to construct the .contains("MSIE 6.0") portion, which you can see matching the portion of the IE6 user agent after the compatibility flag.

So, that’s how you can do browser independent, JavaScriptless browser detection, and let the server decide how the page should get served to the user.  You can use this to also serve different code to things like search engine crawlers.  There are a million uses.  If you wanted to be REALLY mean, you could even black out your site to users of certain browsers, if you don’t want to support them.  Give it a try and see what different uses you can find for customizing your web pages for different browser uses.

2 Responses to “Smart Progressive Enhancement with dotCMS”

  1. Brad Rice says:

    This is cool. Is there a way to grab the IP address of the requesting computer?

  2. Michael Fienen says:

    Sure, just use the $request.remoteAddr variable, and that will give you the visitor’s IP.

Leave a Reply