Programming in Sitellite
Chapter 7: AJAX in Sitellite
A basic PHP class
First, let's create a basic lib/Calculator.php class in our app with the following standard PHP code in it.
<?php
class Calculator {
function add ($one, $two) {
return $one + $two;
}
function subtract ($one, $two) {
return $one - $two;
}
function multiply ($one, $two) {
return $one * $two;
}
function divide ($one, $two) {
return $one / $two;
}
}
?>
Connecting it with a box
In your boxes folder, create a box named 'calculator' and put this in the index.php file in that folder:
<?php
loader_import ('saf.Misc.RPC');
loader_import ('myapp.Calculator');
echo rpc_handle (new Calculator (), $parameters);
exit;
?>
This is all the code required to hook our Calculator class up to Javascript on the server-side. A couple points to note about the above box code:
- I used $parameters instead of $_GET this time. $parameters is what the box loader passes to a box, which when called from the URL includes both the GET and POST values.
- I called exit at the end this time. This prevents Sitellite from passing the box output to a design template and making it pretty. In this case, we just want the raw data, which Sitellite returns as a JSON string.
A box for the client-side
Let's create a basic box to include the rpc.js and also call a template where we'll put our Javascript code. Let's call this box 'calc'.
<?php
page_title ('AJAX Calculator');
page_add_script (site_prefix () . '/js/rpc-compressed.js');
echo template_simple ('calc.spt');
?>
The client-side code
As you saw, the PHP code required isn't much, since most of the action is happening in Javascript. So our calc.spt file below is going to contain most of the exciting code.
<script language="javascript">
// create a global 'rpc' object
var myrpc = new rpc ();
// create another object to contain all of our methods
var calc = {
// specify the url to submit requests to, an ordinary Sitellite box call
url: '{site/prefix}/myapp-calculator-action',
action: myrpc.action,
// this method will make our AJAX call via myrpc.call()
update: function (form) {
// these are the values we'll pass on to the server
func = form.elements.func[form.elements.func.selectedIndex].value;
one = form.elements.one.value;
two = form.elements.two.value;
// now we make the remote request with myrpc.call()
myrpc.call (
// the first parameter is the request compiled by this.action()
this.action (func, [one, two]),
// the second parameter is the response handler function
function (request) {
// get the server's response
answer = eval (request.responseText);
// update the answer field
document.getElementById ('answer').value = answer;
}
);
// and finally, stop the form from submitting
return false;
}
};
</script>
<form onsubmit="return calc.update (this)">
<p>
<input type="text" name="one" size="5" />
<select name="func">
<option value="add">+</option>
<option value="subtract">-</option>
<option value="multiply">*</option>
<option value="divide">/</option>
</select>
<input type="text" name="two" size="5" />
<input type="submit" value="Go" />
</form>
<p>= <span id="answer" style="font-weight: bold"> </span></p>
The point is that we can easily add new methods on the PHP side to the Calculator class, and just by adding new methods to calc in our Javascript, we can easily connect the two layers together.
Next, let's look at a few more features of rpc.js.
Post requests
Sending a post request uses the post() method instead of call(), however parameters are also set differently. Instead of passing them directly in the URL via the action() method, they must be added via addParameter().
update: function (form) {
func = form.elements.func[form.elements.func.selectedIndex].value;
myrpc.addParameter ('one', form.elements.one.value);
myrpc.addParameter ('two', form.elements.two.value);
myrpc.post (
this.action (func),
function (request) {
response = eval (request.responseText);
// handle the response
}
);
return false;
}
parse_form()
You can also automatically parse an existing form object and automatically add its values all at once (minus submit boxes). This is done with the parse_form() method.
update: function (form) {
myrpc.parse_form (form);
myrpc.call (
this.action ('update'),
function (request) {
response = eval (request.responseText);
// handle the response
}
);
return false;
}
Here we're specifying a new method called 'update' that must be defined on the server-side as well. Let's add that to lib/Calculator.php and then try it out. This method passes requests dynamically to the other methods of Calculator. It saves a bit of code on the client-side while only adding a couple lines on the server-side for our particular example.
function update () {
return $this->{$_POST['func']} ($_POST['one'], $_POST['two']);
}
update_field()
Sitellite's rpc.js library features an update_field() method that makes an AJAX call and automatically inserts the results into the specified tag in the document.
update: function (form) {
func = form.elements.func[form.elements.func.selectedIndex].value;
one = form.elements.one.value;
two = form.elements.two.value;
myrpc.update_field (
'answer',
this.action (func, [one, two])
);
return false;
}
append_field()
In addition to updating an existing field, the append_field() method appends a new child to the specified field with the AJAX results. This method is useful for easily adding new items to a list.
update: function (form) {
func = form.elements.func[form.elements.func.selectedIndex].value;
one = form.elements.one.value;
two = form.elements.two.value;
myrpc.append_field (
'answers',
this.action (func, [one, two])
);
return false;
}
As you can see, Sitellite offers many features for programmers to quickly build powerful web-based applications.




John Luxford