Chapter 8
Form Modification
CONTENTS
Form modification is the process by which data entered by a user is
translated into another format before being submitted to the form's server.
When data from a form is submitted to its server, the data has to be formatted
in a way that the server can understand. The format is usually in the form
<url>?<field1=value>?<field2=value>...
where <field1>, <field2>, and so forth are the NAME attributes
of the INPUT, SELECT, and TEXTAREA elements of the form. The values are,
with minor translations made by the browser, the VALUE attributes of those
elements.
So why would you need to go to the trouble of form modification? Because
the format of the values and the fields are not necessarily very user friendly.
If you have to create a Web page to interface to such a server and you
have no control over the server's input requirements, you can use form
modification to create a superior, easier-to-use Web page.
The scenario
The United States Department of Commerce Bureau of the Census operates
the Tiger Map Service. The Tiger Map Service defines a URL, http://tiger.census.gov/cgi-bin/mapgen,
and a set of field-value pairs that can be specified. The server responds
with a GIF file that displays a made-to-order map specified by the field-value
pairs.
The interface defines a very rich set of field-value pairs. One of these
actually allows you to shorten the data sent to the server by defining
a URL that contains additional field-value pairs. The critical set of pairs,
however, define the area that the map will display. These are
- lon=number
- lat=number
- wid=number
- ht=number
These four field-value pairs define the longitude (east-west coordinate),
the latitude (north-south coordinate), and the width and height of the
area displayed by the map. The values are specified in decimal degrees;
you would specify a latitude of 38 degrees, 45 minutes to the server as
38.75 degrees, for example.
Naturally, this scenario requires a Web page with a form for creating
a map GIF file.
The
requirements
The typical user will want to look at famous U.S. landmarks or at his
or her hometown. The typical user will also have, at best, a vague idea
of the coordinates of the location he or she wants to see. (You can check
a map to get a general idea of the coordinates you need.) The user will
usually have no idea at all how to set the width and height to capture
the desired level of detail. The greater the values of the wid and ht fields,
the larger the area displayed in the map and the less detail displayed.
But how small should these field values be to get the desired level of
detail? Most users won't know and will need to experiment to get the desired
results.
For these reasons, the Web page should let users enter the coordinates
and height and width fields as easily as possible, and should make it easy
for them to change the fields and try again.
The
solution (without JavaScript)
To capture the required fields, you need four INPUT elements with NAME
attributes of lat, lon, wid, and ht. To give the user a reasonable map
size, let's add iht and iwd fields. These fields describe the image height
and image width; both values are specified in pixels. You can make them
HIDDEN type INPUT elements, and give them fixed values. Let's use an image
area 320 pixels wide and 200 pixels high.
The rest of the Web page has the standard HTML/HEAD/BODY structure,
with the fields contained in a FORM element. The FORM ACTION attribute
needs to be specified as "http://tiger.census.gov/cgi-bin/mapgen"
and the METHOD attribute should be "GET." Listing 8.1 contains
the code for this Web page.
Listing 8.1: HTML for non-JavaScript solution
<HTML>
<HEAD>
<TITLE>Map Service</TITLE>
</HEAD>
<BODY>
<PRE>
<FORM ACTION="http://tiger.census.gov/cgi-bin/mapgen"
METHOD="GET">
Longitude: <INPUT NAME="lon" TYPE="text" SIZE=1Ø>
Latitude: <INPUT NAME="lat" TYPE="text" SIZE=1Ø>
Width: <INPUT NAME="wid" TYPE="text" SIZE=1Ø>
Height: <INPUT NAME="ht" TYPE="text" SIZE=1Ø>
<INPUT NAME="iwd" TYPE="hidden" VALUE="32Ø">
<INPUT NAME="iht" TYPE="hidden" VALUE="2ØØ">
<INPUT TYPE="submit"><INPUT TYPE="reset">
</FORM>
</PRE>
</BODY>
</HTML>
Figure 8.1 shows the form with some sample values entered, and Figure
8.2 shows the map GIF file that the server returned as a result.
Figure
8.1 : Non-JavaScript form with sample values.
Figure
8.2 : Result of submitting data from Figure 8.1.
The
solution (with JavaScript)
One problem with the Tiger Map Service interface is that it uses decimal
degrees. Unfortunately, that doesn't tie in very well with most sources
of map data, which usually specify locations in terms of degrees, minutes,
and seconds.
Even worse is the fact that most people have no idea how much real estate
is covered by one degree of latitude or longitude, or one minute, or one
second. How is the average user going to know what to specify for the height
and width of the area?
You need a more intuitive interface than the server allows.
First, the user has to be able to specify the latitude and longitude
in conventional terms of degrees, minutes, and seconds. Second, you need
a more intuitive way to manage the area's height and width. Given that
one of the requirements of this page is to make it easy to change these
values, let's start with an arbitrary height and width of one degree, and
let the user modify the height and width by zooming in and out. Zooming
in will be defined as cutting the height and width in half, which places
one quarter the area (more or less) in the same image size. Zooming out
will be defined as doubling the height and width, placing four times the
area in the same image size.
Finally, you can add buttons to allow the user to fine-tune the center
coordinates. That will further meet the requirement of allowing the user
to easily make quick changes to the map.
You do all this by creating two FORM elements. The first FORM element
is very similar to the FORM element in Listing 8.1. There is one big difference:
The INPUT elements are HIDDEN type instead of TEXT, and the descriptive
text is removed, making the form invisible.
The second FORM element is the form the user will see. It has two BUTTON
INPUT elements, one to execute the zoom in and one to execute the zoom
out. There is also a TEXT INPUT element for displaying the current magnification
factor. This element is useful because the server sometimes cannot meet
the request and a "Sorry, Busy" GIF image appears instead of
the requested map. Once users have more or less zeroed in on the area of
choice, they tend to keep zooming in, and may not recall how far they have
zoomed in. Displaying the magnification factor helps them keep track of
how far they have zoomed in. This visual feedback helps if the user zooms
in but doesn't get a map because the server is busy. There is at least
a clue that maybe the user should press the GO! button instead of pressing
the Zoom In button again.
In addition to the zoom controls, there are three TEXT INPUT elements
for the latitude (one for degrees, one for minutes, and one for seconds)
and three for the longitude. There are also four BUTTON INPUT elements
that allow the user to make small adjustments to the map, moving it to
the west, north, east, or south.
Finally, there is a BUTTON INPUT element to act as a submit button and
a RESET INPUT element. You don't want a real SUBMIT INPUT element, because
the data in this FORM element is not going to be sent to a server.
Laying Out the Controls
There are a lot of controls for this Web page: seven BUTTON INPUT elements,
seven TEXT INPUT elements, and a RESET INPUT element. If you put them in
a TABLE element, you can manage them better.
Let's start with one TABLE element. It, in turn, will contain three
TABLE elements-one for the zoom controls, one for the location controls,
and one for the submit and reset controls. The TABLE element will be inside
the FORM element, and the TABLE HTML will look something like this:
<FORM>
<TABLE>
<TR>
<TD>
<TABLE>
</TABLE>
</TD>
<TD>
<TABLE>
</TABLE>
</TD>
<TD>
<TABLE>
</TABLE>
</TD>
</TR>
</TABLE>
</FORM>
This code describes a TABLE element with a single TABLE ROW (TR) element.
The TABLE ROW element contains three TABLE DATA (TD) elements. Each TABLE
DATA element contains a TABLE element. This produces an effect of three
TABLE elements lined up side by side, as shown in Figure 8.3.
Figure
8.3 : Gross table structure.
The first TABLE element will contain the zoom controls. It looks like
this:
<TABLE>
<TR>
<TD>
<INPUT TYPE="button" VALUE="ZOOM IN">
</TD>
</TR>
<TR>
<TD>
<INPUT TYPE="text" NAME="mag" SIZE=4>
</TD>
</TR>
<TR>
<TD>
<INPUT TYPE="button" VALUE="ZOOM OUT">
</TD>
</TR>
</TABLE>
This code creates three rows, with one data cell each. The top cell
contains the ZOOM IN button, the middle cell contains the magnification
factor display, and the bottom cell contains the ZOOM OUT button, as you
can see in Figure 8.4.
Figure
8.4 : Zoom controls.
The second table contains the location controls. The layout of the table
is like this:
<TABLE>
<TR>
<TD>
East/West <INPUT TYPE="text" NAME="londeg" SIZE=4><INPUT TYPE="text"
NAME="lonmin" SIZE=2><INPUT TYPE="text" NAME="lonsec" SIZE=1Ø>
</TD>
<TD ROWSPAN="2">
<TABLE>
</TABLE>
</TD>
</TR>
<TR>
<TD>
North/South <INPUT TYPE="text" NAME="latdeg" SIZE=2><INPUT TYPE="text"
NAME="latmin" SIZE=2><INPUT TYPE="text" NAME="latsec" SIZE=1Ø>
</TD>
</TR>
</TABLE>
This code creates three cells in two rows-two cells on the left (one
top cell and one bottom cell) and a third cell on the right that's the
height of the other two cells combined as shown in Figure 8.5.
Figure
8.5 : Location controls.
The two left-hand cells provide the TEXT INPUT elements for entering
the longitude (east-west coordinate) and the latitude (north-south coordinate).
The large cell on the right contains another TABLE element that will contain
the east-north-west-south adjustment buttons.
The adjustment controls TABLE is laid out like this:
<TABLE>
<TR>
<TD>
</TD>
<TD>
<INPUT TYPE="button" VALUE="N">
</TD>
<TD>
</TD>
</TR>
<TR>
<TD>
<INPUT TYPE="button" VALUE="W">
</TD>
<TD>
</TD>
<TD>
<INPUT TYPE="button" VALUE="E">
</TD>
</TR>
<TR>
<TD>
</TD>
<TD>
<INPUT TYPE="button" VALUE="S">
</TD>
<TD>
</TD>
</TR>
</TABLE>
This layout produces a simple compass star, as shown in Figure 8.6.
Figure
8.6 : Compass controls.
Finally, the third table contains the submit and reset controls, as
laid out here:
<TABLE BORDER="Ø" CELLPADDING="2">
<TR>
<TD>
<INPUT TYPE="button" VALUE="GO!">
</TD>
</TR>
<TR>
<TD>
<INPUT TYPE="RESET">
</TD>
</TR>
</TABLE>
You can see these controls in Figure 8.7.
Figure
8.7 : The map controls.
Laying Out the Window
Having organized the new FORM element's contents for the screen, you
need to give some thought to the setup of the overall screen. One of the
problems with the non-JavaScript implementation is that the map replaces
the form on the screen; to return to the form data, the user has to use
the BACK button. At no time can the user see the data and the map together.
You can fix this shortcoming by using frames:
<HTML>
<HEAD>
<TITLE>Tiger Map Service</TITLE>
</HEAD>
<FRAMESET ROWS="22Ø, *">
<FRAMESET COLS="*,35Ø,*">
<FRAME NAME="leftBorder" SRC="wall.htm">
<FRAME NAME="viewer" SRC="view.htm">
<FRAME NAME="rightBorder" SRC="wall.htm">
</FRAMESET>
<FRAME NAME="control" SRC="mapctrl.htm">
</FRAME>
</FRAMESET>
</HTML>
This frame document divides the screen vertically into an upper frame
220 pixels high and a lower frame that occupies the remainder of the screen.
The FORM elements will be in the lower frame. The 220 pixel height of the
top frame allows most browsers to display the 200 pixel high image without
a scroll bar. The top frame is then subdivided vertically into a 350 pixel
wide frame flanked by two frames on either side. The 350 pixel width of
the viewer frame allows most browsers to display the 320 pixel wide image
without a scroll bar. Figure 8.8 shows the resulting screen.
Figure
8.8 : JavaScript solution with map displayed.
<FORM NAME="realForm" ACTION="http://tiger.census.gov/cgi-bin/mapgen"
METHOD="GET" TARGET="viewer">
The TARGET attribute tells the browser to display the submission results
in the viewer frame. Without that, the results would replace the contents
of the control frame, and the user would lose his or her view of the data.
Adding Functionality
to the Controls
With the two FORM elements defined, the data entered into the second
FORM element has to wind up, in modified format, in the first FORM element.
This will require event handlers for some of the INPUT elements in the
second FORM element.
BUTTON type elements are the easiest INPUT elements to use. The ONCLICK
event is very understandable to users, much more so than ONCHANGE, ONFOCUS,
and ONBLUR events, which have subtle differences in their behavior from
one platform to another. A mouse click behaves pretty much the same on
all platforms.
The jobs of the ONCLICK event handlers depend on the BUTTON elements
they work on. The GO! and ZOOM controls should display a new map. The compass
controls should modify the contents of the longitude or latitude fields,
but should not display a new map. The user may want to use more than one
compass control to move the image further east and further north, for example,
and will not want to wait between adjustments for the wrong area to be
displayed.
The E and W buttons can share a function; they both adjust the longitude,
just in opposite directions. Similarly, the N and S buttons can share a
function. Let's call these functions changeLongitude() and changeLatitude().
Called with a negative value, changeLongitude() moves the center of the
picture west and changeLatitude() moves the center of the picture south.
Called with a positive value, changeLongitude() moves the center of the
picture east and changeLatitude() moves the center of the picture north.
The two functions are nearly identical; this is changeLongitude():
function changeLongitude(dir)
{
var delta = Ø.1 / getMagnification();
var longitude = getLongitude();
if (dir < Ø)
{
longitude -= delta;
}
else
{
longitude += delta;
}
setLongitude(longitude);
}
The current magnification factor is obtained by a call to getMagnification()
and a value of one-tenth of a degree is divided by the magnification factor.
Because the image spans a degree divided by the magnification factor, this
is a delta of one tenth of the image. The longitude is then obtained by
a call to getLongitude(). The delta is either subtracted from it or added
to it. The new longitude is written back out with setLongitude().
The changeLatitude() function is identical except that it deals with
latitude instead of longitude.
The getMagnification() function obtains the value from the TEXT INPUT
element named "mag":
function getMagnification()
{
var magnification = 1;
if (document.showForm.mag.value.length != Ø)
{
magnification =
Math.abs(parseFloat(document.showForm.mag.value));
if (magnification == Ø)
{
magnification = 1;
}
}
return magnification;
}
The return value is set to 1 as a default. If anything is entered on
screen, parseFloat() is called to evaluate the contents. The absolute value
of the result is taken-a negative magnification factor doesn't make sense.
If the result is 0, the value is replaced with the default value of 1.
The getLongitude() function calculates a decimal longitude from the
three TEXT INPUT elements in which the user has entered the longitude in
degrees, minutes, and seconds:
function getLongitude()
{
var londeg = Ø;
if (document.showForm.londeg.value.length != Ø)
{
londeg = Math.abs(parseInt(document.showForm.londeg.value));
}
var lonmin = Ø;
if (document.showForm.lonmin.value.length != Ø)
{
lonmin = Math.abs(parseInt(document.showForm.lonmin.value));
}
var lonsec = Ø;
if (document.showForm.lonsec.value.length != Ø)
{
lonsec = Math.abs(parseFloat(document.showForm.lonsec.value));
}
var lon = -(londeg + ((lonmin + (lonsec / 6Ø)) / 6Ø));
return lon;
}
As with the magnification value calculated in getMagnification(), values
are calculated for the three fields, with 0 as the default value for each
field. Because the degrees and minutes fields are assumed to be integer
values, parseInt() rather than parseFloat() is used to evaluate their values.
The calculation of the result from the degrees, minutes, and seconds
values is straightforward, with one interesting quirk: The value has to
be negative. The Tiger Map Service delivers maps for the continental United
States, and longitudes are, by convention, negative west of the Prime Meridian.
There is an equivalent function to evaluate the latitude fields, getLatitude().
It is identical to the getLongitude() function except that the return value
is positive. (Again, by convention, latitudes in the northern hemisphere
are positive values.)
The setLongitude() function translates the decimal longitude back into
degrees, minutes, and seconds and writes the values back to the TEXT INPUT
elements:
function setLongitude(longitude)
{
longitude = Math.abs(longitude);
var degrees = Math.floor(longitude);
longitude = longitude - Math.floor(longitude);
longitude *= 6Ø;
var minutes = Math.floor(longitude)
// complicated math to eliminate eensy teensy fractions of seconds
var seconds = 6Ø * (longitude - Math.floor(longitude))
seconds *= 1ØØØ;
seconds = Math.round(seconds);
seconds /= 1ØØØ;
if (seconds >= 6Ø)
{
seconds -= 6Ø;
minutes++;
}
if (minutes >= 6Ø)
{
minutes -=6Ø;
degrees++;
}
document.showForm.londeg.value = -degrees;
document.showForm.lonmin.value = minutes;
document.showForm.lonsec.value = seconds;
}
The longitude value is made positive by a call to Math.abs(). The integer
portion is extracted using Math.floor(); this is the degrees part of the
value. The remaining fractional part is obtained and multiplied by 60,
and the integer portion of the result is taken with Math.floor(); this
is the minutes part of the value. The remaining fractional part is obtained
and multiplied by 60; this is the seconds part of the value, which is allowed
to have a fractional part.
You might think that that's enough, but from the standpoint of user
interaction, it isn't. The seconds field on the form is defined as displaying
ten digits, but Netscape's math functions result in a value with more than
ten digits of precision. Furthermore, the act of translating the three
input fields into decimal degrees and then translating that result back
into degrees, minutes, and seconds may introduce a tiny discrepancy into
the result. This is due to the limitations inherent in representing fractions
such as one third in the computer's binary memory: There is no value expressible
in a finite set of powers of 2 that exactly equals one third.
So the seconds value is multiplied by 1,000, rounded off with Math.round(),
and divided by 1,000. This gives a precision of 1/1,000 of a second. At
the equator, where one degree of longitude is widest, 1/1,000 of a second
is approximately an inch and a quarter, or about three centimeters. That
should be good enough.
Because of rounding, the seconds value may now equal 60, which is one
minute. This scenario has to be handled, and the carry effect may propagate
to the degrees, as would happen if the initial calculation of minutes and
seconds arrived at values of 59 and 59.99999.
Finally, after you have calculated acceptable values for degrees, minutes,
and seconds, the values are written to the appropriate TEXT INPUT elements.
The degrees are written as a negative value.
As with getLongitude() and getLatitude(), setLongitude() has a matching
function, setLatitude(). The calculations are identical, and the difference
is that the degrees latitude are written back as a positive value.
So that's how the compass point buttons work. Let's look at the zoom
buttons next.
The zoom buttons cause two things to occur: First, they change the current
magnification factor. Second, they update the hidden form-the one that
contains the fields that the Tiger Map Service needs-and submit the data
to the server. This function does the work for both buttons:
function zoom(dir)
{
var magnification = getMagnification();
if (dir < Ø)
{
magnification /= 2;
}
else
{
magnification *= 2;
}
display(magnification);
}
If the parameter dir is negative, the user is zooming out; if dir is
positive, the user is zooming in. So, the magnification factor is obtained
by a call to getMagnification and either halved or doubled. The new magnification
factor is then passed to display(), which is shown here:
function display(magnification)
{
document.showForm.mag.value = magnification;
var lon = getLongitude();
setLongitude(lon);
document.realForm.lon.value = lon;
document.realForm.wid.value = 1 / magnification ;
var lat = getLatitude();
setLatitude(lat);
document.realForm.lat.value = lat;
document.realForm.ht.value = 1 / magnification;
document.realForm.submit();
}
First, the new magnification factor is written back to the TEXT INPUT
field. Then the decimal longitude is obtained, the display is updated,
and the decimal longitude is written to the hidden form's lon field. The
hidden form's wid field is set to the inverse of the magnification factor.
Remember, the higher the factor, the smaller of an area you're looking
at.
The analogous calls are then made to set the hidden form's lat and ht
values, and the hidden form's submit method is called, sending the request
to the server.
Finally, the Go button's ONCLICK event handler is extremely simple:
It just calls getMagnification() and sends the result to display(), like
this:
display(getMagnification())
Putting Everything Together
Listing 8.2 shows the finished mapctrl.htm file.
Listing 8.2: HTML for the JavaScript solution
<HTML>
<HEAD>
<TITLE>Map Service</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
function getMagnification()
{
var magnification = 1;
if (document.showForm.mag.value.length != Ø)
{
magnification = Math.abs(parseFloat(document.showForm.mag.value));
if (magnification == Ø)
{
magnification = 1;
}
}
return magnification;
}
function setLongitude(longitude)
{
longitude = Math.abs(longitude);
var degrees = Math.floor(longitude);
longitude = longitude - Math.floor(longitude);
longitude *= 6Ø;
var minutes = Math.floor(longitude)
// complicated math to eliminate eensy teensy fractions of seconds
var seconds = 6Ø * (longitude - Math.floor(longitude))
seconds *= 1ØØØ;
seconds = Math.round(seconds);
seconds /= 1ØØØ;
if (seconds >= 6Ø)
{
seconds -= 6Ø;
minutes++;
}
if (minutes >= 6Ø)
{
minutes -=6Ø;
degrees++;
}
document.showForm.londeg.value = -degrees;
document.showForm.lonmin.value = minutes;
document.showForm.lonsec.value = seconds;
}
function setLatitude(latitude)
{
latitude = Math.abs(latitude);
var degrees = Math.floor(latitude);
latitude = latitude - Math.floor(latitude);
latitude *= 6Ø;
var minutes = Math.floor(latitude)
// complicated math to eliminate eensy teensy fractions of seconds
var seconds = 6Ø * (latitude - Math.floor(latitude))
seconds *= 1ØØØ;
seconds = Math.round(seconds);
seconds /= 1ØØØ;
if (seconds >= 6Ø)
{
seconds -= 6Ø;
minutes++;
}
if (minutes >= 6Ø)
{
minutes -=6Ø;
degrees++;
}
document.showForm.latdeg.value = degrees;
document.showForm.latmin.value = minutes;
document.showForm.latsec.value = seconds;
}
function getLongitude()
{
var londeg = Ø;
if (document.showForm.londeg.value.length != Ø)
{
londeg = Math.abs(parseInt(document.showForm.londeg.value));
}
var lonmin = Ø;
if (document.showForm.lonmin.value.length != Ø)
{
lonmin = Math.abs(parseInt(document.showForm.lonmin.value));
}
var lonsec = Ø;
if (document.showForm.lonsec.value.length != Ø)
{
lonsec = Math.abs(parseFloat(document.showForm.lonsec.value));
}
var lon = -(londeg + ((lonmin + (lonsec / 6Ø)) / 6Ø));
return lon;
}
function getLatitude()
{
var latdeg = Ø;
if (document.showForm.latdeg.value.length != Ø)
{
latdeg = Math.abs(parseInt(document.showForm.latdeg.value));
}
var latmin = Ø;
if (document.showForm.latmin.value.length != Ø)
{
latmin = Math.abs(parseInt(document.showForm.latmin.value));
}
var latsec = Ø;
if (document.showForm.latsec.value.length != Ø)
{
latsec = Math.abs(parseFloat(document.showForm.latsec.value));
}
var lat = latdeg + ((latmin + (latsec / 6Ø)) / 6Ø);
return lat;
}
function display(magnification)
{
document.showForm.mag.value = magnification;
var lon = getLongitude();
setLongitude(lon);
document.realForm.lon.value = lon;
document.realForm.wid.value = 1 / magnification ;
var lat = getLatitude();
setLatitude(lat);
document.realForm.lat.value = lat;
document.realForm.ht.value = 1 / magnification;
document.realForm.submit();
}
function zoom(dir)
{
var magnification = getMagnification();
if (dir < Ø)
{
magnification /= 2;
}
else
{
magnification *= 2;
}
display(magnification);
}
function changeLongitude(dir)
{
var delta = Ø.1 / getMagnification();
var longitude = getLongitude();
if (dir < Ø)
{
longitude -= delta;
}
else
{
longitude += delta;
}
setLongitude(longitude);
}
function changeLatitude(dir)
{
var delta = Ø.1 / getMagnification();
var latitude = getLatitude();
if (dir < Ø)
{
latitude -= delta;
}
else
{
latitude += delta;
}
setLatitude(latitude);
}
//-->
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#ØØØØØØ" TEXT="#FFØØØØ">
<FORM NAME="realForm"
ACTION="http://tiger.census.gov/cgi-bin/mapgen"
METHOD="GET" TARGET="viewer">
<INPUT NAME="lon" TYPE="hidden" SIZE=1Ø>
<INPUT NAME="lat" TYPE="hidden" SIZE=1Ø>
<INPUT NAME="wid" TYPE="hidden" SIZE=1Ø>
<INPUT NAME="ht" TYPE="hidden" SIZE=1Ø>
<INPUT NAME="iwd" TYPE="hidden" SIZE=1Ø VALUE="32Ø">
<INPUT NAME="iht" TYPE="hidden" SIZE=1Ø VALUE="2ØØ">
</FORM>
<CENTER>
<FORM NAME="showForm">
<TABLE BORDER="2" CELLPADDING="2">
<TR>
<TD>
<TABLE BORDER="Ø" CELLPADDING="2">
<TR>
<TD ALIGN="center">
<INPUT TYPE="button" ONCLICK="zoom(1)"
VALUE="ZOOM IN">
</TD>
</TR>
<TR>
<TD ALIGN="center">
<INPUT TYPE="text" NAME="mag" SIZE=4>
</TD>
</TR>
<TR>
<TD ALIGN="center">
<INPUT TYPE="button" ONCLICK="zoom(-1)"
VALUE="ZOOM OUT">
</TD>
</TR>
</TABLE>
</TD>
<TD>
<TABLE BORDER="Ø" CELLPADDING="2">
<TR>
<TD>
East/West <INPUT TYPE="text" NAME="londeg"
SIZE=4><INPUT TYPE="text" NAME="lonmin"
SIZE=2><INPUT TYPE="text" NAME="lonsec"
SIZE=1Ø>
</TD>
<TD ROWSPAN="2">
<TABLE BORDER="Ø" CELLPADDING="Ø">
<TR>
<TD></TD>
<TD>
<PRE><INPUT TYPE="button" VALUE="N"
ONCLICK="changeLatitude(1)"></PRE>
</TD>
<TD></TD>
</TR>
<TR>
<TD>
<PRE><INPUT TYPE="button" VALUE="W"
ONCLICK="changeLongitude(-1)"></PRE>
</TD>
<TD></TD>
<TD>
<PRE><INPUT TYPE="button" VALUE="E"
ONCLICK="changeLongitude(1)"></PRE>
</TD>
</TR>
<TR>
<TD></TD>
<TD>
<PRE><INPUT TYPE="button" VALUE="S"
ONCLICK="changeLatitude(-1)"></PRE>
</TD>
<TD></TD>
</TR>
</TABLE>
</TD>
</TR>
<TR>
<TD>
North/South <INPUT TYPE="text" NAME="latdeg"
SIZE=2><INPUT TYPE="text" NAME="latmin"
SIZE=2><INPUT TYPE="text" NAME="latsec" SIZE=1Ø>
</TD>
</TR>
</TABLE>
</TD>
<TD>
<TABLE BORDER="Ø" CELLPADDING="2">
<TR>
<TD ALIGN="center">
<INPUT TYPE="button"
ONCLICK="display(getMagnification())"
VALUE="GO!">
</TD>
</TR>
<TR>
<TD ALIGN="center"><INPUT TYPE="RESET"></TD>
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
</FORM>
</CENTER>
</BODY>
</HTML>
Improving
the solution
There are many ways of enhancing the JavaScript solution. For starters,
you can change the image size and you can give the user control over the
image size. If you do that, it might be a good idea to define a new window
for the image, because the current 320x200 image size already crowds the
screen.
Also, as mentioned, the Tiger Mapping Service defines a lot of additional
parameters. (For additional details, see the online documentation, which
is listed in the Quick Reference). You can add support for such parameters
as markers for locations on the map, information layers (grids, place names,
and so on), and statistical information.
Modifying
the example for your own use
In your work, you may need to write Web pages that talk to servers whose
interfaces you have no control over. Two common kinds of servers are relational
databases, which may require their input in SQL, and search engines like
Alta Vista or Yahoo!. These interfaces may not meet the needs of your users,
or they may be too complicated for your target audience. Using JavaScript
and the principle of form modification, you can create simple, easy-to-use
interfaces that meet your user's needs while satisfying the requirements
of the server.