Creating a simple AJAX application with Mochikit

Actually I wanted to use a web framework like Django or Turbogears when I decided I need to learn the basics of Javascript to see what AJAX can do for me. I stumbled over the Mochikit Javascript toolkit. This tiny article deals with a "hello world" kind of application so you get the idea.

Mochikit is not Python

My first misunderstanding was that Mochikit has something to do with Python. No, it is a bunch of libraries/files purely written in Javascript. Mochikit does much more than just allow web applications to use AJAX. It provides new functions that make Javascript easier to use and remotely look like Python functions/methods. Everybody who needs to code a lot of Javascript might like Mochikit as it simplifies some everyday tasks. But one part called "Mochikit.Async" is especially supposed to help us here.

AJAX is not magic

Everybody is talking about AJAX (some marketing dorks even get high when they talk about "Web 2.0" - can someone please tell them that this term is just so wrong?). Great applications like Google Maps use AJAX. You can move maps with your mouse in the browser - wow, that's cool. And while Google's web applications surely are a bit complicated the basics of AJAX are not. AJAX basically stands for "Asynchronous Javascript and XML" plus some other words. AJAX is not a product or library but a way to let your web site talk to the web server time and again while you don't seem to click on a link or submit a form. AJAX is an idea that has been implemented by several people. And Mochikit provides a few convenience functions that make AJAX simple(r).

DOM is not evil

So AJAX is about changing the web page you are viewing in your browser without reload the whole page. Just a part of the web page is replaced dynamically. Of course you need to tell somebody which part of the page you want to change. This is where DOM kicks in. DOM ("Document Object Model") gives you ways to address every part of your page. For example it allows you to get or set the value of certain form fields when you know the id="..." attribute of a certain HTML tag. I strongly suggest you install the FireBug add-on to your Firefox browser, activate it and click on Inspector and DOM. Click on Inspect and then click on any element on the web page that you are currently viewing. You will see a tree-like representation of the DOM. Got the idea of the DOM?

Time for an example

It's time for some practical example. Create a basic HTML page and have it include a form.

<html>
<head>
  <script src="/tg_js/MochiKit.js" type="text/javascript"></script>
  <script src="/static/javascript/ajaxtest.js" type="text/javascript"></script>
</head>

<body>
<form method="post" id="nameform">
   Your Name: <input type="text" name="myname2" id="myname" />
   <input type="submit" value="Go" onclick="onDoit(); return false;"/>
</form>

<div id="putitthere"/>
</body>
</html>

The form includes a simple text field where you are supposed to enter your name and a submit button with a Javascript action called onDoit();. The return false is there so that the browser doesn't actually submit the form.

You need to load the MochiKit.js - the above <script...> loads it from /tg_js/ which is the default location if you program your web application with Turbogears. Otherwise just download it and adjust that path accordingly.

The second Javascript you need to include is a ajaxtest.js file that you need to create on your own. It will be the glue that makes your application use AJAX. So put the following into a file called ajaxtest.js and adjust the path accordingly.

var postJSON = function(url, postVars) {
    var req = getXMLHttpRequest();
    req.open("POST", url, true);
    req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    var data = queryString(postVars);
    var d = sendXMLHttpRequest(req, data);
    return d.addCallback(evalJSONRequest);
}

var gotMetadata = function (response) {
    replaceChildNodes( "putitthere", P( null, response.what));
};

var metadataFetchFailed = function (err) {
  alert( "The metadata for MochiKit.Async could not be fetched");
};

function onDoit() {
    var d = postJSON('/ajax-test-cgi', {
        'name': getElement('myname').value,
        });
    d.addCallbacks(gotMetadata, metadataFetchFailed);
}

(This is partly stolen from http://docs.turbogears.org/1.0/TodoList.)

Okay, let's see what it does step by step. So the user has entered the name and clicked on the submit button. That is supposed to call the onDoit() function. That function opens a connection to the CGI at /ajax-test-cgi and sends a HTTP POST request to it. That request contains a parameter called 'name' with the value of your text field. The getElement() is the magic here. It uses the DOM structure to get the element with the id="myname" parameter (which is your text field) and retrieves its current value. So the CGI gets that name passed. At the end of that function we add a callback to two functions:

(If you like just ignore the postJSON function that is defined here. You need it for communicating the POST request to the CGI but there's nothing to see there.)

So the CGI handles the request, does something with the input it gets from the POST requests and passes back some information. You get that information as the parameter to the gotMetadata() function. My CGI returned a variable called 'what' to the Javascript (response.what). And now the magical change in the web page happens: replaceChildNodes(...). That's a Mochikit function that searches for the element of the web page with the id="putitthere" parameter (which is a <DIV>) and fills it with response.what.

The CGI can be as simple as...

#!/usr/bin/python
 
import cgi
 
form = cgi.FieldStorage()
strBlah = form.getfirst( "blah", "")
 
print """
{ "what": "It says %s" }
""" % strBlah.replace( '"', '\\"'

(Shamelessly stolen from http://www.petersblog.org/node/1011)

What you can see above is that the output from the CGI is a dictionary data structure you will know from Python. This is the JSON (JavaScript Object Notation) data format which is used to transport data back from the CGI into the Javascript. (Another way to encode the data is XML but I prefer JSON because it's easier human-readable and a bit shorter than the verbose XML.)

(Turbogears handles such requests a bit nicer. Check out http://docs.turbogears.org/1.0/TodoList)

If everything worked then after clicking on the submit button the <DIV> below the form that was invisible until now (because it was just empty) is now filled with a string from your CGI. To see what happens (or to debug things if something wrong happens) again I recommend the FireBug add-on to Firefox. Open it and click on Console. You will then see what happens in the background.

The request:

The response:

-- ChristophHaas 2007-01-02 23:40:37

WorkaroundOrg: AjaxWithMochikit (last edited 2007-01-02 23:41:04 by ChristophHaas)