Xavante
A Lua Web Server with WSAPI support

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:

  1. 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 by show_javascript.
  2. A user event calls up some JavaScript, which in turn may call some of the stubs.
  3. 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.
  4. 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.
  5. 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:

  1. 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.
  2. The JavaScript stubs call the functions with their specific URL, adding the parameters passed by the calling client side code.
  3. The Xavante dispatch code calls the required function, no CGILua environment is set up.
  4. 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.

Valid XHTML 1.0!

$Id: sajax.html,v 1.10 2008/05/23 20:18:58 carregal Exp $