One basic problem with using large images in slide shows is that you can't trust or use the timing events associated with images. The "completed" and "onLoad" events claim that the image has finished loading when it has barely begun to load. Therefore, your presentation assumes the user has seen the image long enough and begins to load the next image before the previous one has even reached the screen. Worse yet, changing the image source of an image already displayed, a common technique to run a slide show, generates an onLoad event by itself and can lock up a Netscape browser if you're trapping the image onLoad event to determine if an image has finished loading.
Therefore, although you've seen many good-looking slide shows that display small images on a single page, this isn't a robust method to use if you suspect that your images might take nearly as long to load as the time you have planned to pause between images. This tip uses a different event to detect that the page is ready: the body onLoad event. An added benefit of using this event instead of timing images directly is that you can flip and time entire pages, not just images. Let's flip pages first.
</script> </head> <frameset rows="65, *" name="one"> <frame src="tour2.cfm" name="two" border="0" frameborder="no" scrolling="no"> <frame src="tour3.cfm" name="three" border="0" frameborder="no"> </frameset> <body> . </body>
<body onLoad=
"javascript:setTimeout('parent.two.document.playback.ok.value=1',1000);">
<hr><div align="center">If you resize your window, press [>] to resume.
Change speed with [--] or [++] if needed.
The presentation runs automatically.</div><hr>
<script language="javascript"> // Initialization... Show = 0; // array position of current item Nr = 0; // will become number of items Source = new Array; Caption = new Array; Pause = new Array; Gear = 500; // user-changeable multiplier for pause By = 0; // direction of play Waiter = 0; // timer to wait with
// Slides... // To add/change/rearrange/remove slides, // just add/change/rearrange/remove blocks below. Nr = Nr + 1; Source[Nr] = "../slide/one.cfm"; Caption[Nr] = "First."; Pause[Nr] = 15; Nr = Nr + 1; Source[Nr] = "../slide/two.cfm"; Caption[Nr] = "Second."; Pause[Nr] = 5; Nr = Nr + 1; Source[Nr] = "../slide/three.cfm"; Caption[Nr] = "Third."; Pause[Nr] = 10;
When it's ok to change items, it considers the direction in which it should change, resets the form variable to indicate that the desired page hasn't loaded, and then loads the page. See changeItem().
After initiating the page load, the code waits for the item's pause length times the Gear size, then tries to advance to the next page. See loadPage().
The user will increase and decrease the gear size by changing it with a Shift value. See changeGear().
The native javascript setTimeout() function gives the code an odd quality at times. This function is not a "wait" statement. It doesn't stop the current program flow. Instead, it spawns a new process when the timeout is reached. Therefore, if any process manages to initiate the setTimeout() function before it's done, multiple copies of the timer would be spawned. If the Auto button started the timer itself, pressing Auto multiple times would cause multiple timers to run simultaneously; the user would have to press the Manual button several times to stop all of them. To keep this from happening, when the user presses the Auto button, the code deliberately stops the current copy of the timer before starting a new copy and advancing to the next item. For this reason, pressing the Manual button once stops the timer. See doRun() and stopItems().
// Controls...
function loadPage() {
parent.three.document.location = Source[Show];
}
function changeItem(Direction) {
Show = Show+Direction;
if (Show < 1) Show = Nr;
if (Show == Nr + 1) Show = 1;
document.playback.ok.value = 0;
loadPage();
document.playback.Docent.value = Caption[Show];
}
function stopItems() {
clearTimeout(Waiter);
clearTimeout(Runner);
clearTimeout(Waiter);
}
function playItems(By) {
if (document.playback.ok.value == 1) {
changeItem(By);
Runner = setTimeout('playItems(1)',Gear*Pause[Show]);
return true;
}
else {
Waiter = setTimeout('playItems(1)',100);
}
}
function doRun() {
stopItems();
playItems(1);
}
function changeGear(Shift) {
Gear = Gear+Shift;
if (Gear < 100) Gear = 100;
if (Gear > 2800) Gear = 2800;
}
// Begin in Play mode
Runner = setTimeout('playItems(1)',5000);
</script>
Because there is no caption for the control description page, a non-breaking space serves as the initial caption. Wrap in a "virtual" rather than in a "physical" fashion; because, line breaks in the caption text don't need to be preserved.
<style>
a {text-decoration:none;color:black;font-weight:bold;}
a:hover {color:green;}
</style>
<table align="center" cellpadding="0">
<tr>
<form name="playback">
<td bgcolor="#00AACC">
<a href="../public/home.cfm">Home</a>
<input type="button" value="- -"
onClick='changeGear(+50)';><input type="button"
value="Auto" onClick='doRun();'><input
type="button" value="++" onClick='changeGear(-70)';>
<input type="button" value="<"
onClick='changeItem(-1);'><input type="button"
value="Manual" onClick='stopItems();'><input
type="button" value=">" onClick='changeItem(1);'>
</td>
<input type="hidden" name="ok" value="0">
<td>
<textarea name="Docent" wrap="virtual" cols="60" rows="2">
</textarea>
</td>
</form>
</tr>
</td></tr></table>
<body onLoad=
"javascript:setTimeout('parent.two.document.playback.ok.value=1',500);">
Let this code be one.cfm. It's a sample for the demonstration...
<body onLoad=
"javascript:setTimeout('parent.two.document.playback.ok.value=1',500);">
This is page one.
Let this code be two.cfm...
<body onLoad=
"javascript:setTimeout('parent.two.document.playback.ok.value=1',500);">
<hr>
This is page two.
<hr>
Let this code be three.cfm...
<body onLoad=
"javascript:setTimeout('parent.two.document.playback.ok.value=1',500);">
This is page 3.
Here is a unique identifier generated by ColdFusion:
<cfoutput>#createUUID()#</cfoutput>.
In slide.htm, replace "tour2.cfm" with "slide2.htm" and "tour3.cfm" with "slide3.htm".
In slide2.htm, replace function loadPage() with this code. Instead of displaying an existing page, it writes a page "on the fly" that consists of a body tag and an image tag. The body tag contains the magic code you manually added to the beginning of the pages you displayed during the tour. The image tag contains the appropriate source for the image from your item list.
function loadPage() {
Content =
"<body onLoad=javascript:setTimeout('parent.two.document.playback.ok.value=1',500);>";
Content = Content + "<img src=" + Source[Show] + ">";
parent.three.document.write(Content);
parent.three.document.close();
}
Now fix the item list so it contains references to images instead of to pages. You can name them anything and put them anywhere. Here's a sample:
Nr = Nr + 1; Source[Nr] = "../slide/one.gif"; Caption[Nr] = "First."; Pause[Nr] = 15; Nr = Nr + 1; Source[Nr] = "../slide/two.gif"; Caption[Nr] = "Second."; Pause[Nr] = 5; Nr = Nr + 1; Source[Nr] = "../slide/three.gif"; Caption[Nr] = "Third."; Pause[Nr] = 10;
Don't do anything to slide3.htm; it's fine as it stands. In fact, you're done. Browse slide.htm to see this work. At this point, the slide show doesn't even need a Web server!
Try creating more complex pages with the document.write function used in the slide show. If the page you're "replacing" ends in .cfm, you may be able to code some ColdFusion functions and tags into the replacement page "on the fly". Tell us what you've learned. Apply these techniques in good health. =Marty=