blob: ec60348016624fa386c7af00c5ed846df3543697 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ajax</title>
<link rel="stylesheet" href="../templates/wondrous/styles.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="header">
<h1><a href="../index.html">Rivet</a></h1>
<h2 id="slogan">Webscripting for Tcl'ers</h2>
<div class="clear"></div>
</div>
<div id="body">
<div id="content">
<h2>Ajax</h2>
<div class="example">
<!-- p class="title"><b>Example 6. XML Messages and Ajax</b></p -->
<div class="example-contents">
<p>
The <b>headers</b>
command is crucial for generating XML messages that have to be understood by JavaScript
code used in Ajax applications.
</p>
<p>
<b style="border-bottom: 1px solid black;">Brief introduction to Ajax</b>
<p>
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.
</p>
<p>
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.
</p>
<p>
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.
</p>
</p>
<p>
<b style="border-bottom: 1px solid black;">Browsing a database of classical music composers</b>
<p>
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.
</p>
<pre class="programlisting">#
# 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&amp;res_id=&lt;id&gt;: the script is supposed to return the record
# having &lt;id&gt; as record id
if {[var exists load]} {
# the xml declaration is common to every message (error messages included)
set xml "&lt;?xml version=\"1.0\" encoding=\"ISO-8859-1\"?&gt;\n"
switch [var get load] {
catalog {
append xml "&lt;catalog&gt;\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 " &lt;composer key=\"$nm\"&gt;$first_name "
if {[string length [string trim $middle_name]] &gt; 0} {
append xml "$middle_name "
}
append xml "$last_name&lt;/composer&gt;\n"
}
append xml "&lt;/catalog&gt;\n"
}
composer {
append xml "&lt;composer&gt;\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 "&lt;$k&gt;$v&lt;/$k&gt;\n"
}
}
}
append xml "&lt;/composer&gt;\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
}</pre>
<p>
For sake of brevity the JavaScript and HTML will not listed here.
The whole example is at
<a href="http://people.apache.org/~mxmanghi/rivet-ajax.tar.gz">rivet-ajax.tar.gz</a>
.
By simply opening this tar archive in a directory accessible by your apache server and
pointing your browser to <em>rivetService.html</em>
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.
</p>
<p>
This example requires Tcl8.5 or Tcl8.4 with
<a href="http://pascal.scheffers.net/software/tclDict-8.5.2.tar.gz" target="_blank">package 'dict'</a>
installed
</p>
</p>
</div>
</div>
<div class="contentbottom">
</div>
</div>
<div class="sidebar">
<ul>
</ul>
<ul>
<li id="home">
<h4>Rivet</h4>
<ul class="blocklist">
<li class="navitem">
<a title="A home for Rivet" href="../index.html">Rivet Homepage</a>
</li>
<li class="navitem">
<a title="Home of Apache Tcl related stuff" target="asf" href="http://tcl.apache.org/">Apache Tcl Home</a>
</li>
<li class="navitem">
<a title="Getting Rivet" href="download.html">Getting Rivet</a>
</li>
<li class="navitem">
<a title="Hello World!" href="hello%5fworld.html">Examples</a>
</li>
<li class="navitem">
<a title="The Rivet development team" href="about.html">About Us - Contact</a>
</li>
</ul>
</li>
<li id="manual">
<h4>Documentation</h4>
<ul class="blocklist">
<li class="navitem">
<a title="Rivet 2.1 Manual" target="rivetman2.1" href="http://tcl.apache.org/rivet/manual2.1/">Rivet 2.1</a>
</li>
<li class="navitem">
<a title="Rivet 2.2 Manual" target="rivetman2.2" href="http://tcl.apache.org/rivet/manual2.2/">Rivet 2.2</a>
</li>
<li class="navitem">
<a title="Rivet 2.3 Manual" target="rivetman2.3" href="http://tcl.apache.org/rivet/manual2.3/">Rivet 2.3</a>
</li>
<li class="navitem">
<a title="Rivet 3.0 Manual" target="rivetman3.0" href="http://tcl.apache.org/rivet/manual3.0/">Rivet 3.0</a>
</li>
</ul>
</li>
<li id="rivetexamples">
<h4>Examples</h4>
<ul class="blocklist">
<li class="navitem">
<a href="hello%5fworld.html">Hello world!</a>
</li>
<li class="navitem">
<a href="colorful%5ftable.html">A colorful table</a>
</li>
<li class="navitem">
<a href="var%5faccess.html">Variable Access</a>
</li>
<li class="navitem">
<a href="file%5fupload.html">File Upload</a>
</li>
<li class="navitem">
<a href="file%5fdownload.html">File Download</a>
</li>
<li class="navitem">
<a href="ajax.html">XML and Ajax</a>
</li>
<li class="navitem">
<a href="calendar.html">Calendar</a>
</li>
</ul>
</li>
</ul>
<ul>
</ul>
</div>
<div class="clear"></div>
</div>
</div>
<div id="footer">
<div class="footer-content">
<p><a href="http://www.apache.org/">Apache Software Foundation</a> | Design by <a href="http://www.spyka.net">Free CSS Templates</a> | <a href="http://www.justfreetemplates.com">Free Web Templates</a></p>
</div>
</div>
<div style="text-align: center; font-size: 0.75em;">Design downloaded from <a href="http://www.freewebtemplates.com/">free website templates</a>.</div></body>
</html>