The basis of almost all the dynamic pages we create is scripting with one of the various supported scripting languages, usually JavaScript, JScript or VBScript. It's also possible to install plug-in interpreters for other languages; if you wish, you should be able to find ASP and browser-compatible interpreters for Perl and TCL if you prefer to program in these languages. In our case, we will stay with the languages that are included by default—VBScript and JScript on the server in ASP, and JavaScript and VBScript on the client. As we've seen in previous chapters, both VBScript and JavaScript/JScript include commands for inserting information directly into a Web page.
Most browsers in current use support some scripting, and one of the simplest methods of creating dynamic content is to use the write
method of the document
. Because the only browsers that natively support VBScript are IE3 and above, we tend to use JavaScript—except where we are creating pages specifically for one type of browser. Remember that both JavaScript and JScript are case sensitive:
<SCRIPT LANGUAGE="JavaScript">
document.write(variablename_or_expression)
</SCRIPT>
<SCRIPT LANGUAGE="VBScript">
document.write variablename_or_expression
</SCRIPT>
In the previous chapter, you saw how we used client-side script to insert a hyperlink into a page, depending on whether it was hosted in a frameset or not. By comparing self
and parent
(the window objects that host the current page and the parent of the current page if there is one), we can determine if the current page is inside a frameset:
...
<SCRIPT LANGUAGE="JavaScript">
<!--
if (parent == self) {
// if they are equal, the current page is not in a frameset
document.write(' | <A HREF="default.asp">Turn Frames On</A>')
}
// -->
</SCRIPT>
...
In the previous chapter, when we looked at the simple dynamic frameset example, we also mentioned that there are ways to solve the problem of having six different navigation bar files, and loading the appropriate one each time. The problem is caused by using a different image for the current page button, to make it look as if it were depressed. A solution is to use only one file and use client-side script to find out which page is displayed in the main frame. The client can then automatically display the correct combination of button images, by writing the appropriate image URLs into the SRC
attribute of each of the button <IMG>
tags.
Here's the modified code, which checks the href
of the page in the main (right-hand) frame, and from this decides whether to include an 'up' or 'down' version of the image. Notice that we have to write the complete <IMG>
tag, not just the SRC
attribute, because we can’t embed a client-side <SCRIPT>
script section inside another element such as an <IMG>
:
...
<A HREF="mainpage.asp" TARGET="mainframe">
<SCRIPT LANGUAGE=JavaScript>
if (parent.frames[1].location.href.indexOf('mainpage.asp') != -1)
document.write('<IMG BORDER=0 SRC="/images/home_dn.gif" WIDTH="81" ' +
'HEIGHT="25" VSPACE="1" ALT="Web-Developer Home Page"/>')
else
document.write('<IMG BORDER=0 SRC="/images/home_up.gif" WIDTH="81" ' +
'HEIGHT="25" VSPACE="1" ALT="Web-Developer Home Page"/>');
</SCRIPT>
</A><BR>
...
... similar for other buttons here ...
...
Then, we make each of the main content pages reload the single new navigation bar file each time they appear in the main frame. The bar will automatically display the correct combination of images. The small change we make to the script code in each main page is:
...
<script LANGUAGE="JavaScript">
<!--
if (parent != self) parent.frames[0].location.href = 'nav_main.htm';
// -->
</script>
...
Instead of reloading the page, we might consider using script to change the SRC
attribute of the image tag to display a different image. However, this will only work in Navigator 3+ and Internet Explorer 4+, so it doesn't provide a compatible solution for all frame-enabled browsers. But, if you can control which browsers will access you site (for example on an Intranet), you might prefer this technique as it is faster and reduces server load.
In the next chapter we'll be looking at the whole area of compatibility between different browsers, as far as building dynamic content is concerned. For example, at the end of Chapter 4, we'll look at another frameset example that updates the navigation bar content without re-loading the page at all.
One of the reasons for the development of client-side scripting in the first place was to allow validation of forms that use HTML controls, such as text boxes and radio buttons. We often still use this technique in our dynamic pages. Being able to manipulate data and place it into text boxes and other controls, and submit the page to another dynamic page, is a powerful technique.
It's also the only way in many browsers (other than IE4+ and, to some extent, Navigator 4+) that we can change the contents of the page once it's loaded and displayed. The document.write
method can usually only be used as the page is being rendered. It can’t change parts of a loaded page, other than by manipulating a document in another window or frame by clearing it and writing it all again. And even this is only possible in the latest browsers.
To write content into the page dynamically on the server, in ASP, we use either the shorthand syntax:
<% = variablename_or_expression %>
or we use the Write method of the Response object—here as VBScript:
<% Response.Write variablename_or_expression %>
As on the client, we only get one go at creating the content of a page. The ASP script creates parts of the page, or inserts values into it, as it is being built on the server. Unless we turn on buffering (covered in more detail shortly), the content is flushed to the client as a stream of HTML and text as the script is being interpreted on the server.
The great thing with ASP is that we have access to so much information within our pages. Our ASP script can read all the values in a form submitted by another page, or the contents of the query string. It also has access to the contents of the ServerVariables
collection (as we saw in the example in the previous chapter), and several other collections of information about the client. This includes the contents of their client certificate (if presented) and any cookies they have stored on their browser that apply to this site. We'll be looking at these topics in Chapter 5.
And, unlike client-side programming, we can examine and create disk files in ASP, and use a range of components that are installed on our server. While we can provide components that are automatically downloaded to run on the client, it often makes a lot more sense—for reasons of speed, compatibility and security—to run the component on the server and send pure HTML back to the browser.
Buffering gives us an opportunity to 'change our mind' when creating pages using ASP. By adding the line Response.Buffer
=
True
after the LANGUAGE
statement, and before any content is created, we tell ASP to hold all the content of the page on the server and not send anything to the client until we tell it to.
When we're ready to send parts of the page we've created, we use Response.Flush
, or if we change our mind, we can clear the stored buffer contents with Response.Clear
. To stop all processing of the script and send back the current contents of the buffer, we use Response.End
. This is done automatically once the ASP script interpreter has completed executing the page.
As you'll see later, we can use Response.End
even if we haven’t turned buffering on. This simply prevents any further interpretation of the page, and sends the currently generated output to the browser.
Let's come back to the dynamic navigation bar we created earlier, to see how we would create the same effect with ASP on the server. The basic technique for creating the page content is almost identical. Once we know which page we are displaying in the main window, we can decide which button images to include in the navigation bar.
However, finding out which page is displayed in the main window is where the two techniques differ, and it neatly demonstrates the big issue involved in deciding where you actually create dynamic content. The server needs to know which page we're displaying in the main window, but—unlike client-side script—it can't determine this directly. Instead, we have to include the information in the request for the page.
As it turns out, this isn’t difficult because in our original six file example, we load the separate navigation bar pages by specifying their individual URLs directly in each main 'content' page. To pass the page name on to ASP on the server when we want to update the navigation bar frame, we can specify the same URL every time (i.e. the same file name), and append a query string that indicates which 'version' of the page we want:
<script LANGUAGE="JavaScript">
<!--
if (parent != self)
parent.frames[0].location.href = 'nav_main.asp?section=home';
// -->
</script>
The navigation page, now an ASP file, can detect the value of section in the query string, and use it to decide which image to display for each button. The following code demonstrates this, with the script at the start setting the variable strSection to the 'section' we want. Notice that, if a value isn’t specified, we 'fail-safe' by assuming it's the
Homepage:
<% LANGUAGE=VBSCRIPT %>
<%
strSection = Request.QueryString("section")
If Len(strSection) = 0 Then strSection = "home"
%>
<HTML>
<BODY BGCOLOR=#CC3333>
<CENTER>
<IMG BORDER=0 SRC="/images/webdevsm.gif" WIDTH=82 HEIGHT=76 VSPACE="10">
<BR>
<A HREF="mainpage.asp" TARGET="mainframe"><IMG BORDER=0
<% If strSection = "home" Then %>
SRC="/images/home_dn.gif"
<% Else %>
SRC="/images/home_up.gif"
<% End If %>
WIDTH="81" HEIGHT="25" VSPACE="1" ALT="Web-Developer Home Page"></A><BR>
<A HREF="books/booklist.asp" TARGET="mainframe"><IMG BORDER=0
<% If strSection = "samp" Then %>
SRC="/images/samp_dn.gif"
<% Else %>
SRC="/images/samp_up.gif"
<% End If %>
WIDTH="81" HEIGHT="25" VSPACE="1" ALT="Books and Samples"></A><BR>
...
... other buttons here ...
...
<A HREF="mainpage.asp" TARGET="_top"><IMG BORDER=0 SRC="/images/noframes.gif"
WIDTH="81" HEIGHT="25" VSPACE="0" ALT="Turn Frames Off"></A>
</CENTER>
</BODY>
</HTML>
This is basically the same technique that we used to build the frameset in the previous chapter example; by loading default.asp
with a query string that identified which pages we wanted displayed within the frames. The code itself could be written using a subroutine to make it more compact, but we've left the format as close to the original client-side code as possible so that you can easily compare the two.