CGI Communication

Although DHTML in the version 4 browsers is not specifically geared to interact with a server-side process, using some tricks it can be accomplished. This is particularly useful for building true applications using DHTML. You could create a wide range of applications such as some really nifty shopping carts, or a nice DHTML interface to a database, or possibly even a chat room if you're inclined to put in the time to write one. Following the guidelines I will explain here these things are all theoretically possible.

There are few ways to accomplish the task:

Hidden Frame

It's been long known that if you hide a frame you can target your form values to that frame, and the other page will stay loaded. You could submit a form, and have the CGI submit back a page containing JavaScript code that updates the other frame by rewriting layers or whatever. This is the easy way to do it, it's pretty straight-forward, so I won't cover it for now.

Java Client-Server Interaction (Servlet)

This would probably work very well. However you have to be using a server that supports Servlets and it would require a fair amount of work to accomplish. I may play around with creating a servlet and seeing if it indeed would work. The process would be like this:

JavaScript Applet Servlet Applet JavaScript
Use LiveConnect to execute functions in the applet applet communicates directly with the server-side java servlet processes request (writes files, calls database, whatever) and then communicates back to the applet applet sends the JavaScript the results display the results from the process by writing layers

Submitting Forms to Layers

The basic technique to use to submit a form to a layer is really just a derivative of the load external files technique. You load in external files that are generated by a Perl script or equivalent server-side process like ASP, PHP, or any number of web database languages like ColdFusion, Domino, Oracle etc. The fun part is, you can't send any information to the CGI by actually submitting the form (the way CGI scripts usually work). The whole point of developing a DHTML interface is to make the page static, but keep the information contained in it dynamic and updatable. This means you cannot ever change the location of the page and you must load files (containing new information generated by the CGI) into layers contained within the static page.

To communicate with a server using a regular CGI process there is only one solution: query strings!!!.

Your CGI script must be able to accept query strings instead of regular form parsed values. We will use query strings to pass all the relavent data to the CGI - I will be using a simple Perl script to accomplish this task.

Gathering the Data

The easiest way to gather your data is through HTML Forms. But you must realize that this is not the only way to gather data. You could create your own GUI elements to switch widget-like images on and off or any other crazy ideas you have. For simplicity in this example I'll just use a simple form that asks what your favourite operating system is:

<form name="myform">
<p>My Favourite Operating System is:

<p><input type="Radio" name="os" value="win9x">Windows 95/98
<br><input type="Radio" name="os" value="winnt">Windows NT 3.5/4.0
<br><input type="Radio" name="os" value="mac">MacOS 7/8
<br><input type="Radio" name="os" value="linux">Linux
<br><input type="Radio" name="os" value="solaris">Solaris
<br><input type="Radio" name="os" value="freebsd">FreeBSD
<br><input type="Radio" name="os" value="beos">BeOS
<br><input type="Radio" name="os" value="handheld">Handheld (PalmOS/WinCE)
<br><input type="Radio" name="os" value="otherunix">Other Unix-based
<p>
<input type="button" value="Submit" onClick="submitForm()">
</form>

Notice there is not ACTION associated with the Form tag, that's a no-no. You must create a JavaScript function of some sort to collect your data into individual variables. In my case, I just need to know which operating system was selected. So I created a submitForm() function to get that value when the Submit button is clicked:

function submitForm() {
	for (var i=0;i<document.myform.os.length;i++) {
		if (document.myform.os[i].checked) {
			var os = document.myform.os[i].value
			break
		}
	}
	alert(os)
}

View cgicomm1-form.html to view the form.

Getting The CGI Process To Work

Before we go head first into writing a big Perl script, we better do a little test to make sure this will in fact work. What I did was create a "results" layer which will contain the Perl-generated external page. To load the page I'll use the DynLayer load() method. Because the load() method uses an IFrame called "bufferFrame" we must include that as well. If you didn't read the DynLayer load() section yet, I recommend you do so now to understand what I'm doing.

The CSS (auto-generated via the css() function):

writeCSS (
css('resultsText',250,30)+
css('resultsDiv',250,50,200,100,'#c0c0c0')
)

The Div's:

<iframe style="display:none" name="bufferFrame"></iframe>

<div id="resultsText"><b>Results Layer:</b></div>
<div id="resultsDiv"></div>

In order to use the DynLayer load() method, we must have both the dynlayer.js and the dynlayer-common.js (which contains the load function) in the page:

<script language="JavaScript" src="../dynlayer/dynlayer.js"></script>
<script language="JavaScript" src="../dynlayerext/dynlayer-common.js"></script>

The resultsDiv layer must be initialized (DynLayerInit() can be used) and the load() method applied to it:

function init() {
	DynLayerInit()
	results.load = DynLayerLoad
}

When the form is submitted, we must change the location - by using the load() method - directly to the Perl script:

function submitForm() {
	for (var i=0;i<document.myform.os.length;i++) {
		if (document.myform.os[i].checked) {
			var os = document.myform.os[i].value
			break
		}
	}
	results.load("/cgi-bin/dynduo/cgicomm-test.pl")
}

For this "test" case, the cgicomm-test.pl script can be simple, it just writes out a simple page that does what all external files must do - call back to the layer it's being loaded to, to complete the loading sequence.

#!/usr/local/bin/perl

print "Content-type: text/html\n\n";
print "<html*gt;<body onLoad=\"parent.results.loadFinish()\"*gt;\n";
print "This text came from a perl script!";
print "</body*gt;</html*gt;\n";

View cgicomm2-cgitest.html [source] - to view a preliminary test of the DHTML-to-CGI communication technique.

As you can see this process works fine, so lets finish it up...

Finalizing The Perl Script and Query Strings

For this example the Perl script doesn't really do anything except gather the query strings (only one string actually - "os"), and then prints out a page.

#!/usr/local/bin/perl

# Get the query strings
@qsets = split (/&/,$ENV{'QUERY_STRING'});
foreach $qset (@qsets) {
	@qsetpart = split(/=/, $qset);
	$qstr{$qsetpart[0]} = $qsetpart[1];
}

# make a list of the full names for the OSes
$osNames{'win9x'} = "Windows 95/98";
$osNames{'winnt'} = "Windows NT 3.5/4.0";
$osNames{'mac'} = "MacOS 7/8";
$osNames{'linux'} = "Linux";
$osNames{'solaris'} = "Solaris";
$osNames{'freebsd'} = "FreeBSD";
$osNames{'beos'} = "BeOS";
$osNames{'handheld'} = "Handheld (PalmOS/WinCE)";
$osNames{'otherunix'} = "Other Unix-based";

# get the full name of the OS that was selected and sent as a query string 'os'
$os = $osNames{$qstr{'os'}};

# print the page
print "Content-type: text/html\n\n";
print "<html><body onLoad=\"parent.results.loadFinish()\">\n";
print "This text came from a perl script!";
print "<p>You have chosen:<br>$os\n";
print "</body></html>\n";

To test this script out you could point the browser to the script with a query string manually attached: /cgi-bin/dynduo/cgicomm.pl?os=win9x. It'll cause a JavaScript error when it tries to find the "results" layer, but you can see the script works fine otherwise.

There's only one small change we need to make in the JavaScript to finish everything up. We need to send the "os" variable to to the perl script when you submit the form:

if (os) results.load("/cgi-bin/dynduo/cgicomm.pl?os="+os)

And Voila! We have DHTML and JavaScript working together with Perl!

View cgicomm3-final.html [source] - to view a DHTML-to-CGI communication example.

As you can see it's really not that difficult. This general idea could be extrapolated significantly to open up a wide range of possibilities. I will be doing some more work on this, I may try to build a DHTML interface to my Forum. And I'll expand on this technique further in the future.

Home Next Lesson: Audio Controls
copyright 1998 Dan Steinman