Hijaxing Form Submission with Mootools

Not having used the mootools Javascript library to any great extent, I thought I’d try it out on our contact form and add a bit of AJAX to get rid of the page refresh when the form gets posted.

Mootools was chosen over other libraries like YUI, script.aculo.us or Prototype because it’s designed to be small, fast and modular. Because you choose the functions you need when you download, the script size is kept to a minimum - and can be as small as 2.4K.

We only want to use AJAX (and in this case some DOM scripting also) to enhance the experience for users with modern browsers while still providing support for less capable browsers. After reading this article on Hijaxing, it seemed like this would give us everything we wanted: browsers that support Javascript to a reasonable level will send the data via the XMLHTTPRequest object, and those that don’t simply use the standard POST mechanism. This way we can provide an enhanced experience for most users and still retain complete compatibility.

After a bit of probing around on the mootools demo pages I came across a example which did exactly what I needed. All I had to do was to extend it to suit my needs.

*Disclaimer:The following code snippets are just that - snippets - and will not work as is. This example also assumes a JSON object will be returned by the server, and will have a name attribute.*

window.addEvent('domready', function(){
$('myForm').addEvent('submit', function(e) {
new Event(e).stop();

*Note:The $() function is simply a mootools shortcut for the standard DOM document.getElementById() method*

If the browser supports Javascript, the above code will run once the DOM has finished loading and will hook up the submit event of myForm to execute an anonymous function. The submit event is then stopped so that the browser does not send the form via the normal POSTing mechanism, and allows us to send the data via an XMLHTTPRequest which mootools will handle for us.

if(this.action.indexOf('?xhr') == -1) this.action += '?xhr';

Next, we append a key to the end of our POST action (the location we’re posting to) so we can differentiate an AJAX POST from a normal POST. This allows the server to return differing content depending on the submission method:

  • JSON for the AJAX request
  • HTML for a standard POST

Now we send the request and provide a method to call when a response is received from the server:

this.send({ onComplete: function(resp) 
        if(!$defined(resp)) 
            return;

        var obj = Json.evaluate(resp);

        if($defined(obj))
        {
            var el = new Element('strong', {'class' : 'info'});
            el.setHTML('Thanks, ' + obj.name);
            el.injectAfter($(myForm));

            var fader = new Fx.Style('submitFeedback', 'opacity', { duration:1000 });
            fader.start(0, 1).chain(function() {
                this.start.delay(3000, this, [0.0]);
            });
        }
    });

If we get a valid response back from the server the JSON is evaluated, checked and we create a new <strong> element and set its class to info. We then concatenate 'Thanks ' and the value of obj.name and assign it to our newly created element. The element is then inserted immediately after the myForm element using the injectAfter() method.

Finally, we create an effects chain which will fade the newly create element in, and after 3 seconds fade it back out again.

That’s really all there is to it. So with relatively little code, you can provide an enhanced experience for most users while retaining compatibility for those with older browsers.

2007-07-03