Groups > dBase > dBase Internet > Re: AJAX and dBase




AJAX and dBase

AJAX and dBase
Wed, 05 Dec 2007 18:32:11 -050
I've read through the tutorial on the dbase knowledgebase website regarding
using AJAX on web pages tied into dbase cgi scripts.  I thought I understood and
try to write one, but it didn't work.  Thinking that I must be doing something
wrong, I tried just cutting and pasting the code in the tutorial for both the
web-page and the dbase application.  It still doesn't work.

If I click the button on the example web page, I can see PLUSrun start in the
Windows Task manager.  But, the web page never updates and PLUSRun stays on the
task manager display until I manually shut it down.  When I do shut it down, it
generates an error in the Apache error log file: Premature end of script
headers.  I put an alert in the script to show the text error message in the web
page (Internal Server Error), and that matches up with what I'm seeing in the
Apache log file from what I read.  Note that neither error occurs until I use
task manager to force a shutdown of PLUSRun.

I'm doing this on 'localhost' (my computer) using Apache 2.2 and the current
version of Dbase Plus.  I've used (and can still use) this setup to run some of
the traditional web pages in which the dbase program generates all the html
statements for the entire page (instead of just a portion as AJAX is supposed to
allow).  So, I've got most of the Apache configuration file right.  But, I
suspect there might be something else in the configuration file that has to be
set.

Anyone have any ideas?

Regards
Steve

Post Reply
Re: AJAX and dBase
Wed, 5 Dec 2007 21:36:17 -0600
Steve,
I wrote an example Ajax execution with web pages and error messages back on 
2/12/07.  Here is a reprint of the message. Perhaps you will find it useful 
in at least detecting the error which is occuring with your program.

As I recall I accidently inserted an error in the code as shown below. 
Watch for accidental line breaks in the code.

Claus

~~~~ RePrint of earlier porst An Ajax Update~2/12/07~~~~~~
The post from Ira about Ajax got me to look at the concept of updating web
forms using this "asynchronous communication" between the client and
the
server.  For more of a background on this I would recommend users look in
the Knowlegebase at http://www.dbase.com/ajax_and_dbase.html

The article describes how to communicate with the server, but unfortunatly
the returned information is written to a document node and not an input
field.

Another problem not discussed is debugging this type of application.  Since
no response page is generated the standard techniques cannot be used.  So I
would like to share the results of my work with Ajax because I think this
type of communication will do alot to make web/browser application appear
like desktop applications.

The example will use a simple web page with one read/write input field and 4
other readonly fields.  When a change is detected in the read/write field a
lookup on the server is done using Ajax and the readonly fields are
autofilled.

Look for *~~~~  this will be where changes from the knowlegebase article
have been made.

----the Web Page ---
Class MyCGISession of CGISession from "WebClass.cc"

   function StreamHeader

   with (this.fOut)

   puts('Content-type: text/html')
   puts('<html>')
   puts('<head>')
   puts('<title> Web Demo Page<title>')
   puts('<script language="JavaScript">')
   puts('<!--')
   /*
     Ajax communication with server section
   */
   puts([var xmlHttp;])

   puts([function createXMLHttpRequest() {  ])
   puts([  if (window.ActiveXObject) {])
   puts([      xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");])
   puts([  }else if (window.XMLHttpRequest) {])
   puts([      xmlHttp = new XMLHttpRequest();])
   puts([  }])
   puts([}])

   puts([function requestClient() { ])
   puts([   createXMLHttpRequest();])
   puts([   var url = "/cgi-bin/Ajax.exe?timeStamp=" + new
Date().getTime();])
   puts([   var queryString = createQueryString() +
"&method=POST";])
   puts([   xmlHttp.onreadystatechange = handleStateChange;])
   puts([   xmlHttp.open("POST", url, true);])
   puts([   xmlHttp.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");])
   puts([   xmlHttp.send(queryString);])
   puts([}])

   puts([function createQueryString() {])
   puts([  var cId = document.getElementById("ID").value;])
   puts([  var queryString = "ID=" + cId;])
   puts([  return queryString;])
   puts([}])

   puts([function handleStateChange() {])
   puts([   if (xmlHttp.readyState == 4) {])
   puts([      if (xmlHttp.status == 200) {])
   puts([         parseResults();])
   puts([      }])
   puts([   }])
   puts([}])

*~~~~~~~~~
/*
  On the web page the parseResults function is where the action is occuring
  it will
 1. Detect errors and alert the user
 2. Place the content into the readOnly fields

We will use the javaScript split( ) method to parse our data into an array.
All data elements are separated by the ; when returnedString is assembled in
the Ajax app.
*/
*~~~~~~~~~
   puts([function parseResults() {])

   //assign the returned value to a variable
   puts([   var returnedString = xmlHttp.responseText;])

   //create an array to store the information
   puts([   var aReturn = new Array();])

   //parse the string into the array using the semi-colon to separate each
value
   puts([   aReturn = returnedString.split(';');])

*~~~~~~~~~~
/*
  Errors cannot be easily detected in the
  Ajax program, so it is useful to add an alert
  when Ajax returns information which needs
   the users attentions.  In this example there
   could be 3 types of errors occuring:
  1. The ID field was cleared out ( changed value is now empty)
  2. The ID is an invalid value (not found in the table)
  3. A syntatical error occured in the progam and the "catch"  was
activated.

   When one of these error occur we need a practical way to notify the user
of what type of error occured.  So when an error occurs in the Ajax app we
start our returnString with this value "An error occured;".  Then we
test
the return string for this value by checking the first element of the
aReturn array.
*/
*~~~~~~~~~~
   //test and display error message if error occured
   puts('  if ( aReturn[0] == "An error occured") { ')

   /*
     if an error occured assemble an alert message we can display to the
user. Notice the use of the "\n" to create line breaks on the alert
message,
which helps for readability.
   */
   puts('     eAlert  = aReturn[0]+"\n"')

   //capture the original value keyed in by user since we are going to clear
it out below.
   puts('     if ( aReturn[1] == "Invalid client Id") { ')
   puts('        eAlert += aReturn[1]+"
"+document.getElementById("ID").value+"\n"')
   puts([     }else{ ])
   puts('        eAlert += aReturn[1]+"\n"')
   puts([     }])

   puts('     eAlert += aReturn[2]+"\n"')
   puts('     eAlert += aReturn[3]')

  //clear out the screen
   puts([     document.getElementById("ID").value = "";])
   puts([     document.getElementById("NAME").value = "";])
   puts([     document.getElementById("ADDR1").value =
"";])
   puts([     document.getElementById("ADDR2").value =
"";])
   puts([     document.getElementById("CITY_ST_ZIP").value =
"";])

  //select and set foucus to the read/write field
   puts([     document.getElementById("ID").select();])
   puts([     document.getElementById("ID").focus();])

   //alert user of problem by displaying the error message
   puts([     alert( eAlert );])
   puts([  }else{ ])

   //no problem occured so display lookup information
   puts('     document.getElementById("NAME").value = aReturn[0];')
   puts('     document.getElementById("ADDR1").value = aReturn[1];')
   puts('     document.getElementById("ADDR2").value = aReturn[2];')
   puts('     document.getElementById("CITY_ST_ZIP").value =
aReturn[3];')
   puts([  }])
   puts([}])
   puts('//-->')
   puts('</script>')
   puts('  </head>')
   endwith

*~~~~~~~~~
//the only unique information in the "streamBody" section is the
"onChange"
event handler which calls the requestClient function above.  The rest is
only included to make a more complete example.
*~~~~~~~~~
function streamBody

with (this.fOut)
   puts('<body>])
   puts('<form ')
   puts('    method=POST ')
   puts('   name="f1"')
   puts('   onSubmit="return false"')
   puts('  >')
   puts('')
   puts([<div>])
   puts([<table>])
   puts([   <tr>])
   puts([      <th>Client:</th>])
   puts([   </tr><tr>])
   puts([   <td>])
*~~~~~~~~
/*
The onChange event handler activates the Ajax response by calling the
requestClient function above.
*/
*~~~~~~~~
   puts([   <input ])
   puts([     type="text" ])
   puts([     name="ID" ])
   puts([     id  ="ID" ])
   puts([     size="10" ])
   puts([    maxLength="8" ])
   puts([    onChange="requestClient();"])
   puts([   />])
   puts([   </td></tr><tr><td>])
   puts([   <input ])
   puts([     type="text"   ])
   puts([     name="NAME"         ])
   puts([     id  ="NAME"         ])
   puts([     size="47"           ])
   puts([     readonly            ])
   puts([     tabindex="-1"       ])
   puts([   />])
   puts([   </td></tr><tr><td>])
   puts([   <input ])
   puts([     type="text"         ])
   puts([     name="ADDR1"         ])
   puts([     id  ="ADDR1"         ])
   puts([     size="47"           ])
   puts([     readonly            ])
   puts([     tabindex="-1"       ])
   puts([   />])
   puts([   </td></tr><tr><td>])
   puts([   <input ])
   puts([     type="text"         ])
   puts([     name="ADDR2"         ])
   puts([     id  ="ADDR2"         ])
   puts([     size="47"           ])
   puts([     readonly            ])
   puts([     tabindex="-1"       ])
   puts([   />])
   puts([   </td></tr><tr><td>])
   puts([   <input ])
   puts([     type="text"         ])
   puts([     name="CITY_ST_ZIP"  ])
   puts([     id  ="CITY_ST_ZIP"  ])
   puts([     size="47"           ])
   puts([     readonly            ])
   puts([     tabindex="-1"       ])
   puts([   />])
   puts([   </td></tr>])
   puts([</table>])
   puts([</div>])
   puts([</form>])
   puts([</body>])
   puts([</html>])
endwith
return true
endClass

--- Ajax app ---
*~~~~~~~~~~
/*
In the Ajax app we want to:
1. Query the database
2. Create a return string that can be parsed into an array
3. Test for errors. If needed create a return string with the error message.
*/
*~~~~~~~~~~
Set talk OFF   // turn off interactive mode
Set century ON // Y2K
_app.errorAction = 3

try

  //open webClass
  set procedure to WebClass.cc additive

  oCGI = new CGISession( )
  oCGI.connect( )

  if not empty(oCGI["ID"])

     // Open Database
     db = new DATABASE()
     db.databaseName = "<your database>
     db.active       = true

     // Open Query
     q = new QUERY()
     q.database = db

     //execute query
     q.sql = 'select id, name, addr1, addr2, city, st, zip from <your
table>
where id = "'+ oCGI["ID"] +'"'
     q.active = true
     q.rowset.first()

     if not q.rowset.endOfSet
        c  = q.rowset.fields
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
The return string is assembled with just the field values and the ;
delimiter.  No quotes around the individual field values.  Note if you
expect that ; may be a valid value, you can change the delimiter value or
even make it more than one character like ;;
*/
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        responseText   = c['NAME'].value+ [;]
        responseText  += c['ADDR1'].value+ [;]
        responseText  += c['ADDR2'].value+ [;]
        responseText  += trim(c['CITY'].value)+ [, ]+;
                                         c['ST'].value+ [ ] +;
                         displayZip(trim(c['ZIP'].value)) + [;]
        responseText  += displayPhone(trim(c['PHONE'].value))+ [;]
        responseText  += displayPhone(trim(c['FAX'].value))
     else
*~~~~
Note the error message here
        //the user entered an invalid value. the Client Id was not found.
*~~~~~~~
        responseText = "An error occured;Invalid client Id;;;;;"
     endif
  else
    //the user cleard the content of the ID field and a blank was
transmitted.
    responseText = "An error occured;No Client Id Requested;;;;;"
  endif

  oCGI.fOut.puts("Content-type: text/html")
  oCGI.fOut.puts('')
  oCGI.fOut.puts(responseText)

catch (exception e)
*~~~~~~~~~~~~
/*
An error occured in the program and a standard error response will not work.
We need to assemble a useful error message for the user.
*/
*~~~~~~~~~~~~
  responseText = 'An error occured;in file: '+e.Filename+;
                 ';on line no:'+e.LineNo+';'+e.Message

  oCGI.fOut.puts("Content-type: text/html")
  oCGI.fOut.puts('')
*~~~~~~~~
/*
Return a useful message instead of just "Error!"
*/
*~~~~~~~~
//  oCGI.fOut.puts("Error!")
  oCGI.fOut.puts(responseText)

endtry
oCGI = null
quit

Post Reply
Re: AJAX and dBase
Wed, 5 Dec 2007 22:07:38 -0600
by the way the error in the program I just listed was the two functions I 
created for my own personal apps, but are not included in the example:

displayZip( ) - inserts a "-" if the length of the value is > 5

and

displayPhone( ) - which formats the phone # into (999) 999-999

                         displayZip(trim(c['ZIP'].value)) + [;]
        responseText  += displayPhone(trim(c['PHONE'].value))+ [;]
        responseText  += displayPhone(trim(c['FAX'].value))

since they are not included in the Ajax app an error will occur when you run 
the program as is.

You you should be able to just compile the 2 apps on your server create a 
sample database with the 5 fields described in the progam and then play with 
it to get a better understanding of how it works.  You can then also put in 
some errors to get a feel for what to expect.

Good Luck

Post Reply
Re: AJAX and dBase
Wed, 5 Dec 2007 22:09:51 -0600
Oh yeah I see the response included phone and fax when the calling app did 
not have a phone and fax.  Well you should be able to figure that out. 

Post Reply
Re: AJAX and dBase
Fri, 7 Dec 2007 21:43:31 +0100
Some time ago i'v did too some test with Ajax

http://www.medidea.net/testajax/test1.html

there you can also download the source files to run this example
http://www.medidea.net/testajax/testajax.zip

Hope this could be usefull

Silvio 

Post Reply
about | contact