reptile7's JavaScript blog
Saturday, December 12, 2009
 
Dealing with Isolated Proprietary Features, Part 2
Blog Entry #165

We continue today our discussion of HTML Goodies' "Internal Browser Test" tutorial and its scripts.

A bit more on the intbrowtest_example_code.html script

Real DHTML

For the script's first two if statements, Joe chose an MSIE 4/3 'dividing line' because [v]ersion 4.0 is...when DHTML came to IE. Joe could have driven his point home by implementing the title and cursor effects dynamically, which as an added benefit would have allowed a clean separation between the (at-the-time) proprietary code and the nonproprietary code:

<script type="text/javascript">
function realDHTML( ) {
if (navigator.appName == "Microsoft Internet Explorer" && parseFloat(navigator.appVersion) >= 4.0) {
document.anchors["link1"].title = "Gotta Go To Goodies";
document.anchors["link1"].style.cursor = "help"; } }
</script>

<body onload="realDHTML( );">
<p><a name="link1" href="http://www.htmlgoodies.com/">HTML Goodies</a></p>
<!-- Netscape 4.x supports the id attribute for the object and layer/ilayer elements but for no other elements. -->


Feature detection

We have previously on occasion used feature detection as opposed to navigator object property returns to test for a specific browser or group of browsers. At least on the Netscape side, feature detection can be profitably applied to the intbrowtest_example_code.html script. The script's only-Netscape-4.x-supports-the-layer-element problem would be smoothly solved by replacing the
if (navigator.appName == "Netscape" && navigator.appVersion >= "4.0") test
with an
if (document.layers) test.

On the MSIE side, we could similarly replace the
if (navigator.appName == "Microsoft Internet Explorer" && navigator.appVersion >= "4.0") test
with an
if (document.all) test,
although there's no real advantage in doing so (OK, it's easier to type). Moreover, the document.all condition would additionally flag users of Opera, which like MSIE supports the all( ) collection; however, the original "Microsoft Internet Explorer"/"4.0" test will also return true for some Opera users. If for whatever reason you did want to exclude Opera users, you could do so with an
if (document.all && !window.opera) test.
The window.opera expression references an Opera-specific opera object, which is documented here. For non-Opera browsers, window.opera returns undefined, which is converted to false (and thus !window.opera evaluates to true) in a Boolean context.

if...else if...else

You may have noticed that the script's
// This code is for IE less than v4,
// This code is for Navigator v4 or less, and
// This code is for neither IE nor Navigator
sections all execute the same command, e.g.:

if (navigator.appName != "Microsoft Internet Explorer" && navigator.appName != "Netscape")
{ document.write("<a href='http://www.htmlgoodies.com/'>HTML Goodies</a>"); }


It would be more efficient to roll these parts of the script into a single catch-all, which could in turn serve as the final else alternative in an if...else if...else structure:
if (navigator.appName == "Microsoft Internet Explorer" && parseFloat(navigator.appVersion) >= 4.0)
{ title/cursor commands }
else if (document.layers)
{ layer element/object code }
else document.write("<a href='http://www.htmlgoodies.com/'>HTML Goodies</a>");
(An aside: formulating the Script Tips #13-15 browser sniffer as an else if 'cascade' would eliminate the need for the r tracking variable.)

The home page follies

MSIE 5.0 for Windows was released about two months before "Internal Browser Test" was written, and Joe concludes the tutorial with an example that wanders into the MSIE 5+ for Windows-specific world of DHTML behaviors, an interface that extend[s] the current Windows Internet Explorer object model. The tutorial's "Setting your page as Home Page: IE5.0 only!" section offers code that attempts to use Microsoft's behavior property to change the user's browser home page to the current page; this code is conditionalized via an if statement that specifically flags users of MSIE 5.0 for Windows. Here's what we've got:

if (navigator.appName == "Microsoft Internet Explorer" && navigator.appVersion == "4.0 (compatible; MSIE 5.0b2; Windows 95)") {
document.write("<style><!-- .homepage { behavior: url(#_IE_); } --></style>");
document.write("<u><span style='color:blue;cursor:hand;' class='homepage' onclick='this.setHomePage(window.location);'>Make this your home page</span></u>"); }

else document.write("Make this page your Home Page!");


The if block's second document.write( ) command writes to the page a Make this your home page span element string marked up to mimic a link: blue text, underlined, cursor set to hand.
HTML 4 deprecated the u element; text-decoration:underline; is its CSS equivalent.
hand is a nonstandard Microsoft cursor value; pointer is the corresponding standard value.

The span element is equipped with a class='homepage' attribute that ties it to the if block's first document.write( ) command, which assigns a behavior:url(#_IE_); style to the span element. The MSDN Library's behavior property page is here; checking over the page's Possible Values section, it is clear that the url(#_IE_) value is off target: specifically, url(#_IE_) should match the id attribute value of an object element that represents a [b]inary implementation of a DHTML behavior (cf. the last example on the behavior page), and there's nothing like that going on in this script.

The right behavior

Not quite a year later Joe posted a "So You Want ME As Your Homepage, Huh?" tutorial that sets the correct behavior for changing the user's home page:

<span style="cursor:hand;color:blue;text-decoration:underline;" onclick="this.style.behavior='url(#default#homepage)'; this.setHomePage('http://www.htmlgoodies.com/');">Click Here to Make HTML Goodies Your Home Page</span>

Upon clicking the Click Here to Make HTML Goodies Your Home Page span text, the this.style.behavior='url(#default#homepage)'; assignment registers with the span element/object the Windows Internet Explorer #default homePage* behavior/object, which is documented by Microsoft here. All that remains is to call the homePage setHomePage( ) method, whose parameter, http://www.htmlgoodies.com/ in this case, specifies the URL of the user's new home page.

(*homePage or homepage? Case mistakes can stop a script dead in its tracks! On the MSDN Library's "homePage Behavior" page, the Syntax box says "homePage" but it's "homepage" in the Example. Maybe it doesn't matter - All CSS syntax is case-insensitive within the ASCII range (i.e., [a-z] and [A-Z] are equivalent), except for parts that are not under the control of CSS, the W3C stipulates - but as a non-Windows user, I am unfortunately not able to sort this out for you.)

Try me, catch me

Let's get back to the "Internal Browser Test" home page code for just a moment. As shown above, the code's if container only allows MSIE 5.0 for Windows users 'through the gate', so to speak. But what about users of more recent MSIE versions, huh?
(In the name of completeness:
According to Microsoft, MSIE 5.0 for Unix also supports the homePage behavior/object. However, like MSIE for the Mac, MSIE for Unix was discontinued long ago, and I would think that MSIE for Unix users would have moved on to other browsers by now, but if any of them are still out there, how would we accommodate those guys?)

Moreover, the behavior property is part of a proposed addition to CSS: what if the W3C were to standardize this code, leading to its widespread support by non-MSIE browsers? Ideally, we would like to enable general access to the code for current and future browsers that might support it, but at the same time ensure that the code 'fails gracefully' for browsers that don't support it. Gratifyingly, this is achievable via a try...catch statement, a common programming mechanism for handling errors and which was added to JavaScript in JavaScript 1.4.

I won't go through the try...catch statement in detail in this post - for a comprehensive treatment of the try...catch statement, see the try...catch page in the Mozilla JavaScript Reference - but will below with explanatory commentary show you how to apply it to the "So You Want ME As Your Homepage, Huh?" home page code.

We begin by separating the nonproprietary code from the proprietary code. Here's the HTML/CSS base we will use:

#span1 {
color: blue;
cursor: pointer;
text-decoration: underline; }

<span id="span1">Click Here to Make HTML Goodies Your Home Page</span>


As for the proprietary code, we will relocate the two homePage behavior commands to a newHomePage( ) script function. We coassociate the newHomePage( ) function, click events, and the span element/object in the normal way:

var mySpan = document.getElementById("span1");
mySpan.onclick = newHomePage;

function newHomePage( ) { ... }


We're ready to fill in the newHomePage( ) function body. We're not going to execute the homePage commands willy-nilly; rather, we will try to execute them by putting them in the try block of a try...catch statement:

try {
mySpan.style.behavior = "url(#default#homePage)";
mySpan.setHomePage("http://www.htmlgoodies.com/"); }
catch (err) {
window.alert("This feature requires MSIE 5+ for Windows."); }


If a given browser can execute the homePage commands in the try block, it will do so, and then move to whatever follows the catch block(s), if present. However, the setHomePage( ) method call throws an error with the browsers on my computer; for these browsers, an Error object is passed to the catch block and given the catch parameter, err in this case, as an identifier. You can choose or not choose to probe properties of the Error object in the catch block - e.g., err.message returns mySpan.setHomePage is not a function when using Firefox - my preference is to simply display a This feature requires MSIE 5+ for Windows. message.

For those of you willing to try all of this out, click on the link-like text in the div below:


<title>Setting a New Home Page</title>

Click Here to Make HTML Goodies Your Home Page


If you're an MSIE 5+ for Windows user, as you are statistically likely to be, then a dialog box should pop up prompting you to confirm the new home page value before it is set for your browser; after clicking or whatever, go to the browser's Preferences pane to verify that you have a new home page and to reset your previous home page (unless you really do want to change your home page to http://www.htmlgoodies.com/).

We'll briefly discuss the second "JavaScript Browser Test Scripts" tutorial, "Post by Screen Size", in the following entry.

reptile7

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)