A JSP Application

Well, I finally found the opportunity to develop a website using JSPs almost exclusively. A local establishment had made a few nervous steps towards establishing a net presence but it was very basic. They were using a shared service which had annoying pop-up ads on both entering and leaving the page. They were using some simple animation and hadn't even started the burdensome task of adding their food menu informations so I offered to implement their site.

Why JSP? I'd completed reading Advanced JavaServer Pages (highly recommended!) and found a wealth of information along with some compelling arguments for using JSPs. Most appealing to me were the custom tags and templates. When you're trying to ensure a consistent look-and-feel across a website, CSS (Cascading Style Sheets) is not enough. I needed to preserve the graphics as well as the layout, and templates looked to be a good fit. You can find the results here.

I purchased a .ca domain for them (the .com was already taken) and arranged to have the nameservers point back to one of my home servers running Apache/Tomcat. I wanted to use drop-down menus since I believe they're very user-friendly and look slick as well. I tried using some Java applet solutions but they took too long to download and initialize; I was going to have to use JavaScript. A bit of digging and I found a suitable starting point on the web. I had to modify the code to work with my Netscape 6 browser (I'll cover that later) but it fit the bill.

The problem was that there were now about 230 lines of code common to all the pages. Anyone who has worked with tables can tell you that if you make the slightest mistake (remove the wrong line, for example), your content might not be rendered at all. So what I needed was a way to encapsulate the common code and the framework and simply insert the content unique to each page. I also wanted to have an optional footer for navigation. This is one of those applications to which JSP is perfectly suited. Let's have a look at the contents of grill.jsp:

<%@ taglib uri="regions.tld" prefix="region" %>
<region:render template="template.jsp">
	<region:put section="title" content="Menu - Boston Manor's Specialties" direct="true"/>
	<region:put section="footer" content="nav.jsp"/>
	<region:put section="body">
<center>
<font size="+1">Feast on our Black Angus Steaks</font><br>
seasoned and grilled to your liking.
<p>
<font size="3" color="red"><b>
All of our steaks come with vegetables and your choice of rice, fries, mashed or baked<br>
potato. Dress up your baker with bacon and cheese for 0.99. Sub a garden saIad for 1.29
<b></font>
<p>
<table width="80%">
<tr>
<td width="50%">
<table>
<tr><td>
<font size="+1"><b>
Boston Manor New York Steak
</b></font><br>
1Ooz New York steak grilled and seasoned just right.
Guaranteed to satisfy taste. 14.98
</td></tr>
<tr><td>
<font size="+1"><b>
Bourbon Peppercorn Top Sirloin
</b></font><br>
Grilled and seasoned just right, Guaranteed to satisfy
your craving. 13.89
</td></tr>
<tr><td>
<font size="+1"><b>
Steak and Torpedo Shrimp
</b></font><br>
A great combo, Our New York steak served with three
extra large breaded shrimp. 18.98
</td></tr>
</table>
</td>
<td width="50%" valign="top">
<table>
<tr><td>
<font size="+1"><b>
Cajun Blackened Steak
</b></font><br>
Top sirloin rubbed with Boston Manor Cajun spice then
blackened in a cast iron pan. 13.89
</td></tr>
<tr><td>
<font size="+1"><b>
Steak with Sautéed Mushroom and Onion
</b></font><br>
Just like Mom's. Our top sirloin steak is basted in our
bold BBQ sauce and then smothered with sautéed
mushrooms and onions. 14.47
</td></tr>
</table>
</td>
</tr>
</table>
</center>
</region:put>
All I do is set the title, the (optional) navigation footer and in-line the body content. That's fairly straightforward since the encapsulating framework doesn't matter. Granted, I do a bit of table formatting to make things look pretty but it's not hugely complex. There are only 65 lines in the file. I use the regions package provided by the author of the aforementioned book. I do a region:put for each region, with the header and body having a direct attribute of true. Here's the template.jsp file:
<%@ taglib uri="regions.tld" prefix="region" %>
<head>
<title><region:render section="title"/></title>
<script language="JavaScript"><!--

/*
The ultimate DHTML drop-down code
Nick Nettleton
www.computerarts.co.uk || www.fluid7.co.uk
--
This must be the single most requested bit of code in the history of Computer Arts, so we've decided to make it user-friendly and adaptable for everyone. Stacks more goodies to come too - head to one of the above sites for regular infoa nd updates.
Works with v4 and v5 browsers - both IE and NS. Update for NS6 coming. Also, be aware there's no way to automatically centre layers in the window - a JS for this coming soon. In the meantime, stick with left-aligned.
Keep an eye out for update for NS6.
--
You can adapt, use and distribute this code under GNU public licence, as long as:
(1) You leave all the comment and credit lines in, including these ones
(2) You don't sell it for profit
--
If you want to tweak the code yourself, use the f7_droplayer to set the names of the dropdowns, and just call f7_showdrop(n) and f7_hdidedrop from onmouseover, onmouseout and other events. Swap n for the number of the layer as in the array.
--
Enjoy!!!
*/

//names of dropdowns stored here
f7_droplayer=new Array()
f7_droplayer[0]="drop1"

// names of anchors for dropdowns
f7_dropanchor=new Array()
f7_dropanchor[0]="anchor1"

//simple browser check
f7_v4=(parseInt(navigator.appVersion)>=4 && parseInt(navigator.appVersion)<=5)?1:0
f7_ie=(document.all && f7_v4)?1:0
f7_ns=(document.layers && f7_v4)?1:0
f7_w3cdom=(document.getElementById)?1:0


//code for drops

function f7_showdrop(thelayer){
	f7_keep=thelayer; f7_hideall(); f7_showitnow=1
	f7_showit(thelayer)
	}

function f7_showit(thelayer){
		if(f7_ie){ eval(f7_droplayer[thelayer]+'.style.visibility="visible"') }
		if(f7_ns){ eval('document.'+f7_droplayer[thelayer]+'.visibility="show"');}
		if(f7_w3cdom){
			f7_div=eval('document.getElementById("'+f7_droplayer[thelayer]+'")')
			if( f7_div.style.left == "0px" ) {
				f7_anchor=eval('document.getElementById("'+f7_dropanchor[thelayer]+'")')
				f7_div.style.left = f7_anchor.style.left;
				f7_div.style.top = f7_anchor.style.top;
			}
			f7_div.style.visibility="visible"
			}
	}


function f7_hidedrop(){
	f7_keep=-1; setTimeout('f7_hideall()',500)
	}

f7_keep=-1

function f7_hideall(){
	for(i=0;i<f7_droplayer.length;i++){  
		f7_hideit=0; f7_checkmousepos(i)
		if(f7_ie && f7_keep!=i){ 
			if(f7_hideit){ eval(f7_droplayer[i]+'.style.visibility="hidden"') } 
			}
		if(f7_ns && f7_keep!=i){ 
			if(f7_hideit){ eval('document.'+f7_droplayer[i]+'.visibility="hide"') }
			}
		if(f7_w3cdom && f7_keep!=i){ 
			if(f7_hideit){ eval('document.getElementById("'+f7_droplayer[i]+'").style.visibility="hidden"') }
			}
		}
	}

//deal with cursor over layer
document.onmousemove = f7_getmousepos
if (f7_ns) document.captureEvents(Event.MOUSEMOVE)

function f7_getmousepos(e){
	if(f7_ns){f7_mousex=e.pageX; f7_mousey=e.pageY}
	if(f7_ie){f7_mousex=event.clientX; f7_mousey=event.clientY;}
	else if(f7_w3cdom){f7_mousex=e.x; f7_mousey=e.y}
	}

function f7_checkmousepos(i){          
	if(f7_ns){     
		f7_x_min=eval('document.'+f7_droplayer[i]+'.left')
		f7_x_max=f7_x_min+eval('document.'+f7_droplayer[i]+'.clip.width')
		f7_y_min=eval('document.'+f7_droplayer[i]+'.top')
		f7_y_max=f7_y_min+eval('document.'+f7_droplayer[i]+'.clip.height')
		}    
	if(f7_ie){     
		f7_x_min=eval(f7_droplayer[i]+'.style.pixelLeft')
		f7_x_max=f7_x_min+eval(f7_droplayer[i]+'.style.pixelWidth')
		f7_y_min=eval(f7_droplayer[i]+'.style.pixelTop')
		f7_y_max=f7_y_min+eval(f7_droplayer[i]+'.style.pixelHeight')
		}
	if(f7_w3cdom){
		f7_div=eval('document.getElementById("'+f7_droplayer[i]+'")')
		f7_x_min=f7_div.style.pixelLeft
		f7_x_max=f7_x_min+f7_div.style.pixelWidth
		f7_y_min=f7_div.style.pixelTop
		f7_y_max=f7_y_min+f7_div.style.pixelHeight
		}
	if (f7_mousex>=f7_x_min && f7_mousex<=f7_x_max && f7_mousey>=f7_y_min && f7_mousey<=f7_y_max){
		f7_hideit=0; setTimeout('f7_hideall()',500)
		}
	else { f7_hideit=1 }
	return f7_hideit
	}

//--></script>
<script language="JavaScript"><!--

//browser stylesheets

if(f7_ie){
document.write('<style type="text/css"><!--')

document.write('.dropdown {padding-left:10px; padding-top:10px; padding-right:10px; padding-bottom:10px}')
document.write('p { margin-top:0px; margin-bottom:6px }')
document.write('a { text-decoration: none }')
document.write('a:hover { color: blue; text-decoration: underline }')
document.write('--></style>')
}

//--></script>
<style type="text/css">
<!--

.header {  font: bold 24px Arial, Verdana, Helvetica, sans-serif }
.subhead {  font-weight: bold; font-size: 12px  }
.list {  font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 12px; text-decoration: none  }
.forms {  font-size: 12px; font-family: Arial, Verdana, Helvetica, sans-serif }

.dropdown { position: absolute; color:black; width:145;  border: #000000; border-style: solid; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; background-color: white; layer-background-color: white; top:195px; z-index:1; visibility: hidden ;}
.drophead { color:blue; text-decoration:underline }
.dropitem { text-decoration:none; color:blue; }
.drophead:hover { color:blue; text-decoration:none }
.dropitem:hover { color:blue; font: bold; text-decoration:underline }

-->
</style>

</head>
<body background="cloth.gif" text="white" link="blue" alink="blue" vlink="blue">
<table width="100%">
<tr>
<script language="JavaScript">
if( window.innerHeight )
	ht = window.innerHeight
else
	ht = screen.availHeight
document.write( '<td width="34" height="' + ht + '" background="rail4.gif"></td>')
</script>
<td valign="top">
<center>
<table width="90%">
<tr>
<td><img src="rack3.gif"></td>
<td align="center">
<h1>BOSTON MANOR</h1>
<h2>BURLINGTON'S BEST<br>BAR AND BILLIARDS</h2>
<font size="+1">Upscale, <em>not</em> uptight!</font>
</td>
<td><img src="rack3.gif"></td>
</tr>
</table>
<p>
<table width="450">
<tr>
<td bgcolor="white" width="150" align="center" id="anchor1">
<a href="#" class="drophead" onmouseover="f7_showdrop(0)" onmouseout="f7_hidedrop()">Menu</a>
</td>
<td bgcolor="white" width="150" align="center">
<a href="./parties.jsp">Parties</a>
</td>
<td bgcolor="white" width="150" align="center">
<a href="./events.jsp">Events</a>
</td>
</tr>
<tr>
<td bgcolor="white" width="150" align="center">
<a href="./contact.jsp">Contact us</a>
</td>
<td bgcolor="white" width="150" align="center">
<a href="./links.jsp">Links</a>
</td>
<td bgcolor="white" width="150" align="center">
<a href="./coupon.jsp">Coupon</a>
</td>
</tr>
<tr height="0">
<td>
<div id="drop1" class="dropdown" style="middle:0px;" onmouseover="f7_showdrop(0)" onmouseout="f7_hidedrop()">
<p> <a href="./appetizers.jsp" class="dropitem">Appetizers</a><br>
 <a href="./soups.jsp" class="dropitem">Soups & Salads</a><br>
 <a href="./wings.jsp" class="dropitem">Wings</a><br>
 <a href="./sandwiches.jsp" class="dropitem">Sandwiches</a><br>
 <a href="./grinders.jsp" class="dropitem">Grinders</a><br>
 <a href="./wraps.jsp" class="dropitem">Wraps</a><br>
 <a href="./burgers.jsp" class="dropitem">Burgers</a><br>
 <a href="./classics.jsp" class="dropitem">Classics</a><br>
 <a href="./ribs.jsp" class="dropitem">Ribs</a><br>
 <a href="./specialties.jsp" class="dropitem">Specialties</a><br>
 <a href="./grill.jsp" class="dropitem">Grill</a><br>
 <a href="./texmex.jsp" class="dropitem">Tex Mex</a><br>
 <a href="./pasta.jsp" class="dropitem">Pasta</a><br>
 <a href="./pizza.jsp" class="dropitem">Pizza</a></p>
</div>
</td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</center>
<region:render section="body"/>
<region:render section="footer"/>
</td></tr></table>
</body>
That's 228 lines of code and, apart from rendering the title, body and footer, it consists of various stylesheets, the JavaScript menu code and some other fancy elements. By limiting any formatting changes to a single file, I've achieved the standardized look I wanted. There are only 20 files including the index and they range in size from 16 lines in wings.jsp to 122 lines in appetizer.jsp. The only other element is 5 lines of code in a file called nav.jsp which handles the home navigation. It obviously doesn't belong on the main index.

Of course this exercise doesn't even begin to address the potential of custom tags. Get the book and read it; just don't be surprised if you arrive at the logical conclusion that you could duplicate a product like Cold Fusion quite readily. That might make for a useful open-source project.

I alluded earlier to having trouble getting the code from computerarts working on my system. My problem: I run Netscape 6 on a Linux box and the code was only supposed to work on browser versions up to 5. The code you see on my pages will support IE 6 as well as Netscape 6 and 7, along with any W3C DOM browser. I tried to send the changes back to the authors but there's no contact information on their page. Just look for anything involving the f7_w3cdom variable if you want to check on the modifications. When I get some time I'm also going to change the menu position to be relative to an anchor rather than the current absolute positioning.

On another issue, I wanted to have a clipart image of a rail running down the left side of the page. I don't want the pages to be too busy but they can't be too plain either. The only problem was in ensuring that the rail would display for at least one complete screen. It would have looked odd if it ended half-way down. I used a common trick: create a table and have the browser tile your background image. I just had to calculate the minimum size of the screen. Here's the code:

<table width="100%">
<tr>
<script language="JavaScript">
if( window.innerHeight )
	ht = window.innerHeight
else
	ht = screen.availHeight
document.write( '<td width="34" height="' + ht + '" background="rail4.gif"></td>')
</script>
<td valign="top">

...content...

</td>
</td>
</table>
So nothing too earth-shattering here. A few tricks, a bit of tweaking and using some region layout code. It's not a huge site but I think it looks good and is, most important to my mind, internally consistent.

Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 by Phil Selby. All rights reserved.