JavaScript Dynamic Document Creation

By HTMLGoodies Staff

written by Jon Perry

JavaScript came out at the same time that the Microsoft Script language, VBScript, did, and allows flexible and more powerful Web sites to be designed. There is very little actual difference in programming power between JavaScript and VBScript, but I have written these articles for JavaScript. I suppose that at a later date I might translate them into VBScript.

This article explores the JavaScript Dynamic Document Creation (DDC) capabilities. Sounds very complicated, and is. Dynamic Document Creation is the creation of a Web document from within the JavaScript. It may be created while an HTML document is being displayed, and may be influenced by features of the current Web page. As a technique, it is very useful for displaying information from Web pages and creating new HTML documents.

DDC rapidly takes you into frames, new windows, variable expressions and using DHTML to access the DOM, and these topics will be covered later, in detail, in future articles. This article concentrates on explaining the principles of DDC, and is simple enough for a beginner to progress from the simple through to the advanced concepts of DDC.

The basic components of DDC are the JavaScript functions 'write()', 'writeln()', 'open()' and 'close()'. 'write()' writes the string it contains to the document referenced. 'writeln()' does the same, except it adds a carriage return character after writing its string. 'open()' and 'close()' open and close documents. They don't have any relevance to this article, and will be discussed in a later one.

There are two basic levels of implementation of DDC, the first is to create a fresh document from the current document, and the second is to create a document inside a new window. Creating a new window involves a detailed knowledge of the first type of DDC, and so I will begin with the first type.

To dynamically create a new document, you must place the necessary code in the HTML document as JavaScript. The most common method to achieve this is to place the JavaScript inside a <SCRIPT> element inside the <HEAD> element.

A simple DDC example is :

<HTML>
<HEAD>
<TITLE>DDC in Action</TITLE>
<SCRIPT>
document.write('Hello World, ');
document.write('from DDC in Action.');
</SCRIPT>
</HEAD>
</HTML>

This code, with no <BODY> element at all, writes 'Hello Word, from DDC in Action' to the page. Its <BODY> equivalent would be to add the text between the open and close tags of a <BODY> element. So, although with this example there have been no savings, having the line of text implemented form JavaScript, where it may be a variable, does increase our control over the Web page.

Next, I have demonstrated the difference between write and writeln next, virtually completely replicating the previous example, except for changing the write's to writeln's, and changing the text so that it is correctly formatted.

<HTML>
<HEAD>
<TITLE>DDC in Action2</TITLE>
<SCRIPT>
document.writeln('Hello World.');
document.writeln('From DDC in Action2.');
</SCRIPT>
</HEAD>
</HTML>

So you can see the difference between write and writeln, with the inclusion of a space after 'Hello World.'. Note that the last writeln is unnecessary in this example, as nothing it written after it the carriage return is invisible. This isn't a design feature though - if you were to add any further text, the difference would become visible again.

To write the two lines of text on separate lines, we have to write an HTML element to the document. Because write writes to a document, which is then parsed as an HTML document, we can pass it tags.

<HTML>
<HEAD>
<TITLE>DDC in Action3</TITLE>
<SCRIPT>
document.write('Hello World.');
document.write('<BR>');
document.writeln('From DDC in Action3.');
</SCRIPT>
</HEAD>
</HTML>

which places the <BR> element between the two lines of text, and causes them to be on different lines.

At this point, we have developed the theory only at the most basic level. To add excitement and complexity to DDC, we develop the techniques further, and a good example of this is in the use of functions.

Functions are pieces of code that perform calculations over a certain range of variables, and are generally called a lot, normally from different sections of a program. We can use functions in JavaScript to great effect, and so I have briefly explained them and their implementation. If we wish to define a function called 'ButtonPress' and this takes a parameter 'buttonnumber', we would define this like :

<HTML>
<HEAD>
<TITLE>Blank Function Code</TITLE>
<SCRIPT>
function ButtonPress(buttonnumber) {
code
}
</SCRIPT>
</HEAD>
</HTML>

The function is defined within a <SCRIPT> tag. This raises the issue of which JavaScript is interpreted. On a first run, any non-function JavaScript will be executed. Functions are only interpreted when called for the first time. If you run this program, it will not produce an error. This is because 'code' is never reached.

Although this program doesn't do anything, it has given our HTML document a JavaScript function, which we can call later. The curly braces {} will enclose the function's content. Note that functions do not have to take a parameter, we could have equally defined ButtonPress().

Now I add a few buttons to the Web page, and define the function, instead of the potentially dangerous 'code'.

<HTML>
<HEAD>
<TITLE>DDC Buttons</TITLE>
<SCRIPT>
function ButtonPress(buttonnumber) {
document.write('You pressed button number : '+buttonnumber);
}
</SCRIPT>
</HEAD>
<BODY>
<BUTTON onclick="ButtonPress(1);">Button 1</BUTTON>
<BUTTON onclick="ButtonPress(2);">Button 2</BUTTON>
<BUTTON onclick="ButtonPress(3);">Button 3</BUTTON>
</BODY>
</HTML>

This code displays three buttons and then tells you which one you pressed, hence demonstrating the use of variables inside the write command. JavaScript uses a loose typing of variables, e.g. x can any of a string, integer or floating-point. The statement within the write command is a concatenation of a string and variable, which the JavaScript interpreter reads as a variable, converts to the variables value, and converts the value to a string. These two strings are then added together. To press a different button to get a different result, you need to press 'Back' on your browser.

There is a problem in this area. We cannot add content to an existing Web page, we can only create a new one. We can add to a document that we have dynamically created, which can be useful. Advanced DHTML techniques do allow you to dynamically alter content, and there are methods to alleviate this as a problem within JavaScript, namely writing to a frame in the same window, and writing to a new window. Writing to a new window, as I have already said, is complicated. You need a full working knowledge of DDC to do this, and then you are faced with the task of tracking at least two windows rather than just one. I have covered this in the next article in this series, 'Dynamic Document Creation in a New Window.'

<HTML>
<HEAD>
<TITLE>DDC Creating HTML documents</TITLE>
<SCRIPT>
document.write('<BUTTON onclick="ButtonPress(1);">Button 1</BUTTON>');
document.write('<BUTTON onclick="ButtonPress(2);">Button 2</BUTTON>');
document.write('<BUTTON onclick="ButtonPress(3);">Button 3</BUTTON>');

function ButtonPress(buttonnumber) {
document.write('You pressed button number : '+buttonnumber);
}
</SCRIPT>
</HEAD>
</HTML>

This again demonstrates writing HTML elements to a new document. This code behaves exactly as the code before it, but you will notice again has no <BODY> element. A further trick here is to index the button writing code through a for loop, saving time, keeping the code tidy, and slightly increasing our control over the Web page development again.

Change :

document.write('<BUTTON onclick="ButtonPress(1);">Button 1</BUTTON>');
document.write('<BUTTON onclick="ButtonPress(2);">Button 2</BUTTON>');
document.write('<BUTTON onclick="ButtonPress(3);">Button 3</BUTTON>');

to :

for (index=1;index<=3;index++)
document.write('<BUTTON onclick="ButtonPress('+index+');">Button '+index+'</BUTTON>');

This is starting to get awkward. Great care needs to exercised when tracking the type and depth of quotes, and avoid getting confused with string/number combinations. We need to dip in and out of the 'write' string several times to get our desired effect. The write command is very literal in its behaviour, it just writes what you tell it to, and the result is as if you had typed the code in yourself through Windows NotePad.

If you break the example down, the statement :

document.write('<BUTTON onclick="ButtonPress('+index+');">Button '+index+'</BUTTON>');

has to be interpreted very carefully. The document.write command expects to be passed a string. So the first expression is :

document.write('<BUTTON onclick="ButtonPress('

This writes the string '<BUTTON onclick="ButtonPress(' to the document. The variable expression :

+index+

uses index as a number, e.g. index=1. When added to a string, index='1', and the string becomes : '<BUTTON onclick="ButtonPress(1'. So this code does not write the string 'index' to the current string, but converts it first to a number and then to the string of that number.

');">Button '

does a similar thing, and our string is now : '<BUTTON onclick="ButtonPress(1);">Button '. Another numerated index :

+index+

is added to the string, and we finalise it :

'</BUTTON>');

creates our desired string :'<BUTTON onclick="ButtonPress(1);">Button 1</BUTTON>'. This is repeated for all iterated values of index, which creates three buttons. Document.write writes these to a fresh HTML document, and the viewer will see three buttons, labelled Button 1, Button 2 and Button 3, and each one associated with an event handler to the function ButtonPress, with each buttons index as a parameter for the benefit of the function.

The hardest part about doing this is in nesting the strings, and making sure the entry and exit points for the string are correct. It would be very easy to be reading the string 'index', rather than the variable index.

To keep the document in the same window, without having to lose visibility of our initial document, we must use frames. For this example, I have created a frames document first, and give it two frames :

<HTML>
<HEAD>
<TITLE>Frames for DDC</TITLE>
</HEAD>
<FRAMESET rows="100,*">
<FRAME NAME="information">
<FRAME SRC="ButtonsforFrames.htm" NAME="buttons">
</FRAMESET>
</HTML>

We also need a 'Buttons' Web page. The 'Information' Web page is dynamically created from the Buttons document, and so we do not need to supply a SRC attribute for its frame element definition.

<HTML>
<HEAD>
<TITLE>Buttons Revisited</TITLE>
<SCRIPT>
for (index=1;index<=3;index++)
document.write('<BUTTON onclick="ButtonPress('+index+');">Button '+index+'</BUTTON>');

function ButtonPress(buttonnumber) {
parent.information.document.write('<LI>You pressed button number : '+buttonnumber+'</LI>');
}
</SCRIPT>
</HEAD>
</HTML>

This code should be saved in the same folder as 'FramesforDDC.htm', and as 'ButtonsforFrames.htm'. There is a significant development with this example, which is to navigate successfully through the window frame hierarchy, to be able to name the frame we intend to write to. As we are in frame 'Buttons', its parent is 'Window', which has two frames, 'Buttons' and 'Information'. We need the frame 'information', and so this has the relative reference parent.information. This is a reference to a window, and so we access the document part of it. I have put the recorded button presses in a list to maintain order.

This article originally appeared on WebDevelopersJournal.com.



Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
  •