|
support
|
 |
« on: October 08, 2009, 03:11:23 PM » |
|
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.
|
|
|
|
|
Logged
|
|
|
|
|
support
|
 |
« Reply #1 on: October 08, 2009, 03:12:51 PM » |
|
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<html> <head> <title>Hello World</title> </head> <body> <h2>Hello world!</h2> </body> </html>
Perl Script#!/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";
ScriptBasic Script#!/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> """
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.
|
|
|
|
|
Logged
|
|
|
|
|
support
|
 |
« Reply #2 on: October 08, 2009, 03:14:30 PM » |
|
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 EchoDIM 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'> </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>"
ScriptBasic Echo#! /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"> </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
ScriptBasic CGI extension module documentation
|
|
|
|
|
Logged
|
|
|
|
|
support
|
 |
« Reply #3 on: October 08, 2009, 03:16:09 PM » |
|
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<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>
ScriptBasic#!/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
ScriptBasic MySQL extension module documentation
|
|
|
|
|
Logged
|
|
|
|
|
support
|
 |
« Reply #4 on: October 08, 2009, 03:18:15 PM » |
|
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.
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 IFRAMEScripting Iframes - Tutorial and ExamplesI thought I would post this example as a preface to how the upcoming address book example in ScriptBasic will work. <!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>
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 spinNote: 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. <html> <head> <title>The Blue Marble</title> <script src="http://maps.google.com/maps?file=api&v=2&sensor=false&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° (+)<br><input type="text" size=18 ID="lat" name="tilt" value="" ><br>South° (-)</td> <td width="145">East° (+)<br><input type="text" size=18 ID="lon" name="pan" value="" ><br>West° (-)</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>
|
|
|
|
|
Logged
|
|
|
|
|
support
|
 |
« Reply #5 on: October 08, 2009, 03:19:37 PM » |
|
I haven't been much of a AJAX fan due to the layers of protocol getting something simple like a remote/hidden submit to work in my applications. I stumbled across a really nice AJAX framework that I thought I would share and include as part of this tutorial. Prototype JavaScript FrameworkWhy Prototype?
Why didn't I just create a plain old JavaScript object (POJO) for my application, instead of introducing an open source library? For one, Prototype includes a nifty collection of JavaScript shortcuts that reduce typing and help avoid the reinvention of the wheel. The commonly touted shortcut is $("mydiv"), which is a Prototype function that returns a Document Object Model (DOM) Element associated with the HTML tag with id "mydiv". That sort of concision alone is probably worth the cost of setting up Prototype. It's the equivalent of:
document.getElementById("mydiv");
Another useful Prototype shortcut is $F("mySelect"), for returning the value of an HTML form element on a web page, such as a selection list. Once you get used to Prototype's austere, Perlish syntax, you will use these shortcuts all the time. Prototype also contains numerous custom objects, methods, and extensions to built-in JavaScript objects, such as the Enumeration and Hash objects (which I discuss below).
Finally, Prototype also wraps the functionality of XMLHttpRequest with its own Ajax.Request and related objects, so that you don't have to bother with writing code for instantiating this object for various browsers.
Try.these
Try.these(Function...) -> firstOKResult
Accepts an arbitrary number of functions and returns the result of the first one that doesn't throw an error.
More on AJAX soon ...Your probably saying at this point, "What does JavaScript & AJAX have to do with CGI programming with Basic." If your interested in creating desktop like applications in a browser then what CGI is to the server, JavaScript (AJAX) is to the client. Your CGI applications are responsible for dynamically creating HTML/JavaScript and sending it back to the client. (a stream of text which your browser interprets to render your pages) You can request a static HTML page, a page dynamically created based on criteria and a page with embedded localized/remote scripting.
|
|
|
|
|
Logged
|
|
|
|
|
support
|
 |
« Reply #6 on: October 08, 2009, 03:27:47 PM » |
|
I recently had to write a shopping cart for a client's site running ScriptBasic and thought I would add it to my CGI tutorial. This cart can add / remove items and calculates the total with a check for a minimum quantity of 5. ' Program: cart ' Version: 1.0 ' Date: 2009-08-15 ' By: JRS
GLOBAL CONST NL = "\n"
INCLUDE cgi.bas INCLUDE mysql.bas INCLUDE mt.bas INCLUDE t.bas
OPTION cgi$Method cgi::Get OR cgi::Post
session_id = cgi::Cookie("CART")
New_Session:
IF session_id = undef THEN session_id = mt::NewSessionId() mt::SetSessionId(session_id) ELSE IF mt::CheckSessionId(session_id) = False THEN session_id = undef GOTO New_Session END IF mt::SetSessionId(session_id) END IF
dbh = mysql::Connect("CART_DB")
' *** START GET *** IF cgi::RequestMethod() = "GET" THEN
' Check for Add/Remove/Display Mode module_number = cgi::GetParam("module") IF module_number = undef THEN cartmode = "display" ELSE cartmode = "add" END IF
' Check for existing cart array cartstr = mt::GetSessionVariable("cartstr") IF cartstr = undef THEN itemcount = 0 ELSE t::StringToArray(mycart, cartstr) itemcount = UBOUND(mycart) END IF IF cartmode = "add" THEN itemcount += 1
' REMOVE Mode delmod = cgi::GetParam("remove") IF delmod >= 1 AND delmod <= itemcount THEN thisline = 1 UNDEF tmpcart FOR x = 1 TO itemcount IF delmod <> x THEN tmpcart[thisline,0] = thisline tmpcart[thisline,1] = mycart[x,1] tmpcart[thisline,2] = mycart[x,2] tmpcart[thisline,3] = mycart[x,3] tmpcart[thisline,4] = mycart[x,4] tmpcart[thisline,5] = mycart[x,5] thisline += 1 END IF NEXT x UNDEF mycart mycart = tmpcart itemcount -= 1 IF itemcount = 0 THEN UNDEF cartstr, mycart mt::SetSessionVariable("cartstr", undef) ELSE cartstr = t::ArrayToString(mycart) mt::SetSessionVariable("cartstr", cartstr) END IF END IF
' ADD Mode IF cartmode = "add" THEN mycart[itemcount, 0] = itemcount mycart[itemcount, 1] = module_number mysql::query(dbh,"SELECT PTITLE,PPRICE FROM Modules WHERE PNUM = '" & module_number & "'") mysql::FetchArray(dbh, modrow) mycart[itemcount, 2] = modrow[0] mycart[itemcount, 3] = modrow[1] mycart[itemcount, 4] = 5 mycart[itemcount, 5] = FORMAT("%~####.00~", 5 * modrow[1]) cartstr = t::ArrayToString(mycart) mt::SetSessionVariable("cartstr", cartstr) END IF
' Cart Empty IF ISUNDEF(mycart) THEN cgi::Header 302,"text/html" PRINT "Location: /home/curricula\n" cgi::SetCookie("CART", session_id, undef, undef, gmtime() + 2700, false) cgi::FinishHeader END END IF ' *** END GET ***
ELSE
' *** START POST *** IF cgi::PostParam("button") = "Continue to Checkout" THEN cgi::Header 302,"text/html" PRINT "Location: /home/checkout\n" cgi::SetCookie("CART", session_id, undef, undef, gmtime() + 2700, false) cgi::FinishHeader END END IF
cartstr = mt::GetSessionVariable("cartstr") t::StringToArray(mycart, cartstr) itemcount = UBOUND(mycart) FOR x = 1 TO itemcount mycart[x, 4] = cgi::PostParam("line" & x) IF VAL(mycart[x,4]) < 5 THEN mycart[x,4] = 5 END IF mycart[x, 5] = FORMAT("%~####.00~", mycart[x,4] * mycart[x,3]) NEXT x cartstr = t::ArrayToString(mycart) mt::SetSessionVariable("cartstr", cartstr) END IF ' *** END POST ***
' Build Standard Header cgi::Header(200, "text/html") cgi::SetCookie("CART", session_id, undef, undef, gmtime() + 2700, false) cgi::FinishHeader()
PRINT """ <HTML> <HEAD> <TITLE>Order Cart</TITLE> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> <STYLE type=text/css>A { TEXT-DECORATION: underline } A:active { + 1 COLOR: #103366; TEXT-DECORATION: underline } - 1 A:hover { COLOR: #103366; TEXT-DECORATION: underline } A:visited { COLOR: #666666; TEXT-DECORATION: underline } </STYLE> </HEAD> <BODY BGCOLOR=#FFFFFF text="#000000" link="#103366" vlink="#666666" leftmargin="0" topmargin="0" alink="#666666" background="/media/CART/images/background.gif"> """
INCLUDE "header"
PRINT """ <TABLE WIDTH=775 BORDER=0 CELLPADDING=0 CELLSPACING=0> <TR> <TD VALIGN=TOP bgcolor="#103366" width="70" height="523" style="border:1px solid; border-color : #000000;"> """
INCLUDE "left_nav"
PRINT """ </TD> <TD VALIGN=TOP WIDTH=757 height="523" bgcolor="#FFFFFF"> <table border=0 cellspacing=0 cellpadding=0 width=672> <tr align="right"> <td height="22" colspan=3> </td> </tr> <tr valign="top"> <td valign="top"> <TABLE CELLSPACING="0" CELLPADDING="18" BORDER="0"><TR VALIGN="TOP"><TD WIDTH="100%" ALIGN="LEFT"> <font color="#000000" size="2" face="verdana"><a href="/home/curricula">Return to Section Listing</a></font><BR><BR> <font color="#000000" size="2" face="verdana"> <BR> <FONT face="verdana,arial" size=3 style="font-size:18px;" class=font.normal color="#103366"><B>Order Cart</B></font><BR><BR> <TABLE border=1 cellspacing=2 cellpadding=4 width=100%> <form method=post action="/home/cart"> <TR VALIGN="Top"> <TD WIDTH=80 align=center bgcolor="#103366"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal color=#FFFFFF><B>Module #</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td> <TD WIDTH=100% align=left bgcolor="#103366"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal color=#FFFFFF><B>Module Title</B></font></td> <TD WIDTH=80 align=center bgcolor="#103366"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal color=#FFFFFF><B>Price</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td> <TD WIDTH=60 align=center bgcolor="#103366"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal color=#FFFFFF><B>Quantity</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=60 HEIGHT=1 border=0></td> <TD WIDTH=80 align=center bgcolor="#103366"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal color=#FFFFFF><B>Subtotal</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td> </tr> """ FOR x = 1 TO itemcount PRINT """ <TR VALIGN="Top"> <TD WIDTH=80 align=center><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal>""" & mycart[x,1] & """<BR><a href="/home/cart?remove=""" & mycart[x,0] & """\">REMOVE</a></font></td> <TD WIDTH=200 align=left><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>""" & mycart[x,2] & """</B></font></td> <TD WIDTH=80 align=center><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal>""" & FORMAT("%~$##.00~",mycart[x,3]) & """</font></td> <TD WIDTH=60 align=center><input type=text name="line""" & x & """\" value=\"""" & mycart[x,4] & """\" size="4" style="text-align:right;"></td> <TD WIDTH=80 align=right><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>""" & FORMAT("%~$#,###.00~",mycart[x,5]) & """</B></font></td> </tr> <TR VALIGN="Top"> <TD colspan=4 align=right bgcolor="#103366"><IMG SRC="/media/CART/images/spacer.gif" WIDTH=10 HEIGHT=1 border=0></td> </tr> """ NEXT x
total_qty = 0 total_amt = 0
FOR x = 1 TO itemcount total_qty = total_qty + mycart[x,4] total_amt = total_amt + mycart[x,5] NEXT x
IF total_qty >= 5 AND total_qty <= 10 THEN shipping = 5.00 ELSE IF total_qty >= 11 AND total_qty <= 25 THEN shipping = 10.00 ELSE IF total_qty >= 26 AND total_qty <= 50 THEN shipping="15.00" ELSE shipping="20.00" END IF
PRINT """ <TR VALIGN="Top"> <TD colspan=4 align=right bgcolor="#e1e1e1"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>Subtotal</B></font><IMG SRC="/media/CART/images/spacer.gif" WIDTH=10 HEIGHT=1 border=0></td> <TD WIDTH=80 align=right><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>""" & FORMAT("%~$#,###.00~",total_amt) & """</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td> </tr>
<TR VALIGN="Top"> <TD colspan=4 align=right bgcolor="#e1e1e1"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>Shipping & Handling<BR></B></font><IMG SRC="/media/CART/images/spacer.gif" WIDTH=10 HEIGHT=1 border=0></td> <TD WIDTH=80 align=right><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>""" & FORMAT("%~$#,###.00~",shipping) & """</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td> </tr> """
total_inv = total_amt + shipping
PRINT """ <TR VALIGN="Top"> <TD colspan=4 align=right bgcolor="#e1e1e1"><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>Total Due</B></font><IMG SRC="/media/CART/images/spacer.gif" WIDTH=10 HEIGHT=1 border=0></td> <TD WIDTH=80 align=right><FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><B>""" & FORMAT("%~$#,###.00~",total_inv) & """</B></font><BR><IMG SRC="/media/CART/images/spacer.gif" WIDTH=80 HEIGHT=1 border=0></td> </tr> </table> <BR><BR> <FONT face="verdana,arial" size=1 style="font-size:10px;" class=font.normal><input type=submit name=button value="Change Quantities"> You can modify all of the quantity boxes, then click here. <BR><BR> <input type=submit name=button value="Continue to Checkout"></form> <BR><BR><BR><BR></font><br> </TD> </TR> </TABLE> <p><font size="2" face="verdana"> </font><br> <font size="2" face="verdana"> </font> <center> </center></p> </td> </tr> <tr> </tr> </table> </TD></TR><tr><TD COLSPAN=5 bgcolor="#0C0533" height="20" align="center"><font color="#CCCCCC" face="Verdana, Arial, Helvetica, sans-serif" size="1">Copyright © 2000-2009 DBA Company</font></td> </tr></TABLE> </center> <map name="Map3"> <area shape="rect" coords="5,0,283,91" href="/home/start"> </map> </BODY> </HTML> """

|
|
|
|
|
Logged
|
|
|
|
|