JavaScript Tip of the Week for October 21, 1996: The Art of Dynamic HTML creation | 4 | WebReference

JavaScript Tip of the Week for October 21, 1996: The Art of Dynamic HTML creation | 4

JavaScript Tip of the Weekfor October 21, 1996: The Basics: Forms and Frames

The "Tip Finder" is a good example of forms and frames working together. But before you learn how it works, there are a few universal rules about working with frames that you should learn. First, all of your code should be in the main FRAMESET document. That means all of the code you are using should be in the head of the document where you define the frames, right before the <FRAMESET> tag. This is important because whenever you write over a frame, such as this app does when you click "Find Tip", all of the code is erased from that particular frame. The safest place to keep the code is in the main FRAMESET because no matter what happens to any individual frame, the code can always be accesed. Think of it as having global functions and variables. Say you define a variable or function in the main FRAMESET:
    function pointless() {
    alert ("Function pointless was run.");
If you were to call pointless() from any of the frames that this FRAMESET defined, you would need to append parent onto the function name:
Adding the parent property to pointless() tells the browser to run the function that resides in the FRAMESET containing the current frame. That's becaues the functions that are in the FRAMESET are considered to be higher in the object hierarchy than the functions in the current frame. The same goes for any variables in the FRAMESET too. Adding these prefixes to functions and variables is nothing new, you've probably been doing it for a long time but didn't even think about it. For instance, whenever you change a particular frame's location, you add parent.framename to the location property to end up with parent.framename.location = 'file.html'. What you are doing is telling JavaScript look in the main FRAMESET, then for the frame framename in that FRAMESET, and then modify the location property of that frame in the FRAMESET.

Now that you understand how to call functions and access variables between frames, you need to know how to easily and efficiently write to frames. The method that I prefer works well in Netscape 2.0, 3.0, and Internet Explorer. Instead of using the traditional document.write and appending the name of the frame to it, use the location method. I prefer the latter because the former only works properly if you use the open and close methods and it has trouble with IE. The location method works like this: Create an HTML document, give it to a string, and then set the location of a given frame to that string. The resulting effect is just as desirable as using document.write, and certainly no slower. (read on and this will be explained in more depth)

I started the "Tip Finder" app by creating two frames, assigning one to a blank HTML document using the location method in the SRC tag and the other to "part01_index.html".
    <SCRIPT LANGUAGE = "JavaScript">
        function init() {
        blankFrame = '<HTML><BODY BGCOLOR = "#FFFFFF"></BODY></HTML>';
        parent.draw.location = 'javascript:parent.blankFrame';
    <FRAMESET onLoad = "init()" COLS = "30%, 60%" FRAMEBORDER = NO BORDER = 0>
     SRC = "javascript:parent.blankFrame"
     NAME = "draw"
     SRC = "part02_index.html"
     NAME = "main" 
As you can see, all of the code for this program (shown by ...) is put right before the FRAMESET. When the document first loads, it runs the init() function. This function uses the location method to print out a blank HTML document for the the first frame, where all the tips show up. First, string blankFrame is given the value of what looks like a tiny HTML document. Then, the location property of the first frame, draw, is set to javascript:parent.blankFrame. This appears to be a very unorthodox URL, but what it does is set the source of draw equal to string blankFrame. Since blankFrame contains an HTML document, frame draw displays that document.

The form that goes with this app is in "part01_index.html". Here's what it looks like:
    <FORM NAME = "survey">
    First Name: <INPUT TYPE = TEXT NAME = "user_name"></TD></TR>
    Expertise in JavaScript:
    <SELECT NAME = "user_level">
    I want to learn how to:
    <SELECT NAME = "user_learn">
    <OPTION>Play Sound
    <OPTION>Save Space
    <OPTION>Play with Images</SELECT>
     onClick = "if (parent.draw) parent.createPage();">
    <INPUT TYPE = BUTTON VALUE = "Lose the Frames"
     onClick = "parent.location  = 'part02_index.html'">
When "Find Tip" is clicked, function createPage() is run. But remember that createPage() is in the main FRAMESET, so parent must appended to it. Function createPage(), which resides in the main FRAMESET, is the heart of this app, take a look:
    function createPage () {
    var name = parent.main.document.survey.user_name.value;
    var level = parent.main.document.survey.user_level.selectedIndex;
    var learn = parent.main.document.survey.user_learn.selectedIndex;
When the function is run, it defines three variables: name, level, and learn. Variable name, which represents your first name, takes the value you entered into the user_name input box. This illustration shows the hierarchy needed to find the value of user_name:
    FRAME: main  
            FORM: survey
                INPUT: user_name
As you can see, it simply ends up with the value of user_name. Then the values of level and learn are determined. These values, which represent your level of expertise in JavaScript and what you said you wanted to learn, are taken from the two select menus that you chose from [see Select Menu]. Next, chagePage() takes those values and uses a series of if statements to determine which tip is for you:
    if (learn == 0) how_to = 'play sounds';
    if (learn == 1) how_to = 'save space';
    if (learn == 2) how_to = 'play with images'; 
    if (level == 0) {
    comment = 'Since you are just beginning to learn JavaScript';
        if (learn == 0) tip = 'The <A HREF = "../960826/sound_music.html" TARGET = "_top">LiveAudio</A> Tip.';
        if (learn == 1) tip = 'The <A HREF = "../960923/part01.html" TARGET = "_top">Simple Select Menu</A> Tip.';
        if (learn == 2) tip = 'The <A HREF = "../960902/image_object.html" TARGET = "_top">Image Object</A> Tip.';
    if (level == 1) {
    comment = 'Since you have been using JavaScript for a while';
        if (learn == 0) tip = 'The <A HREF = "../960916/part02.html" TARGET = "_top">LiveConnect</A> Tip.';
        if (learn == 1) tip = 'The <A HREF = "../960902/select_boxes.html" TARGET = "_top">Modifiable Select Menus</A> Tip.';
        if (learn == 2) tip = 'The <A HREF = "../960930/index.html" TARGET = "_top">Highlighted Menus</A> Tip.';
    if (level == 2) {
    comment = 'Since you are experienced in JavaScript';
        if (learn == 0) tip = 'The <A HREF = "../960916/part02.html" TARGET = "_top">LiveConnect</A> Tip.';
        if (learn == 1) tip = 'The <A HREF = "../960902/select_boxes.html" TARGET = "_top">Modifiable Select Menus</A> Tip.';
        if (learn == 2) tip = 'The <A HREF = "../960923/part02.html" TARGET = "_top">Animated Billboard</A> Tip.';
First it takes the value of learn; if you choose "I want to learn how to play sounds" then learn is set to 0. If learn is 0, then how_to is set to "play sounds". Then, when the "Your Tip" page is displayed in the frame, it knows that you want to know how to "play sounds". This is the simple logic of the whole program; if this then that, and so on. Next, the level of expertise you have at scripting is determined by level. If level is 0 then the code considers you a beginner, and makes a comment accordingly. These if statements are actually creating an HTML document, phrase by phrase, which is tailored to your preferences.

The final step in this app is to display all of the information in the form of an HTML document:
    function baseHREF() {
    pathURL = window.location + ''; //little bug with URLs and strings
    pathDir = pathURL.lastIndexOf ('/', pathURL.length);
    pathBase = pathURL.substring (0, pathDir + 1);
    return pathBase;
    newPage = '<BASE HREF = "' + baseHREF() + '">' +
              '<HTML><HEAD><TITLE>JavaScript Tip of the Week for October 21, 1996: The Art of Dynamic HTML creation</TITLE></HEAD>' +
              '<BODY BGCOLOR = "#FFFFFF" TEXT = "#000000" LINK = "#B8860B" ALINK = "#8B0000" VLINK = "#B8860B">' +
              '<TABLE BORDER = 0 CELLPADDING = 5><TR><TD ALIGN = CENTER BGCOLOR = "#EDEDED"><FONT SIZE = 4>Your Tip:</FONT></TD></TR>' +
              '<TR><TD>Welcome to JavaScript Tip of the Week ' + name + '. ' + comment + ' and you want to learn how to ' + how_to + 
              ', I suggest:</TD></TR><TR><TD BGCOLOR = "#EDEDED"> ' + tip + '<TD></TR></TABLE>' + 
    parent.draw.location = 'javascript:parent.newPage';
Notice that newPage is actually an HTML document; it has the opening <HTML> tag, and the <BODY> tag, and so on. But if you look a bit closer you'll see that it is separated in many places by different variables. These variables simply add their respective values to the HTML document "stored" in newPage. That's how your name and preferences are displayed on the "Your Tip" page. Where the HTML document is broken by + name +, the name you entered earlier into the form is included. So instead of saying "Welcome to JavaScript Tip of the Week" is says "Welcome to JavaScript Tip of the Week Your Name Here". You are by all means not limited to plain text: you can add images, embeds... pretty much anything that can be done in HTML can be displayed reliably and dynamically in this way.

Finally, using the location method I discussed earlier, you set the left frame, draw, to the value stored in newPage. The page is then instantaneously displayed in the frame (well, pretty quickly anyway). That's all there is to it. But, you should note that if you want to reliably include images or other files in an HTML document created by JavaScript, the base HREF should be included. I've written a little function to do this so just cut and paste and you'll be all set. I hope you find this tip useful; make sure to come back next week if you haven't and I'll show you how.

You can see what I've done with Dynamic HTML creation in the The Hut.