Sajax
Background
Xavante offers a Lua version of Sajax that can be used in AJAX applications. Sajax (the Simple AJAX toolkit) was written in PHP by Thomas Lackner. AJAX is short for "Asynchronous Javascript and Xml", a new name for a not-so-new technology.
AJAX is about writing your user GUI in HTML, with user interactivity defined in client-side Javascript, and getting server data via HTTP requests, the response being returned usually in the form of XML structures.
Sajax doesn't use a lot of XML itself, but the JavaScript object used to make
the HTTP queries is XMLHttpRequest
, so the 'X' in the name remains.
Sajax makes everything easier to do by allowing functions running in the server to be called from JavaScript code running in the client. To do that just register your functions and Sajax will generate JavaScript 'stubs' (small functions that handle the query to the server) with the same name as the server-side functions.
After that, all you have to do is call those functions from the client side Javascript and Sajax handles the magic
Usage
The example below is taken from calculator.lp
, based on one of the examples on
the Sajax site:
<% require "sajax" function multiply(x, y) return x * y end sajax.init() sajax.export ("multiply", multiply) if sajax.handle_client_request () then return end %>
This code defines a very trivial function and registers it with
sajax.export
. After all exported functions have been registered, it calls
sajax.handle_client_request
and finishes the script if there has been a Sajax
request.
<head> <title>Multiplier</title> <script> <% sajax.show_javascript(); %> function do_multiply_cb(z) { document.getElementById("z").value = z; } function do_multiply() { var x, y; x = document.getElementById("x").value; y = document.getElementById("y").value; x_multiply(x, y, do_multiply_cb); } </script> </head>
The <head>
part of the page includes some JavaScript
code. The call to sajax.show_javascript
generates the support
functions and the JavaScript stub function that will remotely call the registered
Lua functions.
The function do_multiply
reads two values, x
and
y
from form fields and calls the stub function x_multiply
,
adding as the last parameter a callback function. The function x_multiply
will perform the query to the server, and return immediately. The callback function
do_multiply_cb
will be called with the server function's return value
as the only parameter. In this example, do_multiply_cb
puts the
multiplication result into a form field.
<body> <input type="text" name="x" id="x" value="2" size="3"> * <input type="text" name="y" id="y" value="3" size="3"> = <input type="text" name="z" id="z" value="" size="3"> <input type="button" name="check" value="Calculate" onclick="do_multiply(); return false;"> </body>
The body of the Lua Page contains the HTML fields used by the JavaScript
functions, and also the button that calls the do_multiply
function.
In AJAX, the HTML code is mostly the initial canvas where JavaScript code is executed,
using both user events and server responses as inputs to operation.
Notes
- The
sajax.handle_client_request
function must be called after all the server-side functions has been registered, but before any other page processing. If the call returns true, the script must be finished immediatly. - The JavaScript stubs names are the names under which the server-side
functions were exported, with a
x_
prefix. - The value returned by the server-side function is converted to a string and passed as the parameter to a JavaScript callback. Only one returned value is passed.
- The JavaScript stub returns immediately after posting the query to the server; to do work after the server-side function has returned, use the callback function. That's the 'Asynchronous' part in AJAX.
How it works
There are two different operation modes in sajax.lua
: the generic CGILua
mode, and a Xavante specific optimization.
In generic CGILua, sajax.lua
works very similar to the PHP version:
- When the user enters the URL of the CGILua Script (or Lua Page), all the
functions are registered; but
handle_client_request
returns false, the script continues and produces the whole page, including the JavaScript stubs generated byshow_javascript
. - A user event calls up some JavaScript, which in turn may call some of the stubs.
- The JavaScript stub build a HTTP request with the same URL of the current page, with parameters indicating the function it wants to call, and any other parameter passed by the calling JavaScript code. It also adds the callback function to the request object, posts the request to the server, and returns immediately.
- The client query is handled in the server by the same Lua script. The same
functions get registered, but this time the
handle_client_request
function detects the Sajax request, pulls the required function name and other parameters, and calls the registered function. It then builds the response with the returned value, sends it to the client, and returns true to indicate the main Lua Script that the request has been handled and that it should terminate. - The response is handled by the client-side JavaScript; if the response is positive, the callback function is called with the returned value, if the response signals an error, an alert is posted.
If sajax.lua
detects that the current webserver is Xavante, it uses a
different workflow:
- When the user enters the URL of the CGILua Script (or LuaPage), all the
functions are registered in the Xavante dispatch table as handlers for URLs of
the form:
http://www.server.com/somedir/script.lp/funcname
handle_client_request
does nothing and always returns false. - The JavaScript stubs call the functions with their specific URL, adding the parameters passed by the calling client side code.
- The Xavante dispatch code calls the required function, no CGILua environment is set up.
- The returned value is handled in the same way, calling the client-side callback.
It is very important to notice that the CGILua system is called only for the initial page request; the remote function calls don't fetch the filesystem, and the CGILua environment and parsing is bypassed. That means that the server-side functions can't use most CGILua functions, so any session identifying key should be passed as a function parameter.