The majority of the day thus far has been devoted to understanding the technologies behind DHTML and how to use them separately. It's time to start creating real DHTML web pages. As I've mentioned, the real challenge is creating DHTML so that you reach the largest possible audience within certain practical limitations. I say practical because true DHTML isn't possible in any web browser that doesn't implement scripting or style sheets, and impractical in those that suffer from partial or poor implementations. In other words, using DHTML, you'll never be able to reach 100% of your potential audience. There are a number of different approaches you can take when creating Dynamic HTML, given that not all browsers are created equal when it comes to support for JavaScript and cascading style sheets. The first option is to create separate pages for separate browsers, or separate style sheets and JavaScript files for separate browsers. This requires a lot of duplicated effort, and can be extremely painful. The second option is to try to write your code so that it will work with as many browsers as possible, no matter how poor their support for standards is. This is often what happens when Netscape Navigator 4 is in the mix, or even older versions of Internet Explorer. The version 4 generation of browsers was the furthest from standards compliance browsers have ever been. It was common for pages to include massive amounts of extra code that figured out which browser was viewing the page and accounting for how its DHTML model works. This technique is still relatively common, but I'm not going to cover it today. The third option is to create your pages so that they work in browsers that implement the current web standards, and degrade gracefully in older browsers. Given the small percentage of users who still use older browsers, unless you're specifically required to support them, just making sure that your pages aren't broken in them should be enough. Sniffing for BrowsersAt one time, the most common technique for creating cross-browser DHTML was detecting the user's web browser (commonly called sniffing). After you determined which browser the user was using, you could simply execute the code tailored to that browser. The problem is that there are many browsers out on the market, and many versions of each one. For example, there are two or three versions of both Netscape and Internet Explorer in fairly common usage even today. As you might imagine, accounting for all the available browsers and keeping your scripts up-to-date to accommodate new browsers is a daunting task. Here's a relatively simple browser sniffer that detects only Netscape Navigator 4 and Microsoft Internet Explorer 4 and up. It doesn't distinguish between Netscape 7 and Netscape 4, which are completely different, and doesn't even take browsers like Opera (or other common browsers) into consideration. You may run into code like the sample that follows, but you shouldn't use such code yourself. The following listing creates variables that parse the appropriate objects to return true or false values for the final variables: is_nav4up and is_ie4up. // Trimmed down browser sniffer that // detects Navigator 4+ and IE 4+. // Reference is_nav4up and is_ie4up in other // portions of the script. var agt = navigator.userAgent.toLowerCase(); var is_major = parseInt(navigator.appVersion); var is_minor = parseFloat(navigator.appVersion); var is_nav = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1) && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1) && (agt.indexOf('Webtv')==-1)); var is_nav4up = (is_nav && (is_major >= 4)); var is_ie = (agt.indexOf("msie") != -1); var is_ie4up = (is_ie && (is_major >= 4)); To check for the existence of Netscape Navigator 4 and Microsoft Internet Explorer 4 and later versions, use the following script: if (is_nav4up) { do something } if (is_ie4up) { do something else } You'll see that later as you perform some more scripting. The overall browser sniffer function exists solely to return the proper variables to you so that you can check in other portions of your script. By itself, it won't actually take any action. The following example shows the browser sniffer in action. The body element of the web page calls the doSniff function, which in turn, creates a variable called sniff and assigns it a string value to display, depending on the browser version it detects. Input <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/transitional.dtd"> <html> <head> <title>Browser Sniffing</title> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <script language="javascript" type="text/javascript"> <!-- Hide JavaScript // Trimmed down browser sniffer that // detects Navigator 4+ and IE 4+. // Reference is_nav4up and is_ie4up in other // portions of the script. var agt = navigator.userAgent.toLowerCase(); var is_major = parseInt(navigator.appVersion); var is_minor = parseFloat(navigator.appVersion); var is_nav = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1) && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1) && (agt.indexOf('Webtv')==-1)); var is_nav4up = (is_nav && (is_major >= 4)); var is_ie = (agt.indexOf("msie") != -1); var is_ie4up = (is_ie && (is_major >= 4)); // Function to display the browser version function doSniff() { var sniff if (is_nav4up == true) { sniff = "Netscape Navigator 4+" } if (is_ie4up == true) { sniff = "Microsoft Internet Explorer 4+" } alert(sniff); } // end hide --> </script> </head> <body onload="doSniff()"> </body> </html> Figure 15.2 shows the result in Mozilla Firefox. Output Figure 15.2. Sniffing for the web browser detects the browser version.
Detecting CapabilitiesThere are several big problems with relying on browser detection to make sure that your scripts work across multiple browsers. When new browsers are released, you have to go back through all your scripts that include browser detection and update them to account for the new browsers. Another problem is that if a browser you didn't account for supports the features included on your page, you might be denying access to people for no reason. Rather than trying to determine the user's browser and then running the JavaScript code for it, it makes more sense to test whether the browser supports the specific feature you're going to use. Let's try an analogy: You've rented a car and you want to turn on the air conditioner. The problem is that you're not sure whether the car even has an air conditioner. To find this out, you could get the year, make, and model of the car and then look it up in a service manual. This is what browser detection is. On the other hand, you could just look at the dashboard of the car and see whether it has an air conditioner. This is how capability detection works. This might seem like an oversimplification, but that's really all there is to it. Before you call a particular piece of code, you just have to test whether the browser supports the objects associated with the code you're calling. Back in Lesson 13, I gave you a sneak preview of this technique. Before I attempted to perform an image rollover, I tested whether the browser supported the document.images objectif it didn't, I knew that the rollover wouldn't work and moved on. Testing for the Existence of ObjectsLet me explain how this works in more detail. JavaScript is an object-oriented language, so you generally deal with objects that both contain data and have methods that can be called to perform various tasks. You can easily test for the existence of objects and, if they exist, call methods of those objects to perform the tasks you want to accomplish. |