Some of these pages result from work on automating our sailing club web site. Our sailing club needed some simple but useful applications without too much effort. This was invented as BTInternet offered three pre written CGI scripts, but did not allow user CGI scripts. If they modified their guestbook script to support this idea, then the site owner could ftp .htm files, and ftp gbookFXXX.js up to the server. Also, I was on a Pay As you Go Dial Up. Editing on line was painful, as every minute costed me. Always on Broadband has changed this.
This is also good if you need a simple application where security is not a big issue, and access to the server is constrained by no telnet access and update is via ftp only via dial up. Also, as the web page code is 'open' to a view source, anybody who wants to rip off and improve for private or public use can!
When your visitor signs this guestbook, the entry is appended to a file of JavaScript, which is downloaded when the page is next loaded by the viewer. Note: users can only append data, and cannot delete entries. Spam can be deleted by the person with FTP access.
Using javascript code that you write, the guestbook entries can be sorted, selected and formatted by JavaScript running on the clients browser.
This allows simple applications to be written.
All the demo applications use the same cgi perl script guestbook.pl hosted on my Web server ccgi.dougrice.plus.com. You could run guestbook.pl ( or ASP / PHP version ) on your Web server.
You write the custom JavaScript to sort and summarise the data in the guestbook, and the data is also available to validate the guestbook form.
This page is tested first in Microsoft IE 5
I first used this to implement an online booking diary for our sailing club boats, which members can use. This diagram shows the split of functionality between the Server and the client.
An example - Sorting the Guestbook entries to display the latest entry first using the HTML and Javascript code below.
<html><body>
<script>
var thisEntry = "", opStr = ""
var gifsA = "flower.gif,abubble.gif,aflash.gif,aflower.gif,aheart.gif,astar.gif,biled0.gif,biled1.gif,biled2.gif,biled3.gif,".split(",")
// The function below is called once per guestbook entry.
// You write this function to do what you want!!
function gbF( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments){
// pick an image based on the value of userfield2 from an array of image names
var img = ""
var imgIndex = userfield2*1
if ( ( imgIndex > 0 ) << ( imgIndex < gifsA.length ) ){ img = "<img src=./simple/gifs/"+gifsA[ imgIndex ] +" > " }
news = ((""+comments).replace( "<","<")).replace( ">",">")
updated = new Date( postedOn ).toString()+" by "+name
thisEntry = "<HR><B>" + img + userfield1 + "</B><BR><pre>" + news + "</pre><BR><i>" + updated + "</i>"
opStr = thisEntry + opStr
}
// test call
gbF( "Test Call","email","15 Nov 2003","IPaddress","userfield1","userfield2","userfield3","userfield4","Testcomments")
</script>
<!-- Include remote guestbook-->
<script language = "JavaScript" type = "text/javascript"
src = "http://ccgi.dougrice.plus.com/gb/gbookFXXX.js" >
</script>
<H2> Last Entry</h2>
<script> self.document.write( thisEntry ) </script>
<H2> Prevous Entries</h2>
<script> self.document.write( opStr ) </script>
</body></html>The example above. A form to make an entry to this example guestbook. You may need to refresh the example page to see latest entry if you use this form.
Otherways to look at the data in this guestbook.
name =name - name of person signing guestbook email =email - email address of person signing guestbook userfield1 =userfield1 - a string that the application can use userfield2 =userfield2 - a string that the application can use userfield3 =userfield3 - a string that the application can use userfield4 =userfield4 - a string that the application can use userfield5 =uf5 Tue Oct 23 21:47:32 UTC+0100 2007 - anti spam security string set by javascript comments =This is a multi line comment
The fields above are copied into the parameters below, suitably escaped:
function gbF( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments){
This field is use to select the guestbook to update:
guestbook =XXX - this string is appended to gbookF{guestbook}.js
These fields control the next URL to go to:
nextpage ="http://ccgi.dougrice.plus.com/db0601/db7.php" - URL of page to go to. loadnextpage=loadnextpage - this is a flag to load the next page
Add data to http://ccgi.dougrice.plus.com/gb/gbookFXXX.js using the simple form.
Here are various ways of displaying and sorting gbookFXXX.js. This is all done by your web browser using javascript.
Remember that you can use IE's view source menu option to view the source.
Guestbook
Guestbook
( code )
Guestbook-last entry first
( code )
Another Guestbook - last entry first
JavaScript - open then do viewsource for code
SQLite schema and insert statements - open then do viewsource for code
MySQL schema and insert statements and PHP scripts - How to interface to a MySQL database using PHP
and gbookFXXX.js
Or variations of the Sorted Guestbooks:
Sorted:

Sorted + update form
( code )
Intelligently Sorted + update form
( code )
Sortable tables - remembering last sort order
Sortable tables - remembering last sort order - All guestbooks ( ~800 entries )
Collated using linked lists:

Collate data by userfield1
( code )
tables of data by userfield1
( code )
or
tables of data by userfield1 + updates
Or a
Calendar showing when the gbookFXXX was updated. It is a calendar showing when people posted an entry in the guest book. ( Use View Source to see code ).
A technical overview of the idea...
A walk through the basics...
A try at a multiple update form and perl script... This provides multiple sub forms, using data from gbookFmulti.js, which are appended to the gbookFmulti.js using gbook_multi.pl
A minimal multiple update form and perl script... This provides multiple forms.
A try at a multiple update form and perl script... This provides links generated, using data from gbookFmulti.js, you can add sub forms by clicking on hypertext links of by using a dropdown select list.
Another multiple update form... This a page where each item can be edited, and before submit, a list of updated entries can be listed, checked and submitted.
When you submit the data is appended to gbookFmulti.js using gbook_multi.pl
Data dump of guestbooks:
Data Dump at www.plus.net
A walk through the basics... Minimal application and code...
This was adopted into a simple fault tracker: Website bug report system
Here is the Mark 1 booking diary that uses a BT Internet Guestbook. Early work: First try for a booking system
Mark 1 Dinghy Booking . The user is expected to do a copy and paste.
Needless to say, we did not go live with this!!!
Early work: Second try for a booking system
Early work: Demo to support new idea
eScrapBook / eWorkingRecords - A User Updateable Sorted lists with history User Updateable Sorted lists. This could be adapted to a loan book, room booking, leave records, Document indexs, Test Spec/ results, Resource Information, Message boards, Fault tracker etc
Christmas Menu Questionnaire, Captured data viewed using eScrapbook
A first attempt, that explores Javascript possibilities:
WARNING: If you are trying these off line IE 5 works best, Netscape waits a long time, while trying to download files from the WWW.Feel free to submit the form, these are demo examples with demo data.
The web is a wonderful thing. Many people, like me can publish ideas and theories at little cost, as it is easy to knock a few Web pages together and push them up to our ISP's free personal web space. However, most free ISP's do not allow you to run CGI or ASP scripts, for valid security reasons. BT Internet is one of them. That is a shame as a simple CGI script can be used to automate a simple application. BTInternet do allow you to run a few of their own CGI scripts.
There are many people who provide web counters and guest book services. These protect the security concerns, and you, the web page author, do not need to get your hands dirty with PERL or UNIX or MySQL or build web servers on your machine to develop your web pages or all that webhosting stuff.
Do you wish that you had a Guest book that did just that little bit more. Maybe, you want to sort the entries by name or uses the information supplied in one of your fields.
I am in a sailing club, and we wanted a booking diary system that was WEB based. It had to be out side the firewall at work, so we need to host on an external webhosting site. BTInternet is an idea first choice.
It needed to keep a record of who had booked the boat, but present the bookings in a number of formats.
It had to keep an audit trail of bookings and allow amendments, so a guestbook that stored every posting was a good choice.
I thought that I could use the BT Internet Guestbook system. If I could find a way to sort people's submissions, then I could present them in diary order and show if the boat is booked or available.
> There is no way that a Web page can read guestbookfile1.html file output by BT Internet's guestbook CGI script, for security reasons.
Well, here is a generic way of doing it.
<!-- Start of entry --> /* Start of segment of code output by the BT internet CGI script */ /* This would be stored in gbookF5.js */ gbF( "doug", "d@g", "28/10/02 07:53:02", "127.0.0.1", "userfield1", "userfield2", "userfield3", "userfield4", "comments" ); <!-- End of entry -->
The data flow is:
1) Force a reload of the web page.
2) Include gbookF5.js, maybe in a separate frame which can be force reloaded.
3) gbF() is called once for each guestbook entry. copy the data into an array element gbA[count]
3) Summarise and Sort gbA array included in gbook_n.js using JavaScript's sort function. This allows you to write a call back function to select the fields, see example at the end.
4) Use javascript to output the contents of gbA array in the format that you want, to a separate frame. You can provide hypertext links that call different display options.
5) Provide a form called UserForm for the user to fill in. Hypertext links on the frame that your java script has just written to can be used to partially fill this form.
6) Capture the Submit button for UserForm. In the submit function, validate and copy and combine the fields from UserForm onto the MainForm that has the fields:
name, email, userfield1, userfield2, userfield3, userfield4, comments
If validated, the form can be submitted. I changed the text on the Submit buttion to indicate how the validation was progressing.
These are the user fields on BT Internet's Guestbook CGI. If BTInternet added the fields:
guestbook
then you could update different guestbooks.
Your version of gbF() could filter the data into different arrays, dependant on, say, the value of userfield1.
The different arrays could be used for bookings or status or usernames say.
Currently BTInternet allow 5 guestbooks. These are selected by:
HTTP://www.btinternet.com/cgi-bin/guestbook/~yourUserName?guestbook=5"
6) Now submit this form to the ISP ( BTInternet's ) or Guestbook provider's CGI script for appending onto your guest book.
The Guestbook provider's CGI script provides a thankyou page that has a link back to your web page, so that you can reload the gbookF5.js file and redisplay it.
A walk through the basics... has minimal size web pages and a working example that provides a frame work for futher development.
If you think that you could use this technology and do not
want to go to the expense of setting up a webhosting account,
please email me or sign my guestbook. I might set you up a trial
guestbook file. Think of a name, say Diary. I would create a file
called gbookFDiary.js, which I would have to give universal read
and write permissions using FTP or telnet and chmod 666
gbookFDiary.js The perl CGI script errors if it cannot
write to an existing file.
This would located at:
http://www.dougrice.webhoster.co.uk/public/gbookFDiary.js
so, to pick up the data, include the following, on your web page:
<script src="http://www.dougrice.webhoster.co.uk/public/gbookFDiary.js" language="JavaScript" type=text/javascript> ></script></code>
First you need to set some variables, so include the following:
<SCRIPT>
<!-- Sec 1.0 Variables -->
var count = 0
var gbA = new Array()
var statsA = new Array()
<!-- The CGI script appends the value of -->
<!-- field name="GuestBookArrayName" value="_mem" -->
<!-- to allow more than one array, so you have to declare them -->
var count_mem = 0
var gbA_mem = new Array()
function GB( name,email,postedOn,IPaddress,userfield1,userfield2,userfield3,userfield4,comments){
this.name = name
this.email = email
this.postedOn = postedOn
this.IPaddress = IPaddress
this.userfield1 = userfield1
this.userfield2 = userfield2
this.userfield3 = userfield3
this.userfield4 = userfield4
this.comments = comments
//This function is run for each guestbook entry
//when the data is loaded add a field to be used
//for sorting
this.JSindex = count
// if userfield1 has a user entered date in it.
this.date = new Date( userfield1 )
// or possibly some output HTML
self.document.write("loading:"+count+": "+name+" @ "+postedOn+"<BR>")
// build up some statitics
// userfield2 could be selected by a drop down list
statsA[ userfield2 ] = statsA[ userfield2 ]*1 + 1
return this
}
// The guest book CGI script on the server takes the Guestbook's form fields:
// name,email,postedOn,IPaddress,
// userfield1,userfield2,userfield3,userfield4,comments
// and wraps the values in the following format:
//
gbF( "name", "email", "28/10/02 07:53:02", "127.0.0.1", "userfield1", "userfield2", "userfield3", "userfield4", "comments" );
The original format below, adds the data to an array. This was simplified to the gbF() format. This new format is simpler to understand.
gbA[ count ]= new GB( "name", "email", "postedOn", "IP address", "userfield1", "userfield2", "userfield3", "userfield4", "comments" ); count = count + 1 // function call back for data stored in guestbook.
function gbF(
name,email,postedOn,IPaddress,
userfield1,userfield2,userfield3,userfield4,
comments
){
gbA[ count ] = new GB(
name,email,postedOn,IPaddress,
userfield1,userfield2,userfield3,userfield4,
comments );
count++ }
</SCRIPT> <!-- Now pick up the data from the remote web sites hosting the guest book --> <script src="http://www.dougrice.webhoster.co.uk/public/gbookFDiary.js" language="JavaScript" type=text/javascript></script>
You also have to edit the form action to:
<form name="F1" action="HTTP://www.dougrice.webhoster.co.uk/cgi-bin/guestbook.pl?guestbook=Diary" method="POST" >
or, as I sometimes use a local webserver 127.0.0.1, I use:
if ( document.location.host == "127.0.0.1" ){
form1.action = "HTTP://127.0.0.1/cgi-bin/guestbook.pl?guestbook=Diary"
} else {
form1.action = "HTTP://www.dougrice.webhoster.co.uk/cgi-bin/guestbook.pl?guestbook=Diary"
}
We have used this technology, and it is simple and works. We had 250 transactions over the year, which trippled our boat usage.
At the bottom of this page is a form that submits and appends to gbookF5.js it is followed by a table that outputs the data in gbookF5.js. The form does a minimal validation of the new entries against the data in gbookF5.js. There are hypertext links on the table that fill the form back in, in case you wish to amend the guestbook entry, and append a new version onto the end of the guestbook.
If you are a web hoster that wants to provide this for free or a nominal charge feel free to use it.
We used this guestbook on our webhoster account to support the sailing club.
I ran two guest books, one for the yacht and one for the dinghies. We had about 250 transactions and 4000 pages hits for the whole site in the year. 22Mbytes for pages, forms and documents was downloaded. It was reasonable to use and given a good example to work from, I am sure many other people could find an application that they could use it for.
The 2002 season has been much better.
"If you invent the perfect Web portal, you will have a beatten path to your mouse trap"
A walk through the basics... has minimal size web pages and a working example that provides a frame work for futher development.
This is important.
Use the OnLoad function to call doOnLoad(), or before the rest of the code do:
<script> doOnLoad() </script>
It adds the field JSindex to gbA[ ],
so that the array can be sorted back to submitted order.
It sorts the array into diary order, using the value stored in
gbA[ ].userfield1. If the dates are the same, then
sort by submit order now stored in gbA[ ].JSindex.
With a diary sorted array, you can now add fields amending
and ammendedBy fields to gbA[ ]. These
can be used to identify if a second submission for a given date
has been made.
The web page author can then choose what to do with amended submissions, when they display the information.
<body background=paper2.jpg bgcolor="#FFFFFF" onLoad="doOnLoad()">
...
function doOnLoad() {
if ( gbA.length > 0 ) {
//
// This function is called on the page load.
// In this function put functionality to summarise the guestbook entries.
//
// Build Indexes here, by adding extra properties of the object.
// assuming that one of the userfileds is the diary date
// We could sort the array into diary order and find amending bookings.
// which refer to a date previously booked, submitted earlier.
//
// before Sorting the Guestbook array, add a field = to index
// this can be used to sort the entries back to the submitted order.
for ( I in gbA ){
// add a new
gbA[ I ].JSindex = I
gbA[ I ].amendingJS = "."
gbA[ I ].amendedByJS = "."
gbA[ I ].amendingD = "."
gbA[ I ].amendedByD = "."
}
// sort the array into [ diary order, submit order ]
gbA.sort( sort_diary )
// now your can add links so that amending bookings
// and amended bookings can be identified.
var cnt = 0
var lastI = ""
for ( I in gbA ){
gbA[ I ].diaryOrder = cnt
cnt = cnt+1
//write( "<P>"+lastI+","+I )
if ( lastI != "" ){
if ( gbA[ I ].userfield1 == gbA[ lastI ].userfield1 ){
// use the submitted order
gbA[ I ].amendingJS = gbA[ lastI ].JSindex
gbA[ lastI ].amendedByJS = gbA[ I ].JSindex
// use the current sorted order
gbA[ I ].amendingD = lastI
gbA[ lastI ].amendedByD = I
}
}
lastI = I
}
// Now display the guestbook sorting by date
displayGuestBookArray( 2 )
}
//populate the Who: select list of the User Form
var window1 = parent.frames["OPform"]
var form1 = window1.document.F1
var form2 = window1.document.F2
if ( gbA_mem.length > 0 ) {
for ( I =0 ; I < gbA_mem.length; I++ ) {
form1.who.options[I]= new Option( gbA_mem[ I ].name,"")
}
form1.who.options[0].selected
}
}