This section provides a brief introduction to some DHTML effects that are possible. The examples focus on maximum cross-browser and backward compatibility, and use the layerlib.js presented in the section “Building a Cross-Browser DHTML Library.” While the examples should work under the common browsers from the 4.x generation on, because of bugs with clipping regions, you may find some of the examples do not work under some versions of Opera or other browsers.
With positioned layers, you can hide and show regions of the screen at any time. Imagine putting colored regions on top of content and progressively making the regions smaller. Doing this would reveal the content in an interesting manner, similar to a PowerPoint presentation. While you can create such transitions easily with filters under Internet Explorer, this effect should work in most modern browsers. The code for this effect is shown here, and its rendering is shown in Figure 15-6.
<<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">> <<html xmlns="http://www.w3.org/1999/xhtml">> <<head>> <<title>>Wipe Out!<</title>> <<meta http-equiv="content-type" content="text/html; charset=utf-8" />> <<style type="text/css">> <<!-- .intro { position:absolute; left:0px; top:0px; layer-background-color:red; background-color:red; border:0.1px solid red; z-index:10; } #message { position: absolute; top: 50%; width: 100%; text-align: center; font-size: 48pt; color: green; z-index: 1;} -->> <</style>> <<script type="text/javascript" src="layerlib.js">><</script>> <</head>> <<body>> <<div id="leftLayer" class="intro">> <</div>> <<div id="rightLayer" class="intro">> <</div>> <<div id="message">>JavaScript Fun<</div>> <<script type="text/javascript">> <<!-- var speed = 20; /* Calculate screen dimensions */ if (window.innerWidth) theWindowWidth = window.innerWidth; else if ((document.body) && (document.body.clientWidth)) theWindowWidth = document.body.clientWidth; if (window.innerHeight) theWindowHeight = window.innerHeight; else if ((document.body) && (document.body.clientHeight)) theWindowHeight = document.body.clientHeight; /* nasty hack to deal with doctype switch in IE */ if (document.documentElement && document.documentElement.clientHeight && document.documentElement.clientWidth) { theWindowHeight = document.documentElement.clientHeight; theWindowWidth = document.documentElement.clientWidth; } /* cover the screen with the layers */ setWidth('leftLayer', parseInt(theWindowWidth/2)); setHeight('leftLayer', theWindowHeight); setX('leftLayer',0); setWidth('rightLayer', parseInt(theWindowWidth/2)); setHeight('rightLayer', theWindowHeight); setX('rightLayer', parseInt(theWindowWidth/2)); clipright = 0; clipleft = parseInt(theWindowWidth/2); function openIt() { window.scrollTo(0,0); clipright+=speed; setClip('rightLayer',0,theWindowWidth, theWindowHeight,clipright); clipleft-=speed; setClip('leftLayer',0,clipleft,theWindowHeight,0); if (clipleft<<0) clearInterval(stopIt) } function doTransition() { stopIt=setInterval("openIt()",100); } window.onload = doTransition; //-->> <</script>> <</body>> <</html>>
A point of interest in this example is the setInterval(code, time) method of the Window object, which is used to perform the animation. The basic use of this method, which is fully presented in Chapter 12, is to execute some specified string code every time milliseconds. To turn off the interval, you clear its handle, so that if you have anInterval = setInterval ("alert('hi')", 1000), you would use clearInterval(anInterval) to turn off the annoying alert.
We saw earlier in the chapter how a rollover effect might reveal a region on the screen containing a text description. This form of targeted rollover, often called a dynamic scope note, can be implemented without CSS by using images, but with the DOM- and CSS-positioned items we may have a much more elegant solution. As an example, look at the code for simple scope notes presented here.
<<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">> <<html xmlns="http://www.w3.org/1999/xhtml">> <<head>> <<title>>CSS Rollover Message<</title>> <<meta http-equiv="content-type" content="text/html; charset=utf-8" />> <<style type="text/css">> <<!-- #buttons {position: absolute; top: 10px; background-color: yellow;width: 20%;} #description {position: absolute;top: 10px;left: 40%;} -->> <</style>> <<script src="layerlib.js" type="text/javascript">><</script>> <</head>> <<body>> <<div id="buttons">> <<a href="about.html" onmouseover="setContents('description', 'Discover the history and management behind the Democompany.');" onmouseout="setContents('description', ' ');">>About<</a>> <<br />><<br />> <<a href="products.html" onmouseover="setContents('description', 'If you like our domes, you\'ll love our robots!');" onmouseout="setContents('description', ' ');">>Products<</a>> <</div>> <<div id="description">> <</div>> <</body>> <</html>>
Note |
Without the non-breaking space ( ), you may find that the description layer will collapse under HTML and thus not instantiate the required object for manipulation via JavaScript. |
The last example in this chapter presents some very simple animation using JavaScript. We move an object up and down to particular coordinates as well as left to right. The basic idea will be to figure out the current position of an object and then move the object incrementally around the screen using the setX() and setY() functions in our layer library. First, we add simple getX(layerName) and getY(layerName) functions that return the coordinates of the layer passed. These routines are shown here.
/* return the X-coordinate of the layer named layerName */ function getX(layerName) { var theLayer = getElement(layerName); if (layerobject) return(parseInt(theLayer.left)); else return(parseInt(theLayer.style.left)); } /* return the y-coordinate of layer named layerName */ function getY(layerName) { var theLayer = getElement(layerName); if (layerobject) return(parseInt(theLayer.top)); else return(parseInt(theLayer.style.top)); }
Next, we need to define some variables to indicate how many pixels to move at a time (step) and how quickly to run animation frames (framespeed).
/* set animation speed and step */ var step = 3; var framespeed = 35;
We should also define some boundaries for our moving object so it doesn’t crash into our form controls that will control the animated object.
/* set animation boundaries */ var maxtop = 100; var maxleft = 100; var maxbottom = 400; var maxright = 600;
Next, we’ll add routines to move the object in the appropriate direction until it reaches the boundary. The basic idea will be to probe the current coordinate of the object, and if it isn’t yet at the boundary, move it a bit closer by either adding or subtracting the value of step and then setting a timer to fire in a few milliseconds to continue the movement. The function right() is an example of this. In this case, it moves a region called “ufo” until the right boundary defined by maxright is reached.
function right() { currentX = getX('ufo'); if (currentX << maxright) { currentX+=step; setX('ufo',currentX); move=setTimeout("right()",(1000/framespeed)); } else clearTimeout(move); }
The complete script is shown here with a rendering in Figure 15-7.
<<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">> <<html xmlns="http://www.w3.org/1999/xhtml">> <<head>> <<title>>UFO!<</title>> <<meta http-equiv="content-type" content="text/html; charset=utf-8" />> <<script src="layerlib.js" type="text/javascript">><</script>> <<script type="text/javascript">> <<!-- /* return the x-coordinate of the layer named layername */ function getX(layername) { var theLayer = getElement(layername); if (layerobject) return(parseInt(theLayer.left)); else return(parseInt(theLayer.style.left)); } /* return the y-coordinate of layer named layerName */ function getY(layerName) { var theLayer = getElement(layerName); if (layerobject) return(parseInt(theLayer.top)); else return(parseInt(theLayer.style.top)); } /* set animation speed and step */ var step = 3; var framespeed = 35; /* set animation boundaries */ var maxtop = 100; var maxleft = 100; var maxbottom = 400; var maxright = 600; /* move up until boundary */ function up() { var currentY = getY('ufo'); if (currentY >> maxtop) { currentY-=step; setY('ufo',currentY); move=setTimeout("up()",(1000/framespeed)); } else clearTimeout(move); } /* move down until boundary */ function down() { var currentY = getY('ufo'); if (currentY << maxbottom) { currentY+=step; setY('ufo',currentY); move=setTimeout("down()",(1000/framespeed)); } else clearTimeout(move); } /* move left until boundary */ function left() { var currentX = getX('ufo'); if (currentX >> maxleft) { currentX-=step; setX('ufo',currentX); move=setTimeout("left()",(1000/framespeed)); } else clearTimeout(move); } /* move right until boundary */ function right() { var currentX = getX('ufo'); if (currentX << maxright) { currentX+=step; setX('ufo',currentX); move=setTimeout("right()",(1000/framespeed)); } else clearTimeout(move); } //-->> <</script>> <</head>> <<body background="space_tile.gif">> <<div id="ufo" style="position:absolute; left:200px; top:200px; width:241px; height:178px; z-index:1;">> <<img src="space_ufo.gif" width="148" height="141" alt="ufo!" />> <</div>> <<form action="#" method="get">> <<input type="button" value="up" onclick="up();" />> <<input type="button" value="down" onclick="down();" />> <<input type="button" value="left" onclick="left();" />> <<input type="button" value="right" onclick="right();" />> <<input type="button" value="stop" onclick="clearTimeout(move);" />> <</form>> <</body>> <</html>>
We could modify the animation example to multiple regions and to move across a predefined path. Yet the question is, should we?