Tips and Tricks

Internet Development Index

As with any type of programming, writing bug-free, efficient scripts that meet your expectations takes a bit of work. The following sections provide some tips and hints to make that work take less time and go more smoothly.

Checking the Internet Explorer Version Number

You should always check for the type and version of the client browser, so that your content degrades gracefully if the client browser does not support features on your Web site.

The easiest way to identify a browser and its characteristics (browser code name, version number, language, etc.) in script is through the Dynamic HTML (DHTML)?A HREF="objects/obj_navigator.html">navigator object. You can also access this object and its properties in C++ applications through the IOmNavigator interface.

The userAgent property of the navigator object returns a string that includes the browser and browser version. The following example Microsoft® JScript® function runs on most browsers and returns the version number for any Microsoft Internet Explorer browser and zero for all other browsers.

function msieversion()
// Return Microsoft Internet Explorer (major) version number, or 0 for others.
// This function works by finding the "MSIE " string and extracting the version number
// following the space, up to the semicolon
{
var ua = window.navigator.userAgent
var msie = ua.indexOf ( "MSIE " )
if ( msie > 0 )        // is Microsoft Internet Explorer; return version number
return parseFloat ( ua.substring ( msie+5, ua.indexOf ( ";", msie ) ) )
else
return 0    // is other browser
}

When checking browser version numbers, always check for version numbers greater than or equal to a target version. In this way, your Web site will be be compatible with future versions of the browser. For example, if you have designed your content for the latest version of Internet Explorer, use that version number as a minimum version number.

Note  Browsers often have several releases of a browser version. For example, 4.01, 5.0, 5.5 and 6.0b are all different versions of Internet Explorer. The 'b' in 6.0b represents a beta version of Internet Explorer 6.

As of Internet Explorer 5, conditional comments are available as an alternative technique for detecting browser versions. Conditional comments have the advantage of not using a script block, which means that it is not always necessary to use scripting and DHTML when working with conditional comments. When no scripting is used in a Web page, no scripting engine needs to be loaded. Conditional comments are processed during the downloading and parsing phase, so only the content that is targeted for the browser loading the Web page is actually downloaded. Conditional comments can be combined freely with other browser detection techniques. For more information, see About Conditional Comments.

Canceling a Button Click

The following HTML example shows a common scripting mistake related to event handling and canceling the default action.

<HTML>
<HEAD><TITLE>Canceling the Default Action</TITLE>
<SCRIPT LANGUAGE="JScript">
function askConfirm()
{ return window.confirm ("Choose OK to follow hyperlink, Cancel to
not.")
}
</SCRIPT>
<BODYonload="b3.onclick=askConfirm">
<!-- Try links with different hookups - should be canceled by "Cancel" to confirm dialog. -->
<BR><A NAME=b1 HREF="http://www.microsoft.com" onclick="askConfirm()">1 Without return (won't work)</A>
<BR><A NAME=b2 HREF="http://www.microsoft.com" onclick="return askConfirm()">2 With return (works)</A>
<BR><A NAME=b3 HREF="http://www.microsoft.com">3 Function pointer (works)</A>
</BODY>
</HTML>

The first a element in this example does not work properly. Without the return in the onclick JScript expression, the browser interprets the function expression, throws away the resulting value, and leaves the default action unaffected.

The other a elements correctly bind the return value to the event, hence the default action can be canceled when false is returned.

Preventing a Document From Being Cached

You can prevent a document from being cached by adding the following meta tag to the document.

<META HTTP-EQUIV="Expires" CONTENT="0">

Preventing the document from being cached ensures that a fresh copy of the document will always be retrieved from the site, even during the user's current session, regardless of how the user has set the browser's caching options. This is useful if the content of the document changes frequently.

Using Objects

Objects are Microsoft® ActiveX® Controls or other similar components that provide custom capabilities and services for HTML documents. You can add a control to your document using the object element, and you can gain access to the capabilities and services of the control using its properties and methods from script.

When using objects, be aware that DHTML extends every object by providing these additional properties:

alignclassidcode
codeBasecodeType
dataform
heightname
objectrecordset
typewidth

If a control has properties with these same names, you will not be able to access the properties unless you preface the name with the object property. For example, assume that an ActiveX control is added to the document using the following:

<OBJECT ID="MyControl" HEIGHT=100 WIDTH=200 CLASSID="clsid: ... ">
</PARAM NAME="width" VALUE="400">
</OBJECT>

In this example, there are two widths: an extended property set within the object element, and a property belonging to the control that is set using the param element. To access these from script, you use the following code.

alert(MyControl.width);   // this is Dynamic HTML's property; displays "200"
alert(MyControl.object.width);  // this is the object's property; displays "400"

Replacing Custom Controls with DHTML

DHTML provides everything you need to generate animated effects without resorting to custom controls. For example, consider the following script, which is a replacement for the Path control.

var tickDuration;
tickDuration = 50;
var activeObjectCount;
var activeObjects;
var itemDeactivated;
var tickGeneration;
activeObjects = new Array();
activeObjectCount = 0;
timerRefcount = 0;
itemDeactivated = false;
tickGeneration = 0;
function initializePath(e) {
e.waypointX = new Array();
e.waypointY = new Array();
e.duration = new Array();
}
function addWaypoint(e, number, x, y, duration) {
e.waypointX[number] = x;
e.waypointY[number] = y;
e.duration[number] = duration;
}
function compact() {
var i, n, c;
n = new Array();
c = 0;
itemDeactivated = false;
for (i=0; i<activeObjectCount; i++)  {
if (activeObjects[i].active == true) {
n[c] = activeObjects[i];
c++;
}
}
activeObjects = n;
activeObjectCount = c;
}
function tick(generation) {
if (generation < tickGeneration) {
// alert("Error "+generation);
return;
}
//alert("tick: "+generation);
if (itemDeactivated)
compact();
if (activeObjectCount == 0) {
return;
}
else {
for (i=0; i<activeObjectCount; i++) {
moveElement(activeObjects[i]);
}
window.setTimeout("tick("+generation+");", tickDuration);
}
}
function start(e) {
if (itemDeactivated)
compact();
activeObjects[activeObjectCount] = e;
activeObjectCount++;
if (activeObjectCount == 1) {
tickGeneration++;
tick(tickGeneration);
}
}
function runWaypoint(e, startPoint, endPoint) {
var startX, startY, endX, endY, duration;
if (e.waypointX == null)
return;
startX = e.waypointX[startPoint];
startY = e.waypointY[startPoint];
endX = e.waypointX[endPoint];
endY = e.waypointY[endPoint];
duration = e.duration[endPoint];
e.ticks = duration / tickDuration;
e.endPoint = endPoint;
e.active = true;
e.currTick = 0;
e.dx = (endX - startX) / e.ticks;
e.dy = (endY - startY) / e.ticks;
e.style.posLeft = startX;
e.style.posTop = startY;
start(e);
}
function moveElement(e) {
e.style.posLeft += e.dx;
e.style.posTop += e.dy;
e.currTick++;
if (e.currTick > e.ticks) {
e.active = false;
itemDeactivated = true;
if (e.onpathcomplete != null) {
window.pathElement = e;
e.onpathcomplete()
}
}
}

To use this script in your document, do the following:

  1. Load the script using the src attribute of the script element.
  2. Initialize the paths using the initializePath function.
  3. Set the way points using the addWaypoint function.
  4. Set the path-complete handlers using the runWaypoint function.

The following sample document shows how this works.

<html>
<body>
<div id=Item1 style="position: absolute; left: 0; top: 0;">Item1</div>
<div id=Item2 style="position: absolute; left: 0; top: 0;">Item2</div>
<div id=Item3 style="position: absolute; left: 0; top: 0;">Item3</div>
<div id=Item4 style="position: absolute; left: 0; top: 0;">Item4</div>
<div id=Item5 style="position: absolute; left: 0; top: 0;">Item5</div>
<div id=Item6 style="position: absolute; left: 0; top: 0;">Item6</div>
<input type=button value="Start" onclick="runWaypoint(Item1, 0, 1); runWaypoint(Item2, 0, 1);">
<div id=Debug>Generation</div>
<script src="htmlpath.js">
</script>
<script>
// need to call initializePath on all objects that will be moved with this mechanism
initializePath(Item1);
initializePath(Item2);
initializePath(Item3);
initializePath(Item4);
initializePath(Item5);
initializePath(Item6);
// the 0th waypoint is the initial position for waypoint #1
// syntax is item, waypoint, endx, endy, duration in msecs
addWaypoint(Item1, 0, 0, 0, 0);
addWaypoint(Item1, 1, 200, 200, 2000);
addWaypoint(Item2, 0, 100, 100, 0);
addWaypoint(Item2, 1, 400, 100, 4000);
addWaypoint(Item3, 0, 400, 400, 0);
addWaypoint(Item3, 1, 200, 100, 1000);
addWaypoint(Item4, 0, 0, 0, 0);
addWaypoint(Item4, 1, 200, 200, 2000);
addWaypoint(Item5, 0, 100, 100, 0);
addWaypoint(Item5, 1, 400, 100, 4000);
addWaypoint(Item6, 0, 400, 400, 0);
addWaypoint(Item6, 1, 200, 100, 1000);
function endfunction() {
// syntax for runWaypoint is Item, start point, end point
runWaypoint(Item3, 0, 1);
runWaypoint(Item4, 0, 1);
runWaypoint(Item5, 0, 1);
runWaypoint(Item6, 0, 1);
}
function endfunction2() {
runWaypoint(Item1, 0, 1);
}
Item1.onpathcomplete = endfunction;
Item6.onpathcomplete = endfunction2;
</script>
</body>
</html>
This feature requires Microsoft® Internet Explorer 4.0 or later. Click the following icon to install the latest version. Then reload this page to view the sample.