Ajax

The headers command is crucial for generating XML messages that have to be understood by JavaScript code used in Ajax applications.

Brief introduction to Ajax

Ajax is a web programming technique that heavily relies on the abilty of a web browser to run in backround JavaScript functions. JavaScript functions can be run as callbacks of events generated by a user interaction but they can also react to other I/O events, for example network events. Modern browsers endow JavaScript with the ability to build http GET/POST requests to be sent to a remote webserver. Generally these requests refer to scripts (e.g. Tcl scripts run by Rivet) which inherit as variables the arguments encoded in the request. The output produced by these scripts is sent back to the browser where callbacks functions extract information and hand it down to functions that directly manipulate a page's DOM. Therefore through Ajax becomes possible to build web applications that are more responsive and flexible: instead of going through the cycle of request-generation-transfer-display of a whole page, Ajax scripts request from a webserver only the essential data to be displayed. Ajax emphasizes the requirement of separation between data and user interface, saves the server from sending over the same html code and graphics if only a fraction of a page has to be updated, allows the programmer to design flexible solutions for complex forms and makes possible to find new innovative approaches to simple problems (e.g. Google tips that show up as you type in a query). A downside of this approach is the large number of complexities, subtleties and incompatibilities that still exist in the way different versions of popular browsers handle the DOM elements of a page.

JavaScript can handle the communication between client and server through an instance of a specialized object. For quite a long time 2 approaches existed, the non-IE world (Firefox,Safari,Opera...) used the XMLHttpRequest class to create this object, whereas IE (before IE7) used the ActiveXObject class. With the release of IE7 Microsoft introduced native support for XMLHttpRequest class objects thus enabling programmers with a unique method for the development of dynamic pages.

By creating an instance of this class a POST or GET request can be sent to the server and the response is stored in a property ('returnedText') of the communication object. It's become widely customary to encode these responses in XML messages. You can invent your own message structure (either based on XML or anything else), but one has to be aware that if the http headers are properly set and the message returned to the client is a well formed XML fragment, also the property XMLResponse is assigned with a reference to an object that represents the DOM of the XML response. By means of the XML W3C DOM interface the programmer can easily manipulate the data embedded in the XML message.

Browsing a database of classical music composers

In this example a Rivet script fills a Tcl dictionary with the essential data regarding a few of the major composers of the european music. This dictionary plays the role of a database. The script sends back to the client two types of responses: a catalog of the composers or a single record of a composer.

#
# Ajax query servelet: a pseudo database is built into the dictionary 'composers' with the
# purpose of emulating the role of a real data source. 
# The script answers with  2 types of responses: a catalog of the record ids and a database 
# entry matching a given rec_id. The script obviously misses the error handling and the
# likes. Just an example to see rivet sending xml data to a browser. The full Tcl, JavaScript
# and HTML code are available from http://people.apache.org/~mxmanghi/rivet-ajax.tar.gz

# This example requires Tcl8.5 or Tcl8.4 with package 'dict' 
# (http://pascal.scheffers.net/software/tclDict-8.5.2.tar.gz)
# 

# A pseudo database. rec_id matches a record in the db

set composers [dict create  1 {first_name Claudio middle_name "" last_name Monteverdi	\
			       lifespan 1567-1643 era Renaissance/Baroque}		\
			    2 {first_name Johann middle_name Sebastian last_name Bach	\
			       lifespan 1685-1750 era Baroque }				\
			    3 {first_name Ludwig middle_name "" last_name "van Beethoven" \
			       lifespan 1770-1827 era Classical/Romantic}		\
			    4 {first_name Wolfgang middle_name Amadeus last_name Mozart	\
				lifespan 1756-1791 era Classical }			\
			    5 {first_name Robert middle_name "" last_name Schumann	\
				lifespan 1810-1856 era Romantic} ]

# we use the 'load' argument in order to determine the type of query
#
# load=catalog:		    we have to return a list of the names in the database
# load=composer&res_id=<id>: the script is supposed to return the record
#			    having <id> as record id

if {[var exists load]} {

# the xml declaration is common to every message (error messages included)

    set xml "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
    switch [var get load] {
	catalog {
	    append xml "<catalog>\n"
	    foreach nm [dict keys $composers] {
		set first_name [dict get $composers $nm first_name]
		set middle_name [dict get $composers $nm middle_name]
		set last_name  [dict get $composers $nm last_name]
	        append xml "    <composer key=\"$nm\">$first_name "
		if {[string length [string trim $middle_name]] > 0} {
		    append xml "$middle_name "
		}
		append xml "$last_name</composer>\n"
	    }
	    append xml "</catalog>\n"
	}
	composer {
	    append xml "<composer>\n"
	    if {[var exists rec_id]} {
		set rec_id [var get rec_id]
		if {[dict exists $composers $rec_id]} {

		    foreach {k v} [dict get $composers $rec_id] {
			append xml "<$k>$v</$k>\n"
		    }

		}
	    }
	    append xml "</composer>\n"
	}
    }

# we have to tell the client this is an XML message. Failing to do so
# would result in an XMLResponse property set to null

    ::rivet::headers type "text/xml"
    ::rivet::headers add Content-Length [string length $xml]
    puts $xml
}

For sake of brevity the JavaScript and HTML will not listed here. The whole example is at rivet-ajax.tar.gz . By simply opening this tar archive in a directory accessible by your apache server and pointing your browser to rivetService.html you should see a page with a drop-down list. Every time a different name is picked from the list a new query is sent and the data displayed on the page updated accordingly even though the whole html never gets reloaded. The background exchange between browser and apache rivet can be observed looking at the apache log file.

This example requires Tcl8.5 or Tcl8.4 with package 'dict' installed

Last Modified: 28-11-2018 15:39:22 UTC
Design downloaded from free website templates.