Creating Web pages with basic HTML is a fairly straightforward task, but adding active content with multiple frames is a different matter altogether. The secret is just to take things one step at a time, building content in stages. In this chapter, you'll learn how easy it can be to create exciting, complex Web pages.
This chapter presents a simple, frames-based Web site. You'll have a home page, composed of frames, that displays various other HTML pages within the frames. It contains some useful navigation elements to let users jump from one URL to another within a consistent browsing environment. To accomplish this, you'll develop a home page that uses two frames that remain static, along with a third that changes URLs to display information requested by the user. Figure 12.1 shows the basic concept for the frames.
Figure 12.1. The conceptualization of the frames layout for the sample home page.
During the conceptualization phase, I decided that the top frame, or banner frame, would be completely static and non-resizable, and that this frame would contain bitmaps used for navigation among topics. I also decided that the left frame, or contents pane, would be resizable and would display a more in-depth selection of topics in a textual format. This design leaves the frame to the right of the resizable frame border for use as a topic viewing area, where the various HTML files can be displayed.
You will learn how to integrate several HTML files into a master frames page that implements the concept shown in Figure 12.1. The frames page acts as a container for other HTML files and as the home page for the small sample Web site that you'll build throughout the course of this chapter. The files you'll start out with are:
As you saw, the frames page for your sample Web site is to be made up of three frames. These frames are defined by two framesets, one horizontal and one vertical. A frameset is simply a container for frames that allows you to specify their size and orientation. Each frame in a frameset has a Universal Resource Locator (URL). This means that you can click a link in one frame and view the corresponding data in another frame. Each frame in the sample Web site you build in this chapter displays a separate HTML file. The banner and contents frames remain constant, but the topic frame displays various HTML documents.
A frame can be scrolling or nonscrolling (scrolling is the default), and resizable or static (resizable is the default). The following is the syntax for a basic frame:
<frame src=[URL] name=[FrameName] scrolling=[yes/no] [noresize]>
As mentioned earlier, two framesets are used for this page, one nested inside the other. The first frameset uses the rows attribute, which means it's a horizontal frameset composed of rows of frames. For the frame sizing in this preliminary stage, the frame in the top row is set to 10% of the browser window's height, and the bottom frame is set to the remaining 90% of the browser window, like this:
<frameset rows="10%,90%">
The second frameset uses the cols attribute, which means it's a vertical frameset composed of columns of frames. The initial sizing for the frame in the left column is set to 25% of the browser window's width, and the bottom frame is set to the remaining 75% of the browser window, like this:
<frameset cols="25%,75%">
As new pages are developed for display within the various frames, the spacing used for the framesets will change (as the needs of the page evolve). The initial frameset values of rows="10%,90%" and cols="25%,75%" are just estimates at this stage.
The file INDEXFRM.HTM contains all of the code for the basic frameset used in the same Web site. The code for this is straightforward, as you can see in Listing 12.1.
Listing 12.1. The initial HTML source code for a basic nested frameset page with three frames (INDEXFRM.HTM).
<html> <head> <title>Sample Web Site With Multiple Frames</title> </head> <!-- Set up the frames for the home page --> <frameset rows="10%,90%"> <frame src="banner.htm" name="banner" scrolling="no" noresize> <frameset cols="25%,75%"> <frame src="toc.htm" name="contents"> <frame src="welcome.htm" name="topic"> </frameset> <!-- If the browser doesn't support frames, display this --> <noframes> <BODY> <p> This site uses frames, but your browser doesn't support them. </p> </body> </noframes> </frameset> </html>
In this case, the frame named "banner" is listed right after the first frameset statement, which means it inhabits the 10% spot (the top). The 90% spot (the bottom) is taken by the nested frameset, with the frame named "contents" taking the 25% spot (the left), and the frame named "topic" taking the 75% spot (the right). Make sense? Take a look at the resulting sample home page shown in Figure 12.2, in its first incarnation.
The files used to generate the version of the sample home page seen in Figure 12.2 can be found on the companion CD-ROM in the SOURCE\CHAP14\STAGE1 directory.
Figure 12.2. The first stage of the sample home page.
Placeholder HTML files must be created in order for the frames to display as in Figure 12.2. The source files for the URLs used within the frames are quite simple at this point, although you'll develop each into a more complex version as you go along. The source code for each of the basic frame URLs is listed in the next sections.
The banner frame will eventually contain a sample logo and a series of images that act as links for graphical navigation. The source for the basic banner page, BANNER.HTM, is shown in Listing 12.2.
Listing 12.2. The initial HTML source code for the basic banner frame (BANNER.HTM).
<HTML> <HEAD> <TITLE>Banner</TITLE> </HEAD> <BODY> <H2>Banner Frame</H2> </BODY> </HTML>
The contents frame will contain a bitmap and some text links to the topics to display in the topic frame. The source for the basic contents page, TOC.HTM, is shown in Listing 12.3.
Listing 12.3. The initial HTML source code for the basic contents frame (TOC.HTM).
<HTML> <HEAD> <TITLE>Contents</TITLE> </HEAD> <BODY> <H2>Contents Frame</H2> </BODY> </HTML>
The topic frame will display various different HTML files, depending on what the user chooses in the contents frame or in the banner frame's navigation bar. The source for the placeholder topic file WELCOME.HTM is shown in Listing 12.4. Later you'll add two more pages, TOPIC1.HTM, and TOPIC2.HTM. These three pages will always appear in the topic frame.
Listing 12.4. The initial HTML source code for the basic welcome page (WELCOME.HTM).
<HTML> <HEAD> <TITLE>Welcome</TITLE> </HEAD> <BODY> <H2>Welcome Page</H2> </BODY> </HTML>
As you can see, all of these pages are very similar at this point, being little more than skeletal HTML files generated by the ActiveX Control Pad (see Chapter 11, "Using ActiveX Control Pad," for more information). Next, you'll develop each page to show how the entire home page comes together with frames.
Now you can turn your attention to developing the banner. A sample logo image is needed, along with other images for navigating to the three topic URLs. Images for your pages can be created with a variety of tools. For these examples, I'll use the Persistence of Vision ray tracer (POVRAY) to create some beautiful images, along with Corel's Photo-Paint 6 for image manipulation and conversion.
Be sure to visit the POVRAY Web site at http:\\www.povray.org to truly appreciate the incredibly beautiful and realistic images that can be generated with this completely free software! The new POVRAY 3.0 has been released for many platforms including: MS-DOS, Windows 3.1x with Win32s, Windows 95, Windows NT, Linux, UNIX, Macintosh, and SunOS.
The idea for the banner is to have a black background with a sample logo on the left, and three shiny stone spheres next to the logo, one after another, on the right. The stones are the navigation images corresponding to the Welcome page, the Topic 1 page, and the Topic 2 page.
The Sample logo was created completely in Photo-Paint 6, using a plasma cloud texture fill for the background. Because the background for the banner frame is to be black, I blended the plasma fill gradually from solid black on the right using the Photo-Paint airbrush tool. Next, I added the word "Sample" (pretty creative, eh?) with the text tool. Finally, for a bit of drama, I added a slight lens flare with the lens flare tool. I centered the lens flare on the "p" in "Sample " and saved the image as SAMPLE.GIF.
The other banner images were created using POVRAY to generate the wonderful stone spheres, followed by Photo-Paint to add the text for each. The images were then saved as STONE1.GIF, STONE2.GIF, and STONE3.GIF, and all four banner images are shown, in Photo-Paint, in Figure 12.3.
Figure 12.3. The images used in the Banner page, manipulated in Corel Photo-Paint 6.
Now that you have your images, continue by positioning them in the page. You want to have them aligned at the left and top, and the page background should be black. To accomplish this, the following code is used in the <BODY> tag for the page:
<BODY BGCOLOR="#0" TOPMARGIN="0" LEFTMARGIN="0">
The background color #0 is, of course, black, and the TOPMARGIN and LEFTMARGIN attributes are set to zero so the images will snuggle up close to the left and top of the frame in Internet Explorer (Netscape Navigator is a bit different, as you'll see). Next, the images are listed one after another, with no line or paragraph break codes, like this:
<img src="../gif/sample.gif" width=142 height=46> <img src="../gif/stone1.gif" width=100 height=46 BORDER=0> <img src="../gif/stone2.gif" width=100 height=46 BORDER=0> <img src="../gif/stone3.gif" width=100 height=46 BORDER=0>
<A HREF="topic1.htm" TARGET="topic" ALT="Topic 1">
This line references TOPIC1.HTM as the link, and the Topic frame as the target. It's that simple!
The target frame specified in the TARGET attribute is case-sensitive! The link to the target frame won't work if the case of the characters isn't exactly the same as specified in the page that defines the frame names (in this case, INDEXFRM.HTM).
There is already a basic Welcome page (WELCOME.HTM), but the Topic 1 and Topic 2 pages don't yet exist. By simply copying the Welcome page twice, naming the files TOPIC1.HTM and TOPIC2.HTM, and changing the title and heading to Topic 1 and Topic 2, respectively, you have all the pages the sample site will use.
Listing 12.5 shows the final banner page source code. In this final incarnation, the code supports links to TOPIC1.HTM, TOPIC1.HTM, and TOPIC1.HTM from the sphere images (STONE1.GIF, STONE2.GIF, AND STONE3.GIF, respectively).
Listing 12.5. The final HTML source code for the Banner page (BANNER.HTM).
<html> <head> <title>Banner</title> </head> <BODY BGCOLOR="#0" TOPMARGIN="0" LEFTMARGIN="0"> <img src="../gif/sample.gif" width=142 height=46> <A HREF="welcome.htm" TARGET="topic" ALT="Welcome"> <img src="../gif/stone1.gif" width=100 height=46 BORDER=0></a> <A HREF="topic1.htm" TARGET="topic" ALT="Topic 1"> <img src="../gif/stone2.gif" width=100 height=46 BORDER=0></a> <A HREF="topic2.htm" TARGET="topic" ALT="Topic 2"> <img src="../gif/stone3.gif" width=100 height=46 BORDER=0></a> </body> </html>
Now that the Banner page is complete, you can move on, right? Not so fast! The banner frame marginwidth and marginheight attributes must be set to zero in INDEXFRM.HTM, so the images snuggle up against the left and top of a frame when viewed in Netscape Navigator, like this:
<frame src="banner.htm" name="banner" scrolling="no" noresize marginwidth="0" marginheight="0">
I originally set up the frames to use percentages in the INDEXFRM.HTM file, and as the browser window resizes, so do the frames. Because the SAMPLE.GIF image uses bright colors along its bottom edge, an unacceptably sharp delineation occurs between the black background and the image's bottom edge when the browser window is maximized. To prevent this, you need to set the banner frame to a specific height: that of the images themselves.
The images are all 46 pixels high, as you can see from the height attributes in the code. After viewing the INDEXFRM.HTM file in both Netscape Navigator and Internet Explorer, I decided on a height of 48 pixels, taking into account the width of the frame borders, which in Internet Explorer can be adjusted, like this:
<frameset rows="48,*" frameborder="1" framespacing="1">
The statement rows="48,*" tells the browser to make the top frame of the frameset exactly 48 pixels high, and to use the rest of the window for the bottom frame. These changes give you the final version of the INDEXFRM.HTM file, shown in Listing 12.6.
Listing 12.6. The final HTML source code for the frames home page (INDEXFRM.HTM).
<html> <head> <title>Sample Web Site With Multiple Frames</title> </head> <!-- Set up the frames for the home page --> <frameset rows="48,*" frameborder="1" framespacing="1"> <frame src="banner.htm" name="banner" scrolling="no" noresize marginwidth="0" marginheight="0"> <frameset cols="33%,69%"> <frame src="toc.htm" name="contents"> <frame src="welcome.htm" name="topic"> </frameset> <!-- If the browser doesn't support frames, display this --> <noframes> <BODY> <p> This web site uses frames, but your browser doesn't support them. </p> </body> </noframes> </frameset> </html>
Figure 12.4 shows the result of this phase of completion, with the Banner page displayed in the banner frame. That's a start, but there's still a long way to go to have a truly active and exciting Web site! Continue on to the Contents page.
You can find the files used to generate the version of the sample home page seen in Figure 12.4 on the companion CD-ROM in the SOURCE\CHAP14\STAGE2 directory.
Figure 12.4. The sample home page with the Banner page completed.
The Contents page is useful because it allows you to get detailed about the contents of your Web site. Because this sample site only contains a few pages, the Contents page is pretty simple. Of course, you can use the ideas presented here to create much larger Contents pages. At this point, you need to know more about the content of pages that will appear in the topics frame.
The Contents page will, of course, supply links to the Welcome, Topic 1, and Topic 2 pages, but it will also provide links to two anchors, or bookmarks, that you'll put in the Topic 2 page later in this chapter (in Stage 6). These anchors will be named, in the Topic 2 HTML source, as anchor1 and anchor2. Because you know this ahead of time, you can include links to the anchors on the Contents page now.
To include a link to an anchor, you use this syntax:
<A HREF="#AnchorName">
To include a link to a frame, you use this syntax:
<A HREF="filename.htm" TARGET="FrameName">
To include a link to an anchor that will appear in a frame, you use this syntax:
<A HREF="filename.htm#AnchorName" TARGET="FrameName">
Using these simple types of links, you can control the content within the topics frame from the contents frame. Listing 12.7 gives the complete HTML code for the Contents page (TOC.HTM).
Listing 12.7. The final HTML source code for the Contents page (TOC.HTM).
<HTML> <HEAD> <TITLE>Contents</TITLE> </HEAD> <BODY bgcolor="#FFFFF"> <H2><I>Contents</I></H2> <HR> <font face="Arial" size="2"> <!-- Welcome --> <A HREF="welcome.htm" TARGET="topic" ALT="[Welcome]"> <IMG SRC="../gif/bullet2.gif" ALT="*" border="0"> <b>Welcome</b> </a> <p> <!-- Topic 1 --> <A HREF="topic1.htm" TARGET="topic" ALT="[Topic 1]"> <IMG SRC="../gif/bullet2.gif" ALT="*" border="0"> <b>Topic 1: A Java Applet</b> </a> <p> <!-- Topic 2 --> <A HREF="topic2.htm" TARGET="topic" ALT="[Topic 2]"> <IMG SRC="../gif/bullet2.gif" ALT="*" border="0"> <b>Topic 2: The Poetry Page</b> </a> <br> <blockquote> <li><A HREF="topic2.htm#anchor1" TARGET="topic" ALT="[Poem of the week]"> Poem of the Week<br> </a></i> <li><A HREF="topic2.htm#anchor2" TARGET="topic" ALT="[Runner up poem]"> Runner-Up </a></li> </blockquote> <p> </font> </BODY> </HTML>
Figure 12.5 shows the result of this phase of completion, with the Contents page displayed in the contents frame. Now you can move on to the Welcome page.
The files used to generate the version of the sample home page seen in Figure 12.5 can be found on the companion CD-ROM in the SOURCE\CHAP14\STAGE3 directory.
Figure 12.5. The sample home page with the Contents page completed.
The Welcome page simply greets users and wows them with an ActiveX label control that expands and contracts as it changes colors. At the same time, background percussion music begins to play, and the famous Internet Explorer logo animated GIF spins around. Take a look at how all of this is accomplished.
The most prominent feature of this page is the animated label control. This animation is accomplished with VBScript and two ActiveX timer controls. To get the label control on the page, I used the ActiveX Control Pad, discussed in Chapter 11. After the control was in place, I added some VBScript to the page to control the label and the timers.
The label control is named IeLabel1 and the two timer controls are named IETimer1 and IETimer2, respectively. One timer controls the size of the label, and the other timer controls the color. RGB color components are determined randomly by this VBScript function:
Function GetRandomColor(nMax) GetRandomColor = Int((nMax + 1) * Rnd) End Function
The IETimer1_Timer() event controls the color changes, like this:
' ' Flashing text colors ' Sub IeTimer1_Timer() crRed = GetRandomColor(256) crGreen = GetRandomColor(256) crBlue = GetRandomColor(256) IeLabel1.ForeColor = RGB(crRed, crGreen, crBlue) end sub
The size of the label is determined by the VBScript nSize variable, like this:
' ' Resizing label ' Sub IeTimer2_Timer() IeLabel1.FontSize = nSize if (nSize < 12) then nSize = 12 bLarger = true elseif (nSize > 24) then nSize = 24 bLarger = false end if if (bLarger) then nSize = nsize + 1 else nSize = nsize - 1 end if end sub
Listing 12.8 gives the complete code listing for the Welcome page. Note the use of the <BGSOUND SRC> HTML tag, which plays a sound file when the page is displayed. In this case, the file is in MIDI format (although standard WAV files can be used as well). The background sound is specified like this:
<BGSOUND SRC="../media/percfun.mid">
This plays some percussive sounds that build in intensity the longer the page is displayed.
Listing 12.8. The final HTML source for the Welcome page (WELCOME.HTM).
<HTML> <HEAD> <TITLE>Welcome!</TITLE> <META Name="keywords" Content="ActiveX Programming Unleashed"> </HEAD> <BODY BACKGROUND="../gif/tan.gif"> <H2><i>Welcome!</i></H2> <HR> <P> <IMG SRC="../gif/underc.gif" ALT="Under Construction!"> Welcome! This is just a sample Web site, but it utilizes a lot of cool technologies including: ActiveX, Java, JavaScript, VBScript, and more! It also uses state-of-the-art computer graphics, including ray-traced animation. <p> Browse what's here so far, and be sure to come back regularly! And remember: <p> <!--### Active "ActiveX Rocks!!" ###--> <center> <!-- MS Label Control --> <OBJECT ID="IeLabel1" WIDTH=423 HEIGHT=49 CLASSID="CLSID:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" CODEBASE="http://www.microsoft.com/activex/controls/ielabel.ocx"> <PARAM NAME="_ExtentX" VALUE="11192"> <PARAM NAME="_ExtentY" VALUE="1296"> <PARAM NAME="Caption" VALUE="ActiveX Rocks!!"> <PARAM NAME="Angle" VALUE="0"> <PARAM NAME="Alignment" VALUE="1"> <PARAM NAME="Mode" VALUE="0"> <PARAM NAME="FillStyle" VALUE="0"> <PARAM NAME="FillStyle" VALUE="0"> <PARAM NAME="ForeColor" VALUE="#000000"> <PARAM NAME="BackColor" VALUE="#C0C0C0"> <PARAM NAME="FontName" VALUE="Arial"> <PARAM NAME="FontSize" VALUE="12"> <PARAM NAME="FontItalic" VALUE="1"> <PARAM NAME="FontBold" VALUE="1"> <PARAM NAME="FontUnderline" VALUE="0"> <PARAM NAME="FontStrikeout" VALUE="0"> <PARAM NAME="TopPoints" VALUE="0"> <PARAM NAME="BotPoints" VALUE="0"> <!-- For those browsers that can't see ActiveX... --> <h2><i>ActiveX Rocks!! Get a new browser!</i></h2>. </OBJECT> </center> <OBJECT ID="IeTimer1" WIDTH=39 HEIGHT=39 CLASSID="CLSID:59CCB4A0-727D-11CF-AC36-00AA00A47DD2" CODEBASE="http://www.microsoft.com/activex/controls/ietimer.ocx"> <PARAM NAME="_ExtentX" VALUE="1032"> <PARAM NAME="_ExtentY" VALUE="1032"> <PARAM NAME="Interval" VALUE="150"> </OBJECT> <OBJECT ID="IeTimer2" WIDTH=39 HEIGHT=39 CLASSID="CLSID:59CCB4A0-727D-11CF-AC36-00AA00A47DD2" CODEBASE="http://www.microsoft.com/activex/controls/ietimer.ocx"> <PARAM NAME="_ExtentX" VALUE="1032"> <PARAM NAME="_ExtentY" VALUE="1032"> <PARAM NAME="Interval" VALUE="200"> </OBJECT> <!-- OK, tie 'em together with some VBScript! --> <SCRIPT LANGUAGE="VBScript"> <!-- dim crRed, crGreen, crBlue dim nSize dim bLarger crRed = 255 crGreen = 230 crBlue = 0 nSize = 12 bLarger = true Randomize Function GetRandomColor(nMax) GetRandomColor = Int((nMax + 1) * Rnd) End Function ' ' Flashing text colors ' Sub IeTimer1_Timer() crRed = GetRandomColor(256) crGreen = GetRandomColor(256) crBlue = GetRandomColor(256) IeLabel1.ForeColor = RGB(crRed, crGreen, crBlue) end sub ' ' Resizing label ' Sub IeTimer2_Timer() IeLabel1.FontSize = nSize if (nSize < 12) then nSize = 12 bLarger = true elseif (nSize > 24) then nSize = 24 bLarger = false end if if (bLarger) then nSize = nsize + 1 else nSize = nsize - 1 end if end sub --> </SCRIPT> <!-- Display the IE3 animated gif --> <CENTER> <font face="Arial" size=-1 color="000000"><B> <span style="font-size:9pt; color:000000"> Best experienced with<BR> <A HREF="http://www.microsoft.com/ie/ie.htm"> <IMG SRC="../gif/ie3_anim.gif" WIDTH=88 HEIGHT=31 ALT="Microsoft Internet Explorer" BORDER=0 ALIGN=center> </A> <br>Click here to start. </span> </font> <!-- Keep the user apprised of last update --> <H5> <SCRIPT LANGUAGE="JavaScript"> <!-- Hide script from old browsers update = new Date(document.lastModified) month = update.getMonth() + 1 date = update.getDate() year = update.getYear() document.writeln("<I>Last modified: " + month + "/" + date + "/" + year + "</I>") // End script hiding --> </SCRIPT> </H5> </CENTER> <p> <!-- Some rhythmic background music --> <BGSOUND SRC="../media/ percfun.mid"> </BODY> </HTML>
Figure 12.6 shows the result of this phase of completion, with the Welcome page displayed in the topic frame.
The files used to generate the version of the sample home page seen in Figure 12.6 can be found on the companion CD-ROM in the SOURCE\CHAP14\STAGE4 directory.
Figure 12.6. The final cut of the home page with WELCOME.HTM in the Topic pane.
Java applets provide yet another way to activate a Web site. The purpose of the Topic 1 page is to show off the use of a simple Java applet in a Web page. The applet is controlled by parameters given within the <APPLET> tag in the HTML source code. In this stage, I'll develop a simple Java applet called SpinningRedTorus. It's named this because the applet is an animation-only applet that displays a shiny red torus spinning around its axis.
For those of you not familiar with the term torus, it refers to a type of fourth-order, 3-dimensional mathematical surface called a quartic. All this lofty terminology really means is: a donut-shaped object. For instance, an inner tube is a torus.
The Java programming language has taken the world by storm, and it was the initial impetus that began to bring Web pages to life. Java is a very intuitive and powerful object-oriented programming language with a well-defined class library. Java can create both applications, which run stand-alone, and applets, that run within a host application (such as a Java-enabled Web browser). Although Java is capable of creating much more than simple Web page applets, this discussion of Java will be restricted to this area of interest. Like ActiveX controls, Java applets can really spice up your Web pages!
Sun Microsystems has licensed their Java technology to many software vendors, including Microsoft. Microsoft has released its Windows Java development system, Visual J++, to provide a familiar and comfortable working environment for Visual C++ users. The Visual J++ Developer Studio looks and acts exactly like the Visual C++ Developer Studio.
You can easily create basic Java applets in Visual J++ by using the Applet Wizard, which walks you through several simple steps to define a skeletal Java applet. Figure 12.7 shows step 1 of the process, which allows you to define a class name for the applet, and to specify how the applet will execute (as an applet only, or as an applet and as an application).
Figure 12.7. Step 1 of the Java Applet Wizard.
Figure 12.8 shows step 2 of the Applet Wizard, which allows you to specify the width and height of the applet, and to specify whether a sample HTML file should be generated to test the compiled applet.
Figure 12.8. Step 2 of the Java Applet Wizard.
Figure 12.9 shows step 3 of the Applet Wizard, which allows you to create a multithreaded applet (or not) and specify whether the applet will be used to display an animation. In this case, the SpinningRedTorus applet will be an animation-only applet. This step also allows you to specify whether the applet will respond to mouse messages (which SpinningRedTorus doesn't).
Figure 12.9. Step 3 of the Java Applet Wizard.
To control the rotation direction of the SpinningRedTorus (clockwise or counterclockwise) and the rotation velocity, two properties are needed: direction and interval. Step 4 of the Applet Wizard makes defining applet properties a snap, as you can see in Figure 12.10.
Figure 12.10. Step 4 of the Java Applet Wizard.
Once you've completed all the steps, Applet Wizard generates the source files for the applet, complete with default bitmaps that make up the animation frames. Figure 12.11 shows the SpinningRedTorus project loaded in the Microsoft Developer Studio.
Figure 12.11. The Developer Studio with the SpinningRedTorus project loaded.
The Applet Wizard uses 18 default bitmaps, depicting the earth rotating about its axis, but I replaced the default images with images from a 12-frame animation (of a spinning torus!) that I rendered using POVRAY.
The applet source code is pretty straightforward and is well commented. When it executes in a browser, the applet loads the 12 images for its animation frames from the images directory, which must be a subdirectory of the applet's home directory. This images subdirectory is hard-coded into the applet, so SpinningRedTorus is very finicky about this location. The complete source code for the applet is given in Listing 12.9.
Listing 12.9. The complete source code for the SpinningRedTorus applet (SpinningRedTorus.java).
//***************************************************************** // Applet : SpinningRedTorus.java // // Author : Rob McGregor // // Comments : Adapted from the Visual J++ Applet Wizard default // animation applet //***************************************************************** import java.applet.*; import java.awt.*; //================================================================= // Main Class for applet SpinningRedTorus //================================================================= public class SpinningRedTorus extends Applet implements Runnable { //-------------------------------------------------------------- // THREAD SUPPORT: //-------------------------------------------------------------- // m_SpinningRedTorus Thread object for the applet //-------------------------------------------------------------- Thread m_SpinningRedTorus = null; //-------------------------------------------------------------- // ANIMATION SUPPORT: //-------------------------------------------------------------- // m_Graphics stores the applet's Graphics context // m_Images[] the array of Image objects for the animation // m_nCurrImage the index of the next image to be displayed // m_ImgWidth width of each image // m_ImgHeight height of each image // m_fAllLoaded indicates whether all images have been loaded // IMAGE_LAST number of images used in the animation //-------------------------------------------------------------- private Graphics m_Graphics; private Image m_Images[]; private int m_nCurrImage; private int m_nImgWidth = 0; private int m_nImgHeight = 0; private boolean m_fAllLoaded = false; // Constants private final int NUM_IMAGES = 12; private final int FORWARD = 1; private final int BACKWARD = 0; //-------------------------------------------------------------- // PARAMETER SUPPORT: //-------------------------------------------------------------- // Parameters allow an HTML author to pass information to // the applet; the HTML author specifies them using the <PARAM> // tag within the <APPLET> tag. The following variables are // used to store the values of the parameters. //-------------------------------------------------------------- // Members for applet parameters private int m_Interval = 100; private int m_Direction = 0; // Parameter names. To change a name of a parameter, you need // only make a single change. Simply modify the value of the // parameter string below. //-------------------------------------------------------------- private final String PARAM_Interval = "Interval"; private final String PARAM_Direction = "Direction"; //============================================================== // SpinningRedTorus Class Constructor //============================================================== public SpinningRedTorus() { // Add constructor code here } //============================================================== // public String getAppletInfo() //-------------------------------------------------------------- // Returns a string describing the applet's author, copyright // date, or miscellaneous information //============================================================== public String getAppletInfo() { return "Name: SpinningRedTorus\r\n" + "Author: Rob McGregor\r\n" + "Created with Microsoft Visual J++ Version 1.0"; } //============================================================== // public String[][] getParameterInfo() //-------------------------------------------------------------- // The getParameterInfo() method returns an array of strings // describing the parameters understood by this applet. // // SpinningRedTorus Parameter Information: // { "Name", "Type", "Description" }, //============================================================== public String[][] getParameterInfo() { String[][] info = { { PARAM_Interval, "int", "Interval between frames" }, { PARAM_Direction, "int", "Forward or backward (1 or 0)" }, }; return info; } //============================================================== // public void init() //-------------------------------------------------------------- // Called by the AWT when an applet is first loaded or reloaded // Override this method to perform whatever initialization your // applet needs, such as initializing data structures, loading // images or fonts, creating frame windows, setting the layout // manager, or adding UI components. //============================================================== public void init() { // The following code retrieves the value of each parameter // specified with the <PARAM> tag and stores it in a member // variable. //----------------------------------------------------------- String param; // Interval: Interval between frames //----------------------------------------------------------- param = getParameter(PARAM_Interval); if (param != null) m_Interval = Integer.parseInt(param); // Direction: Forward or backward (1 or 0) //----------------------------------------------------------- param = getParameter(PARAM_Direction); if (param != null) m_Direction = Integer.parseInt(param); resize(160, 120); } //============================================================== // public void destroy() //-------------------------------------------------------------- // Called when the applet is terminating, place additional // applet clean up code here. //============================================================== public void destroy() { // Place applet cleanup code here } //============================================================== // public boolean imageUpdate() //-------------------------------------------------------------- // The imageUpdate() method is called repeatedly by the AWT // while images are being constructed. The flags parameter // provides information about the status of images under // construction. This method checks whether the ALLBITS flag is // set, which means that an image is completely loaded. When all // the images are completely loaded, this method sets the // m_fAllLoaded variable to true so that animation can begin. //============================================================== public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) { // Nothing to do if images are all loaded //----------------------------------------------------------- if (m_fAllLoaded) return false; // Want all bits to be available before painting //----------------------------------------------------------- if ((flags & ALLBITS) == 0) return true; // All bits are available, so increment loaded count of fully // loaded images, starting animation if all images are loaded //----------------------------------------------------------- if (++m_nCurrImage == NUM_IMAGES) { m_nCurrImage = (FORWARD == m_Direction) ? 0 : NUM_IMAGES - 1; m_fAllLoaded = true; } return false; } //============================================================== // private void displayImage() //-------------------------------------------------------------- // Draws the next image (if all images are currently loaded) //============================================================== private void displayImage(Graphics g) { if (!m_fAllLoaded) return; // Draw Image in center of applet //----------------------------------------------------------- g.drawImage(m_Images[m_nCurrImage], (size().width - m_nImgWidth) / 2, (size().height - m_nImgHeight) / 2, null); } //============================================================== // public void paint(Graphics g) //-------------------------------------------------------------- // SpinningRedTorus Paint Handler //============================================================== public void paint(Graphics g) { // The following code displays a status message until all the // images are loaded. Then it calls displayImage to display // the current image. //----------------------------------------------------------- if (m_fAllLoaded) { Rectangle r = g.getClipRect(); g.clearRect(r.x, r.y, r.width, r.height); displayImage; } else g.drawString("Loading ray traced images...", 10, 20); } //============================================================== // public void start() //-------------------------------------------------------------- // Called when the page containing the applet first appears on // the screen to start execution of the applet's thread. //============================================================== public void start() { if (m_SpinningRedTorus == null) { m_SpinningRedTorus = new Thread(this); m_SpinningRedTorus.start(); } } //============================================================== // public void stop() //-------------------------------------------------------------- // Called when the page containing the applet is no longer on // the screen. This method stops execution of the applet's // thread. //============================================================== public void stop() { if (m_SpinningRedTorus != null) { m_SpinningRedTorus.stop(); m_SpinningRedTorus = null; } } //============================================================== // public void run() //-------------------------------------------------------------- // Called when the applet's thread is started. If your applet // performs any ongoing activities without waiting for user // input, the code for implementing that behavior typically goes // here. For example, for an applet that performs animation, // the run() method controls the display of images. //============================================================== public void run() { repaint(); m_Graphics = getGraphics(); m_nCurrImage = 0; m_Images = new Image[NUM_IMAGES]; // Load in all the images //----------------------------------------------------------- String strImage; // For each image in the animation, this method first // constructs a string containing the path to the image file; // then it begins loading the image into the m_Images array. // Note that the call to getImage() will return before the // image is completely loaded. //----------------------------------------------------------- for (int i = 1; i <= NUM_IMAGES; i++) { // Build path to next image //-------------------------------------------------------- strImage = "./images/img00" + ((i < 10) ? "0" : "") + i + ".gif"; m_Images[i-1] = getImage(getDocumentBase(), strImage); // Get width and height of one image. // Assuming all images are same width and height //-------------------------------------------------------- if (m_nImgWidth == 0) { try { // The getWidth() and getHeight() methods of the // Image class return -1 if the dimensions are not // yet known. The following code keeps calling // getWidth() and getHeight() until they return // actual values. // // NOTE: // This is only executed once in this loop, since // we are assuming all images are the same width // and height. However, since we do not want to // duplicate the above image load code, the code // resides in the loop. //-------------------------------------------------- while ((m_nImgWidth = m_Images[i-1].getWidth(null)) < 0) Thread.sleep(1); while ((m_nImgHeight = m_Images[i-1].getHeight(null)) < 0) Thread.sleep(1); } catch (InterruptedException e) { // Place exception-handling code here in case an // InterruptedException is thrown by Thread.sleep(), // meaning that another thread has interrupted this // one } } // Force image to fully load //-------------------------------------------------------- m_Graphics.drawImage(m_Images[i-1], -1000, -1000, this); } // Wait until all images are fully loaded //----------------------------------------------------------- while (!m_fAllLoaded) { try { Thread.sleep(10); } catch (InterruptedException e) { // Place exception-handling code here in case an // InterruptedException is thrown by Thread.sleep(), // meaning that another thread has interrupted this // one } } repaint(); while (true) { try { // Draw next image in animation //----------------------------------------------------- displayImage(m_Graphics); if (m_Direction == FORWARD) // 1 { m_nCurrImage++; if (m_nCurrImage == NUM_IMAGES) m_nCurrImage = 0; } if (m_Direction == BACKWARD) // 0 { m_nCurrImage--; if (m_nCurrImage <= 0) m_nCurrImage = NUM_IMAGES - 1; } // Set the animation to desired speed Thread.sleep(m_Interval); } catch (InterruptedException e) { // Place exception-handling code here in case an // InterruptedException is thrown by Thread.sleep(), // meaning that another thread has interrupted this // one stop(); } } } }
Now that you have a custom Java applet on your hands, how do you add it to a Web page? Simple! Using the HTML <APPLET> tag, you can define the applet for Java-enabled browsers by using the following syntax:
<applet code = [AppletClass].class id = [AppletID] width = [AppletWidth] height = [AppletHeight]> <param name=[Param1Name] value=[Value]> <param name=[Param2Name] value=[Value]> ...etc... </applet>
Recall that the SpinningRedTorus applet uses two parameters, Direction and Interval. Interval specifies the milliseconds paused between frames, and Direction specifies either clockwise (1) or counterclockwise (0) rotation. The Topic 1 page is the lucky recipient of the SpinningRedTorus applet and uses parameters of Interval=100, and Direction=1 (clockwise rotation), like this:
<applet code = SpinningRedTorus.class id = SpinningRedTorus width = 160 height = 120> <param name=Interval value=100> <param name=Direction value=1> </applet>
Take a look at Listing 12.10, which shows the complete source code for TOPIC1.HTM. Note that a background music file is specified by this line:
<BGSOUND SRC="../media/ludwig5.mid">
This is a MIDI file that plays the opening of Beethoven's Fifth Symphony (it seemed a fitting addition to the drama of the spinning torus).
Listing 12.10. The final HTML source code for the Topic 1 page (TOPIC1.HTM).
<html> <head> <title>Topic 1: A Spinning Red Torus</title> </head> <body bgcolor="#FFFFF"> <!-- Some not so soothing background music --> <BGSOUND SRC="../media/ludwig5.mid"> <h2><i> Topic 1: A Java Applet </i></h2> <hr> <h3>Rob's Ray-Traced Shiny-Red Torus and Gold Sphere Java Applet...</h3><p> <h4>This 'lil Java applet is 160x120 pixels in size and takes two parameters: </h4><p> <IMG SRC="../gif/bullet2.gif" ALT="*"> <b><i>Interval</i></b> specifies the milliseconds paused between frames, and <br> <IMG SRC="../gif/bullet2.gif" ALT="*"> <b><i>Direction</i></b> specifies either clockwise (1) or counterclockwise (0) rotation.<p> For this example page, the <tt><b>Interval=100</b></tt>, and the <tt><b>Direction=1</b></tt> (clockwise): <p> <applet code=SpinningRedTorus.class id=SpinningRedTorus width=160 height=120 > <param name=Interval value=100> <param name=Direction value=1> </applet> <hr> Check out the <a HREF="../java/SpinningRedTorus.java" TARGET="topic" BORDER="0" ALT="Topic 1"> <b>source code </b></a> for this applet by clicking the link provided. If you have Visual J++ installed on your system, it will load the applet project! </body> </html>
Figure 12.12 shows the result of this stage of completion, with the Topic 2 page displayed in the topic frame. Now on to the final page.
The files used to generate the version of the sample home page seen in Figure 12.12 can be found on the companion CD-ROM in the SOURCE\CHAP14\STAGE5 directory.
Figure 12.12. The sample home page with the Applet Page completed.
This final stage of the sample Web site simply shows how to add some anchors, or bookmarks, to a Web page. You'll create the two anchors mentioned back in stage 3, when you developed the Contents page, and add a few images to the page to make it look nice.
Recall from the HTML code in TOC.HTM that you are to name the two anchors on this page anchor1 and anchor2. This is a simple process, using the <A NAME="Name"> syntax to define an anchor. The first anchor is then defined as:
<a name="anchor1"><h3>Poem of The Week</h3></a>
The second anchor is defined as:
<a name="anchor2"><h3>Runner Up</h3></a>
To add a little activity to the Topic 2 page, I added a marquee, which scrolls text across the screen. Although the marquee is a bit cliched because of its overuse on the Web, it does help to bring this otherwise static page to life. The marquee uses the HTML <MARQUEE> tag and is defined like this:
<FONT SIZE=4 COLOR=#FF0000> <MARQUEE BEHAVIOR=SLIDE DIRECTION=LEFT BORDER="0"> Poems of the week... </MARQUEE> </FONT>
This sets the font size and color, and it tells the browser to start displaying the text beyond the right edge of the window and slide the text to the left.
For cosmetic reasons, the background color of this page is set to a subdued aqua color with the BGCOLOR attribute set in the <BODY> tag, like this:
<BODY BGCOLOR="#92DDD4">
The complete HTML source code for this final page of the sample Web site is shown in Listing 12.11.
Listing 12.11. The HTML source code for the final version of the Topic 2 page (TOPIC2.HTM).
<HTML> <HEAD> <TITLE>Topic 2: The Poetry Corner</TITLE> </HEAD> <BODY BGCOLOR="#92DDD4"> <H2><I>Topic 2: The Poetry Corner</I></H2> <p> <!-- A cliche marquee --> <FONT SIZE=4 COLOR=#FF0000> <MARQUEE BEHAVIOR=SLIDE DIRECTION=LEFT BORDER="0"> Poems of the week... </MARQUEE> </FONT> <hr> Hello, and welcome to the poetry corner, where each and every week you can feed your soul! This time around the poem of the week is one of my favorites: "The Road Not Taken" <p> <center> <a name="anchor1"><h3>Poem of The Week</h3></a> <img src="../gif/frost1.gif" align=bottom width=302 height=450> </center> <hr> We've also got a poem this week from one of Florida's most talented young poets. The piece is entitled, "Yesterday" <p> <center> <a name="anchor2"><h3 align>Runner Up</h3></a> <img src="../gif/yester.gif" align=bottom width=251 height=453> </center> </BODY> </HTML>
Figure 12.13 shows the result of this final stage, with the Topic 2 page displayed in the topic frame.
The files used to generate the version of the sample home page seen in Figure 12.13 can be found on the companion CD-ROM in the SOURCE\CHAP14\STAGE6 directory.
Figure 12.13. The sample home page with the Topic 2 displayed in the Topic frame.
Creating exciting, interactive Web pages and Web sites is both challenging and fulfilling. It takes both artistic and programming talent, as well as an eye for detail. This chapter has shown you how to create a basic frames-driven Web site that contains six HTML files. Each of these six files demonstrated a different aspect of Web page design, including the use of: frames, ActiveX controls with VBScript, Java applets, JavaScript, image and text links to other frames, and background sounds, among other things.
Now that you've seen how the client side works, it's time to explore the server side of things. In the next chapter, you'll learn how to get greater control over your Web sites with Windows CGI Scripting.