In this section I am primarily going to be concerned with what it takes to use stacked handlers to create a system that returns a page comprised of three parts: a header; the center part of the page that will generally be generated dynamically; and a page footer. This is another one of those times when it is appropriate to keep in mind the distinction between what is going on at the browser client and what is going on at the server. At the server I am going to be executing three components, but when the output gets back to the browser it'll just be one page, no different than if I had written the same as static html. Sometimes it helps to keep that in mind.
PerlHandler BB_STACKED::header BB_STACKED::body BB_STACKED::footerThe only special requirement involved on the server level is that the module(s) involved be specified in a PerlModule directive so the relevant subroutines are visible to the interpreter as the server loads. (Theoretically, I guess it would be possible to get around that requirement if you put each subroutine in its own module and named that subroutine handler(), but that's too clunky to even think about.)
sub header {
my $r=shift;
$r->content_type('text/html');
$r->print('<body bgcolor="#ffffff" text="#000000" link="#0000ff" vlink="#800080" alink="#ff0000">
<table width="95%" border="1" cellspacing="0" cellpadding="4">
<tr>
<!-- Row 1 Column 1 -->
<td><center>
<a href="home.html" /href> Home </a>
</center>
</td>
<!-- Row 1 Column 2 -->
<td ><center>
<a href="/league/" /href> League Description </a>
</center></td>
<!-- Row 1 Column 3 -->
<td ><center>
<a href="/stats/" /href> Results and Statistics </a>
</center></td>
<!-- Row 1 Column 4 -->
<td ><center>
<a href="/entry/" /href> Game Entry and System Maintenance </a>
</center></td>
<!-- Row 1 Column 5 -->
<td ><center>
<a href="/login/" /href> Login </a>
</center></td>
</tr>
</table><br><br><center>
<table width="85%" border="1">
<tr><td></body></html>');
OK;
}
sub body {
my $r=shift;
$r->print(' <br><br><br>
This is the home page for the Legendary Lizards Baseball Association
<br><br><br>');
OK;
}
sub footer {
my $r=shift;
$r->print('<br><br><br><br>
</td></tr></table></center><br><br><br><br>
<table width="95%" border="3" bgcolor="darkblue" >
<tr>
<td><font size="16" color="darkgoldenrod">
<center>THE LEGENDARY LIZARDS BASEBALL ASSOCIATION</center></font>
</td>
</tr>
</table>
</body>
</html>');
OK;
}
The output displayed by the browser is shown in the figure to the right. (I must confess that the first few versions of this I created did not have the tremendous aesthetic appeal of the page you see to the right. It took a while before I started thinking "I should put this in a table, or center that" or whatever.) This is pretty straightforward, and pretty simple. A rather roundabout way to return static html, but a good illustration of what is going on.Then I got to thinking, why not put the start() subroutine from the BB_APP module in the middle position, just to see what that looks like. I changed the PerlHandler line for this location,
PerlHandler BB_STACKED::header BB_APP::start BB_STACKED::footer
and the result looks like the figure at the left. Now things are getting really cool. Of course, the app as displayed doesn't have anything to do with the menu across the top, but whaddaya want, anyway? <grin>.Obviously, however, I really do not want to put static html in the subroutines, at least in this context. I can conceive of a few situations in which it would make sense to do that, but in general it would be something of a pain to maintain. It would be much handier if the files could be read in from outside of the application itself. That way the potential exists to change what is displayed without modifying the code. I have experimented with this a bit by reading the lines above from filehandles on external files, with mixed results. I decided not to mess further with that, because when I do implement that kind of functionality I am going to be doing it in a different manner. It is, however, likely that at some point I will be doing something similar, so if you are sighing with frustration I would counsel patience. <ahem>
In the next section I am going to take the structure above and fit into it the sel_form() functionality written around the apache api functions rather than the CGI module functions.