ScriptBasic > Tutorials

CGI Programming II

(1/2) > >>

Support:
This thread is an attempt to introduce CGI programming using Basic as your server side CGI scripting language. The goal is to show how using Basic as your server side scripting language and interacting with the browser client via CGI and JavaScript can provide feature rich applications with desktop like  functionality. This tutorial will be Linux / Apache based.

Support:
When you enter a link in your browser address bar, the web server either loads a static html document and sends it verbatim to the browser or executes a CGI program to send the html to the browser.

Static HTML

--- Code: ---<html>
<head>
<title>Hello World</title>
</head>
<body>
<h2>Hello world!</h2>
</body>
</html>

--- End code ---

Perl Script

--- Code: ---#!/usr/bin/perl -wT
print "Content-type: text/html\n\n";
print "<html><head><title>Hello World</title></head>\n";
print "<body>\n";
print "<h2>Hello world!</h2>\n";
print "</body></html>\n";

--- End code ---

ScriptBasic Script

--- Code: ---#!/usr/bin/scriba -c

INCLUDE cgi.bas

cgi::Header 200,"text/html"
cgi::FinishHeader

PRINT """<html>
<head>
<title>Hello World</title>
</head>
<body>
<h2>Hello world!</h2>
</body>
</html>
"""

--- End code ---

The CGI program has the advantage of dynamically creating html content based on session variables, form data and database access. The next installment will show interaction with the browser client using a form to collect user input and pass that data to the CGI program to validate and process.

Support:
CGI is not a language. It's a protocol that can be used to communicate between Web forms and your program. A CGI script can be written in any language that can read STDIN, write to STDOUT, and read environment variables.

The following echo CGI program is a great way to see what is happening between the browser and the web server when a page is submitted. There are two primary requests made to the server. The GET request is normally used for the initial page load of the document. The POST request works like the GET but also passes the <form> variables to your CGI program via STDIN. When your CGI program is called by the web server, the system environment variables are web server based and not the OS based variables you would find if running your program in a console. Your CGI program uses it's STDOUT (print) function to send the generated HTML to the browser. This is really CGI in a nutshell and what everything else is built on.

BCX Echo

--- Code: ---DIM POST$

PRINT "Content-type: text/html"
PRINT ""
PRINT "<HTML>"
PRINT "<HEAD>"
PRINT "<TITLE>Echo CGI</TITLE>"
PRINT "</HEAD>"
PRINT "<BODY>"
PRINT "<H1>View CGI Parameters</H1>"
PRINT "This page shows the CGI parameters by submitting to itself."
PRINT "<PRE>"
PRINT ""
PRINT "CGI system variables"
PRINT "--------------------"
PRINT ""
PRINT "ServerSoftware  = ", ENVIRON$("SERVER_SOFTWARE")
PRINT "ServerName      = ", ENVIRON$("SERVER_NAME")
PRINT "GatewayInterface= ", ENVIRON$("GATEWAY_INTERFACE")
PRINT "ServerProtocol  = ", ENVIRON$("SERVER_PROTOCOL")
PRINT "ServerPort      = ", ENVIRON$("SERVER_PORT")
PRINT "RequestMethod   = ", ENVIRON$("REQUEST_METHOD")
PRINT "PathInfo        = ", ENVIRON$("PATH_INFO")
PRINT "PathTranslated  = ", ENVIRON$("PATH_TRANSLATED")
PRINT "ScriptName      = ", ENVIRON$("SCRIPT_NAME")
PRINT "GET QueryString = ", ENVIRON$("QUERY_STRING")
IF ENVIRON$("REQUEST_METHOD") = "POST" THEN
  INPUT POST$
ELSE
  POST$ = ""
END IF
PRINT "POST Form Data  = ", POST$
PRINT "RemoteHost      = ", ENVIRON$("REMOTE_HOST")
PRINT "RemoteAddress   = ", ENVIRON$("REMOTE_ADDR")
PRINT "AuthType        = ", ENVIRON$("AUTH_TYPE")
PRINT "RemoteUser      = ", ENVIRON$("REMOTE_USER")
PRINT "RemoteIdent     = ", ENVIRON$("REMOTE_IDENT")
PRINT "ContentType     = ", ENVIRON$("CONTENT_TYPE")
PRINT "ContentLength   = ", ENVIRON$("CONTENT_LENGTH")
PRINT "UserAgent       = ", ENVIRON$("HTTP_USER_AGENT")
PRINT "Cookie          = ", ENVIRON$("HTTP_COOKIE")
PRINT "Referer         = ", ENVIRON$("HTTP_REFERER")
PRINT "Password        = ", ENVIRON$("HTTP_PASSWORD")
PRINT "</PRE>"
PRINT "<TABLE><TR><TD BORDER=0 BGCOLOR='EEEEEE'><PRE>"
PRINT "A simple form to POST parameters:<BR>"
PRINT "<FORM METHOD='POST' ACTION='/cgi-bin/echo.cgi'>"
PRINT "<INPUT TYPE='TEXT' VALUE='DEFAULT TEXT' NAME='TEXT-FIELD'>"
PRINT "<INPUT TYPE='SUBMIT' NAME='SUBMIT-BUTTON' VALUE=' POST '>"
PRINT "</FORM></PRE></TD>"
PRINT "<TD BORDER=1 width='20'>&nbsp;</TD>"
PRINT "<TD BORDER=0 BGCOLOR='EEEEEE'><PRE>"
PRINT "A simple form to GET parameters:<BR>"
PRINT "<FORM METHOD='GET' ACTION='/cgi-bin/echo.cgi'>"
PRINT "<INPUT TYPE='TEXT' VALUE='DEFAULT TEXT' NAME='TEXT-FIELD'>"
PRINT "<INPUT TYPE='SUBMIT' NAME='SUBMIT-BUTTON' VALUE=' GET '>"
PRINT "</FORM></PRE></TD></TR></TABLE>"
PRINT "</BODY></HTML>"

--- End code ---

ScriptBasic Echo

--- Code: ---#! /usr/bin/scriba -c
global const nl = "\n"
Const NumberOfCookies = 3

include cgi.bas

option cgi$Method cgi::Get or cgi::Upload

' cgi::RequestBasicAuthentication "login password"
cgi::Header 200,"text/html"

'
' We are setting several cookies. The expire time is ten seconds so you can test that
' the cookies are being sent by the browser. Remeber, their only valid for 10 seconds so
' be quick with a submit
'
for i=1 to NumberOfCookies
  ' cookie(i) is i, no domain is defined, path is /, expires after 10 seconds, not secure
  cgi::SetCookie "cookie" & i,i,undef,"/",gmtime()+10,false
next i

cgi::FinishHeader

'-------------------------------------------------------
print """<HTML>
<HEAD>
<title>CGI parameter testing</title>
</HEAD>
<BODY><font face="VERDANA" size="2">
<H1>View CGI Parameters</H1>
This page shows the cgi parameters the way it was uploaded.
<!-- here is the result of the previous HTTP request -->
<FONT SIZE="3">
<PRE>

CGI system variables
--------------------

"""
'-------------------------------------------------------

print "ServerSoftware  = ",cgi::ServerSoftware(), nl
print "ServerName      = ",cgi::ServerName(), nl
print "GatewayInterface= ",cgi::GatewayInterface(),nl
print "ServerProtocol  = ",cgi::ServerProtocol(), nl
print "ServerPort      = ",cgi::ServerPort(), nl
print "RequestMethod   = ",cgi::RequestMethod(), nl
print "PathInfo        = ",cgi::PathInfo(), nl
print "PathTranslated  = ",cgi::PathTranslated(), nl
print "ScriptName      = ",cgi::ScriptName(), nl
print "QueryString     = ",cgi::QueryString(), nl
print "RemoteHost      = ",cgi::RemoteHost(), nl
print "RemoteAddress   = ",cgi::RemoteAddress(), nl
print "AuthType        = ",cgi::AuthType(), nl
print "RemoteUser      = ",cgi::RemoteUser(), nl
print "RemoteIdent     = ",cgi::RemoteIdent(), nl
print "ContentType     = ",cgi::ContentType(), nl
print "ContentLength   = ",cgi::ContentLength(), nl
print "UserAgent       = ",cgi::UserAgent(), nl
print "Cookie          = ",cgi::RawCookie(), nl

print "Referer         = ",cgi::Referer(),nl
print "Password        = ",Environ("HTTP_PASSWORD"),nl
print "Full auth string= ",Environ("HTTP_AUTHORIZATION"),nl
print "\nCookies:\n"
for i=1 to NumberOfCookies
  print "cookie" & i," ",cgi::Cookie("cookie" & i),"\n"
next i

print "Text field using Param(\"TEXT-FIELD\") is ",cgi::Param("TEXT-FIELD"),nl,nl


if cgi::RequestMethod() = "GET" then
  print "GET text field using GetParam(\"TEXT-FIELD\") is ",cgi::GetParam("TEXT-FIELD"),nl
end if

if cgi::RequestMethod() = "POST" then
  print "POST text field using PostParam(\"TEXT-FIELD\") is ",cgi::PostParam("TEXT-FIELD"),nl
  if cgi::ContentType() like "multipart*" then
    print "Original file name is ",cgi::FileName("FILE-UPLOAD-NAME"),nl
    if cgi::FileLength("FILE-UPLOAD-NAME") > 0 then
      print "File with a length of ",cgi::FileLength("FILE-UPLOAD-NAME")," bytes was saved\n"
      on error goto NoSave
      cgi::SaveFile "FILE-UPLOAD-NAME","/var/www/vhosts/scriptbasic.org/httpdocs/upload/newup.txt"
    else
      print "There is no uploaded file."
    end if
  end if
end if

print """</PRE><TABLE><TR><TD BORDER=0 BGCOLOR="EEEEEE"><PRE>
A simple form to POST parameters:<BR>
<FORM METHOD="POST" ACTION="/cgi-bin/echo.bas">
<INPUT TYPE="TEXT" VALUE="DEFAULT TEXT" NAME="TEXT-FIELD">
<INPUT TYPE="SUBMIT" NAME="SUBMIT-BUTTON" VALUE=" POST ">
</FORM>
</PRE></TD><TD BORDER=1 width="20">&nbsp;</TD><TD BORDER=0 BGCOLOR="EEEEEE"><PRE>
A simple form to GET parameters:<BR>
<FORM METHOD="GET" ACTION="/cgi-bin/echo.bas">
<INPUT TYPE="TEXT" VALUE="DEFAULT TEXT" NAME="TEXT-FIELD">
<INPUT TYPE="SUBMIT" NAME="SUBMIT-BUTTON" VALUE=" GET ">
</FORM>
</PRE></TD></TR></TABLE><PRE>
<hr>
A simple form to UPLOAD a file:<BR>
<FORM METHOD="POST" ACTION="/cgi-bin/echo.bas" ENCTYPE="multipart/form-data">
<INPUT TYPE="TEXT" VALUE="DEFAULT TEXT" NAME="TEXT-FIELD">
<INPUT TYPE="FILE" VALUE="FILE-UPLOAD-VALUE" NAME="FILE-UPLOAD-NAME">
<INPUT TYPE="SUBMIT" NAME="SUBMIT-BUTTON" VALUE="UPLOAD FILE">
</FORM>
<hr>
</BODY>
</HTML>
"""
stop
NoSave:

print "An error has happened saving the file. Code =",error(),nl

resume next

--- End code ---

ScriptBasic CGI extension module documentation

Support:
Before we get too far down the road, I thought I would introduce database use within your CGI scripts. ScriptBasic uses it's associative array functionality with it's DB interface like PHP does with their MySQL interface.

Table Layout


PHP

--- Code: ---<html>
<body>
<?
mysql_connect("localhost", "user", "password") or die(mysql_error());
mysql_select_db("dbname") or die(mysql_error());

$result = mysql_query("SELECT * FROM contact");
echo "<TABLE border=1 cellpadding=3>";
while($row = mysql_fetch_assoc($result)){
echo "<TR>",
"<TD>".$row['ID']."</TD>",
"<TD>".$row['NAME']."</TD>",
"<TD>".$row['ADDRESS']."</TD>",
"<TD>".$row['CITY']."</TD>",
"<TD>".$row['STATE']."</TD>",
"<TD>".$row['ZIP']."</TD>",
"<TD>".$row['PHONE']."</TD>",
"<TD>".$row['EMAIL']."</TD>",
"<TD>".$row['URL']."</TD>",
"</TR>";
}
echo "</table>";
?>
</body>
</html>

--- End code ---

ScriptBasic

--- Code: ---#!/usr/bin/scriba -c

INCLUDE cgi.bas
INCLUDE mysql.bas

OPTION cgi$Method cgi::Post or cgi::Get

dbh = mysql::RealConnect("localhost","user","password","dbname")

mysql::query(dbh,"SELECT * FROM contact")

cgi::Header 200,"text/html"
cgi::FinishHeader

PRINT """
<HTML>
<HEAD>
<title>mySQL testing</title>
</HEAD>
<BODY>
"""
PRINT """<FONT face="Verdana, Arial, Helvetica, sans-serif">"""

PRINT """<TABLE border="1" cellpadding="3">"""

WHILE mysql::FetchHash(dbh,column)

PRINT "<TR>"
PRINT "<TD>",column{"ID"},"</TD>"
PRINT "<TD>",column{"NAME"},"</TD>"
PRINT "<TD>",column{"ADDRESS"},"</TD>"
PRINT "<TD>",column{"CITY"},"</TD>"
PRINT "<TD>",column{"STATE"},"</TD>"
PRINT "<TD>",column{"ZIP"},"</TD>"
PRINT "<TD>",column{"PHONE"},"</TD>"
PRINT "<TD>",column{"EMAIL"},"</TD>"
PRINT "<TD>",column{"URL"},"</TD>"
PRINT "</TR>"

WEND

PRINT "</TABLE>"

PRINT "<BR>"
PRINT "The database handle is: <b>",dbh,"</b><BR>"
PRINT "Affected rows by SELECT: <b>",mysql::AffectedRows(dbh),"</b><BR>"
PRINT "Character set name is: <b>",mysql::CharacterSetName(dbh),"</b><BR>"
PRINT "Last error is: <b>",mysql::ErrorMessage(dbh),"</b><BR>"
PRINT "Client info is: <b>",mysql::GetClientInfo(),"</b><BR>"
PRINT "Host info is: <b>",mysql::GetHostInfo(dbh),"</b><BR>"
PRINT "Proto info is: <b>",mysql::GetProtoInfo(dbh),"</b><BR>"
PRINT "Server info is: <b>",mysql::GetServerInfo(dbh),"</b><BR>"
PRINT "PING result: <b>",mysql::Ping(dbh),"</b><BR>"
PRINT "Thread ID: <b>",mysql::ThreadId(dbh),"</b><BR>"
PRINT "Status is: <b>",mysql::Stat(dbh),"</b><BR>"

PRINT "</FONT>"

PRINT """
</BODY>
</HTML>
"""

mysql::Close(dbh)

END

--- End code ---

ScriptBasic MySQL extension module documentation

Support:

--- Quote ---JavaScript and Java

A common misconception is that JavaScript is similar or closely related to Java; this is not so. Both have a C-like syntax, are object-oriented, are typically sandboxed and are widely used in client-side Web applications, but the similarities end there. Java has static typing; JavaScript's typing is dynamic (meaning a variable can hold an object of any type and cannot be restricted). Java is loaded from compiled bytecode; JavaScript is loaded as human-readable code. C is their last common ancestor language.

Nonetheless, JavaScript was designed with Java's syntax and standard library in mind. In particular, all Java keywords are reserved in JavaScript, JavaScript's standard library follows Java's naming conventions, and JavaScript's Math and Date classes are based on those from Java 1.0.

--- End quote ---

I'm working on a ScriptBasic address book like example that will show using a hidden IFrame and AJAX (using Prototype) to submit requests to the server to allow browsing records without refreshing the page. The following article is from the Apple site back in 2002. (before everyone started touting AJAX as the answer to client/server web scripting)

Remote Scripting with IFRAME

Scripting Iframes - Tutorial and Examples

I thought I would post this example as a preface to how the upcoming address book example in ScriptBasic will work.


--- Code: ---<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html><head><title>Remote Scripting with an IFrame - complexer client page</title>
<meta http-equiv="pragma" content="no-cache">
<script type="text/javascript">

var IFrameObj; // our IFrame object
function callToServer(theFormName) {
if (!document.createElement) {return true};
var IFrameDoc;

// We'll build our URL by checking which state
// has been selected in the drop down menu
var stateEl = document.forms[theFormName].state
var theState = stateEl.options[stateEl.selectedIndex].value
if (theState=='') {return false}; // no state has been selected
var URL = "http://developer.apple.com/internet/webcontent/states/"+theState+".html"

//provide a "loading" message
var responseMessage = document.getElementById('responseMessage');
responseMessage.style.display = 'inline';
responseMessage.innerHTML = 'loading data...';

if (!IFrameObj && document.createElement) {
// create the IFrame and assign a reference to the
// object to our global variable IFrameObj.
// this will only happen the first time
// callToServer() is called
try {
var tempIFrame=document.createElement('iframe');
tempIFrame.setAttribute('id','RSIFrame');
tempIFrame.style.border='0px';
tempIFrame.style.width='0px';
tempIFrame.style.height='0px';
IFrameObj = document.body.appendChild(tempIFrame);

if (document.frames) {
// this is for IE5 Mac, because it will only
// allow access to the document object
// of the IFrame if we access it through
// the document.frames array
IFrameObj = document.frames['RSIFrame'];
}
} catch(exception) {
// This is for IE5 PC, which does not allow dynamic creation
// and manipulation of an iframe object. Instead, we'll fake
// it up by creating our own objects.
iframeHTML='<iframe id="RSIFrame" style="';
iframeHTML+='border:0px;';
iframeHTML+='width:0px;';
iframeHTML+='height:0px;';
iframeHTML+='"><\/iframe>';
document.body.innerHTML+=iframeHTML;
IFrameObj = new Object();
IFrameObj.document = new Object();
IFrameObj.document.location = new Object();
IFrameObj.document.location.iframe = document.getElementById('RSIFrame');
IFrameObj.document.location.replace = function(location) {
this.iframe.src = location;
}
}
}

if (navigator.userAgent.indexOf('Gecko') !=-1 && !IFrameObj.contentDocument) {
// we have to give NS6 a fraction of a second
// to recognize the new IFrame
setTimeout('callToServer("'+theFormName+'")',10);
return false;
}

if (IFrameObj.contentDocument) {
// For NS6
IFrameDoc = IFrameObj.contentDocument;
} else if (IFrameObj.contentWindow) {
// For IE5.5 and IE6
IFrameDoc = IFrameObj.contentWindow.document;
} else if (IFrameObj.document) {
// For IE5
IFrameDoc = IFrameObj.document;
} else {
return true;
}

IFrameDoc.location.replace(URL);
return false;
}

// handleResponse is passed two parameters when called from the onload
// event of the pages loaded in the hidden IFRAME:
// st: a string indicating which state is being loaded
// doc: the document object of the page loaded in the IFRAME
function handleResponse(st, doc) {
// get a reference to the multiple select list, which we will populate
// with the data from the document loaded in the IFRAME
var namesEl = document.forms.stateForm.zipNames

// clear earlier records from the multiple select list
namesEl.length = 0

// get a reference to the DIV containing the data for this state
var dataEl = doc.getElementById(st)

// get a reference to the collection of the children elements of
// our DIV containing the data (this collection is the DIVs containing
// the actual zip names)
namesColl = dataEl.childNodes

// for easy scripting, assign the number of ZIP names for this state
// to a variable
var numNames = namesColl.length

// iterate through the collection of zip Names and
// create an option element for each one
for (var q=0; q<numNames; q++) {
if (namesColl[q].nodeType!=1) continue; // it's not an element node, let's skedaddle
var str = '' // used to store the text we'll use in the new option
str+= namesColl[q].id + ' ('

// get a reference to the collection of the children elements of
// this DIV (this collection contains the zip codes that fall under this zip name)

var zipsColl = doc.getElementById(namesColl[q].id).childNodes
var numZips = zipsColl.length

// iterate through this collection of zips and each one to the string
for (var r=0; r<numZips; r++) {
if (zipsColl[r].nodeType!=1) continue; // it's not an element node, let's skedaddle
str += zipsColl[r].id + ' '
}
str+= ')'

// create a new option element and add it to the zipNames form element
newOption = new Option(str)
namesEl.options[namesEl.length] = newOption
}

//provide a "success" message
var responseMessage = document.getElementById('responseMessage');
responseMessage.innerHTML = 'loaded records from <a href="'+doc.location+'">this external file<\/a>.';
}
</script>

</head>
<body>

<div id="theFormDiv">
<form name="stateForm" id="stateForm" action="server.html">
Select a state from this menu:
<select name="state" onchange="callToServer(this.form.name)">
<option selected value="">
<option value="AL"> Alabama
<option value="AK"> Alaska
<option value="AZ"> Arizona
<option value="AR"> Arkansas
<option value="CA"> California
<option value="CO"> Colorado
<option value="CT"> Connecticut
<option value="DE"> Delaware
<option value="DC"> District of Columbia
<option value="FL"> Florida
<option value="GA"> Georgia
<option value="HI"> Hawaii
<option value="ID"> Idaho
<option value="IL"> Illinois
<option value="IN"> Indiana
<option value="IA"> Iowa
<option value="KS"> Kansas
<option value="KY"> Kentucky
<option value="LA"> Louisiana
<option value="ME"> Maine
<option value="MD"> Maryland
<option value="MA"> Massachusetts
<option value="MI"> Michigan
<option value="MN"> Minnesota
<option value="MS"> Mississippi
<option value="MO"> Missouri
<option value="MT"> Montana
<option value="NE"> Nebraska
<option value="NV"> Nevada
<option value="NH"> New Hampshire
<option value="NJ"> New Jersey
<option value="NM"> New Mexico
<option value="NY"> New York
<option value="NC"> North Carolina
<option value="ND"> North Dakota
<option value="OH"> Ohio
<option value="OK"> Oklahoma
<option value="OR"> Oregon
<option value="PA"> Pennsylvania
<option value="RI"> Rhode Island
<option value="SC"> South Carolina
<option value="SD"> South Dakota
<option value="TN"> Tennessee
<option value="TX"> Texas
<option value="UT"> Utah
<option value="VT"> Vermont
<option value="VA"> Virginia
<option value="WA"> Washington
<option value="WV"> West Virginia
<option value="WI"> Wisconsin
<option value="WY"> Wyoming
</select><br><br>
Once a state has been selected, the multiple select list below will be populated with a partial list of Zip code names drawn from a database of html files that are loaded via a hidden IFRAME. (Zip code data drawn from sources on <a href="http://www.census.gov/geo/www/gazetteer/places.html">the US Census Bureau site</a>).
<select multiple="multiple" name="zipNames" style="width:100%; height:400px">
</select><br><br>
</form>
</div>

<div id="responseMessage" style="display:none"></div>
</body>
</html>

--- End code ---

In another life when I was into panorama photography, I used the NASA equirectanglar Blue Marble image in a Java Applet viewer I normally used to display 360 'virtual tour' images. The projection is if the surface of the earth was painted on the inside of a sphere and your standing in the middle. Google Maps has been scripted into to the demo as well.

Take the Earth for a spin

Note: Drag (or use arrow keys) the image to pan around the globe. (+/- for zoom)

Hint: If you click on the Google graphic, (lower left corner of map) it will open a new tab in Google Maps with your current view setting.


--- Code: ---<html>
<head>
<title>The Blue Marble</title>
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key=ABQIAAAAKVmOoKOF2E2u7QCPFHa89hQHrkFAUW_sbTtysgTBKCd6Skuu4hRoWJVnHTyx78GAQyuNGDLOIxcAPw" type="text/javascript"></script>
<script type="text/javascript">
var map;
function onLoad() {
map = new GMap2(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(0,0), 4);
}
function setloc() {
map.setCenter(new GLatLng(parseFloat(document.forms["cn"].lat.value), parseFloat(document.forms["cn"].lon.value)), 8);
}
</script>
<script language="JavaScript1.1">
function getview(p,t,f) {
document.cn.pan.value = p ;
document.cn.tilt.value = t ;
}
</script>
</head>
<body onload="onLoad()">
<applet code=ptviewer.class width=674 height=444 archive="ptviewer.jar">
   <param name="file" value="earth_2700x1350.jpg">
   <param name="wait" value="globe.gif">
   <param name="fov" value="68">
   <param name="quality" value="6">
   <param name="cursor" value="MOVE">
   <param name=shotspot0 value="x330 y203 q i'targetbw.gif'">
   <param name=showToolbar value="true">
   <param name=imgLoadFeedback value="false">
   <param name="fovmin" value="35">
   <param name="fovmax" value="90">
   <param name="getview" value="getview">
</applet>
<table>
<form name="cn">
  <tr>
    <td width="145">North&#176; (+)<br><input type="text" size=18 ID="lat" name="tilt" value="" ><br>South&#176; (-)</td>
    <td width="145">East&#176; (+)<br><input type="text" size=18 ID="lon" name="pan" value="" ><br>West&#176; (-)</td>
    <td width="145" align="middle"><input type="button" name=mapit value=" MAP " onclick="setloc()"></td>
  </tr>
</form>
</table>
<br>
<div id="map" style="width: 674px; height: 444px"></div>
</body>
</html>

--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version