Following the hype: AJAX, Prototype.js, JSON and the XP framework

at 2006-10-29 in Experiments by friebe (0 comments)

With all the current hype on the (really not so new) possibilities JavaScript offers for rich client-side scripting, and people choosing frameworks because they are "AJAX-enabled", I'd like to show how to "WEB two dot oh" with the XP framework.

This article will show you how to create client/server interaction using JSON as wire-format, the Prototype JavaScript framework and the XP framework's JsonRpcRouter API.

Running the demo
It is assumed that you have...

  1. ...the Apache Web server with mod_php (version 4) up and running
  2. ...an up-to-date XP framework checkout (use svn co svn://php3.de/xp to get it)
  3. ...PHP's include_path configured to contain "." and the XP framework's skeleton
To run the demo application contained in the XP framework's experiments (sourcecode), configure an Apache VirtualHost with its DocumentRoot set to the json experiment's doc_root directory.

In my case, I use Apache 2.2.3 and mod_php4 (from the XAMPP download, the official php4apache2.dll will not work with 2.2) on Windows and don't have a local nameserver, so I'll simply set the global DocumentRoot to the correct directory:
DocumentRoot "C:/cygwin/home/thekid/devel/xp/trunk/experiments/people/friebe/json/doc_root"
<Directory "C:/cygwin/home/thekid/devel/xp/trunk/experiments/">
DirectoryIndex index.php
</Directory>
After restarting the Apache server, open http://[HOSTNAME]/highlight.html (in my case, HOSTNAME is localhost) in a web browser. You will see a text area and an empty area labeled "results" below it:
Screenshot

Simply start typing PHP code inbetween the PHP open and close tags and observe how the result area starts displaying syntax-highlighted code.

How it works: Client-side
The client side uses the textarea's onKeyUp event to capture when you have pressed a key in the textarea - most commonly, that will change the text - so we will call the server-side part and request an updated version of the highlighted code. We do so by using Prototype's Ajax.Request api, passing a JSON-message to the server and updating the result div's innerHTML with the retrieved results.
  new Ajax.Request('/', {
method: 'post',
postBody: JSON.encode(new JSONMessage('Syntax.highlight', [ $F('entry') ], requestNumber++)),
onFailure: function(request) {
alert("Error " + request.readyState + " : " + request.responseText);
},
onSuccess: function(request) {
$('result').innerHTML= JSON.decode(request.responseText).result;
}
});
Notes:
  • The $F() function is a shorthand for form-elements' values
  • The $() function is a shorthand for document.getElementById()
  • In case of an error, we'll show a dialog box with the returned text, this can be quite annoying so you might consider a better way of doing so:)


How it works: Server-side
The doc_root directory contains a file called index.php which will solve as a dispatcher for the JSON requests. It basically contains boilerplate code only, and the only thing you'll need to change is the class path in the following line:
  scriptlet::run(new JsonRpcRouter('service'));

The string "service" points to the location the classes can be found in, which in this case is resolved by the default classloader to ./service/ (because of the "." in the include_path). The JsonRpcRouter class takes care of all serialization, deserialization, error handling and service mapping for you, so the only you will have to do is to write a handler implementation.

In this case, Syntax.highlight is the method we call on the client side, so you'll have to create a class called SyntaxHandler and add a method highlight() to it:
  class SyntaxHandler extends Object {

#[@webmethod]
function highlight($code) {
return highlight_string
($code, TRUE);
}
}

For JsonRpcRouter to be able to know if a class method should be invokeable remotely, the method needs to be decorated with the @webmethod annotation. Failing to do so will yield a "cannot access non-webmethod" error during invocation!

Extending the example
  • To add new service methods, simply add @webmethod-decorated methods to the class.
  • To add new services, simply create a new class and put it in the service directory.
  • To return an error from a service method, simply throw an exception from it, e.g.
    return throw(new IllegalArgumentException('Error Message'));
    This will make the client call the onFailure() callback - the response text will contain a JSON-encoded error object (error.faultString will contain the error message)
  • To improve performance and decrease server load, change the client to only send a request after a full line has been typed.

Enjoy:)



Subscribe

You can subscribe to the XP framework's news by using RSS syndication.


Categories

News
General
PHP5
Announcements
RFCs
Further reading
Examples
Editorial
EASC
Experiments
Unittests
Databases
5.8-SERIES
Unicode
Language
5.9-SERIES

Related

Find related articles by a search for «Following».