2 June, 2009

MooTools AJAX Comment Form

by: Benjamin Kuker

In this tutorial, we're going to create an AJAX form using the MooTools JavaScript framework. This technique can be used for any type of form, but for the sake of demonstration, we'll concentrate on building a comment form that submits a comment and adds it to the comments section without reloading the page.

Whay use AJAX?

Forms are a problem area for many websites because nobody likes filling them out. Some forms require too much personal information, others lose information when submitted, and some are just too slow because they require lengthy page reloads. By using AJAX to submit a form, we remove one of the causes of form friction by not requiring the user to reload the entire page. Because we will be providing instant feedback on the page, it will improve the user's perception of the website's responsiveness and give them a better impression of the site overall. It's a subtle effect, but every part counts when you want to build a professional website that compliments your brand.

A Word on Progressive Enhancement

Not everyone has JavaScript enabled, either by choice or because their browser doesn't support it. In most use cases, it is considered best practice to progressively enhance any features that you add to your website. What that means is that we need to first make sure the basic comment form works without JavaScript. Then, once it is working, we'll add the extra AJAX effects.

Step 1 - Our Sample Blog

Let's start by building a sample blog page. We'll be using PHP for this tutorial, but you can use any server-side scripting language that you like. I won't go into great detail about the XHTML or the CSS code because you can likely find other tutorials on those subjects, but the code in these samples will validate.

In your root directory, create a new XHTML page and name it blog.php.


<body>
<div id="pageWrapper">
  <div id="mainContent">
    <h1>Ajax Comment Demo</h1>
    <p>
       Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
       Mauris nisl risus, pretium ac, hendrerit sed, scelerisque
       a, mauris. Maecenas adipiscing, ligula sit amet lacinia
       pellentesque, turpis dolor hendrerit nibh, sed aliquet
       ligula nisi at nisi. Curabitur leo velit, elementum in,
       congue in, elementum ut, felis. Integer eu dui. Nullam ipsum
       nisi, feugiat tincidunt, condimentum nec, luctus sed,
       sapien....
    </p>

    <p>
       Cras fringilla, velit sed faucibus suscipit, enim...
    </p>

  </div>

  <div id="comments">
    <h2>Comments</h2>
    <ul id="commentList">
      <li>
        <h3>Virtuosi says</h3>
        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
           Mauris nisl risus, pretium ac, hendrerit sed, scelerisque a, mauris....
        </p>
      </li>
    </ul>

    <form id="commentForm" method="post" action="blog.php">
      <h3>What do you think?</h3>
      <div>
        <label for="name">Name</label>
        <input id="name" type="text" name="name" />
        <label for="comment">Comment</label>
        <textarea id="comment" name="comment" cols="40" rows="5"></textarea>
        <input type="submit" value="Submit" />
      </div>
    </form>

  </div>
</div>
</body>
</html>

We've created a sample blog article (the lorem ipsum text), a sample comment, and a comment form. If you're using Firefox, your page should look like this:

Form View

Step 2 - Some Simple Style

Next, let's add some styling using CSS.

In the head section of blog.php, add the following line of code right after the title element:

 <link rel="stylesheet" href="css/default.css">

Now we need to make our CSS file. Create a new folder in your root directory named 'css'. In your CSS directory, create a new CSS file and name it default.css.

In our CSS file, we'll start by adding a reset:

body, div, ul, li, p, h1, h2, h3, form, input, label {margin:0; padding:0;}

I'll let you decide the colors, but let's also add some spacing and alignment to our page.

/*Layout*/
#pageWrapper {width:80%; margin:0 auto;}
#comments {margin-top:2em; border-top:#999 solid 1px;}

/*Text*/
h1, h2, h3, p {margin:.5em 0em;}

As just a small touch, let's add a hover state to our list elements. It won't appear in Internet Explorer 6, but it should work in every other browser. We'll also set the comment list display to none and add some padding to the comment.

/*Comments*/
#commentList {list-style:none;}
#commentList li {padding:1em;}
#commentList li:hover {background:#EEE;}

We'll also fix our form layout so that the labels and inputs are all floated left.

/*Form*/
input, label, textarea {float:left; clear:left; margin:.15em 0em;}
label {font-weight:bold;}

We're finished with the CSS for now. Your default.css file should read:


body, div, ul, li, p, h1, h2, h3, form, input, label {margin:0; padding:0;}

/*Layout*/
#pageWrapper {width:80%; margin:0 auto;}
#comments {margin-top:2em; border-top:#999 solid 1px;}

/*Text*/
h1, h2, h3, p {margin:.5em 0em;}

/*Comments*/
#commentList {list-style:none;}
#commentList li {padding:1em;}
#commentList li:hover {background:#EEE;}

/*Form*/
input, label, textarea {float:left; clear:left; margin:.15em 0em;}
label {font-weight:bold;}

Our newly styled (but still rather plain looking) form should now look like this with the cursor hovering over the comment:

Form View with Style

Step 3 - Processing the form with PHP

You can skip this step if you aren't using PHP. Because interacting with a database is beyond the scope of this article, we'll simply filter the comment form, format it as a comment, and echo a new comment into our comment list. The comment won't be saved if you refresh the page.

We could add the PHP code that processes the comments to blog.phpi, but because we want to reuse it later, we're actually going to create a new PHP file called comment.php in our root directory, complete with the following code:


<?php
if ($_POST['comment']) {
  if ($_POST['name']) {
    $name = '<h3>'.strip_tags($_POST['name']).' says</h3>';
  } else {
    $name = '<h3>Anonymous says</h3>';
  }
  $comment = '<p>'.strip_tags($_POST['comment']).'</p>';
  echo "<li>$name$comment</li>";
}
?>

If we were working with a database, we would also further sanitize our user input against SQL injection before saving the form data to the database. Depending on the type of data you are collecting, you should add additional validations to ensure that it is properly formed. Common validations can include email addresses, websites, postal codes, and phone numbers among others.

Now we're going to include comment.php at the very end of the commentList ul element in blog.php so that it looks like:


<ul id="commentList">
<li>
    <h3>Virtuosi says</h3>
    <p>
      Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
      Mauris nisl risus, pretium ac, hendrerit sed, scelerisque a, mauris.
      Maecenas adipiscing, ligula sit amet lacinia pellentesque, turpis dolor
      hendrerit nibh, sed aliquet ligula nisi at nisi.
    </p>
  </li>
  <?php include_once('./comment.php'); ?>
</ul>

It's time to test our form. If it worked, you should be able to submit a comment and it will appear below our original comment.

Form View with Style

Step 4 - Adding AJAX with MooTools

MooTools can be downloaded from the MooTools site, or you can use the Google Ajax Library API if you'd like Google to host your framework files. We'll download ours. For this project, we'll only need the MooTools Core files, which you can get by selecting all of the checkboxes here and clicking download.

Save the MooTools file in a new folder called javascript. For simplicity's sake, we'll just call it mootools.js. At the same time, create another file called comment.jsi in the same folder.

In the head of blog.php, right below the stylesheet link, add script tags to each of the new JavaScript files. It's important to note that mootools.js must be first.

<script type="text/javascript" src="./javascript/mootools.js"></script>
<script type="text/javascript" src="./javascript/comment.js"></script>

Now it's time for the good stuff.

We'll start by adding the domready function to comments.js. Domready is a special MooTools function that runs as soon as the page has finished loading, but before the CSS and images are loaded and rendered. To test it out, we're going to add a simple alert dialog that will run as soon as the page loads.

window.addEvent('domready', function(){
  alert("hi");                                                                                                        
});

That's simple enough, but what we really want is to run a function when the form is submitted. To do that, we need to attach an event to our form, which has the id of commentForm. In MooTools, you can specify an element with an id by wrapping it with the dollar shortcut function : $('commentForm')i. To add the event, chain the addEvent function to the element reference and pass it the onSubmit event as a parameter.

window.addEvent('domready', function(){
  $('commentForm').addEvent('submit', function(){
    alert('hi');
  });
});

If you tested the script, you'll notice that the alert dialog appeared, but the page still submitted. We need to prevent the event from executing, which can be accomplished using the stop() function. As a reference to the onSubmit event, we'll add the variable e to our function and then includes a line that will prevent the form from submitting.

window.addEvent('domready', function(){
  $('commentForm').addEvent('submit', function(e){
    e.stop();
    alert('hi');
  });
});

MooTools makes using an AJAX request really simple. There are three different request objects in MooTools: Request, Request.HTML, and Request.JSON. Request.HTML and Request.JSON both inherit from Request, so any options that are passed into Request can also be used for child classes. For this tutorial, we'll use Request.HTML.

For our first attempt at AJAX, we'll look at three specific options: url, data, and onSuccess.

The url option simply tells MooTools where to direct the AJAX request. Since we're using comment.php to process our form, we'll set the value for url as 'comments.php' in our options array.

The data option tells the script where to get the data from. We could set the value as a string like 'name=John%20Doe&comment=Hello', but there's a much easier way. Using our dollar shortcut, we can just use the id of the form, $('commentForm'), rather than constructing a string from the form inputs.

Finally, onSuccess is a custom event and it's triggered when the AJAX request is successful. We'll set its value equal to a custom function. There are a few different ways the function could be done, but this method will work in all browsers (including Internet Explorer). I'll show you the code first and then I'll tell you what it does.

window.addEvent('domready', function(){
  $('commentForm').addEvent('submit', function(e){
    e.stop();
    var req = new Request.HTML({
      url: 'comment.php',
      data: $('commentForm'),
      onSuccess: function(tree, response){
        var li = new Element('li');
        var h3 = new Element('h3', {'text': response [1].get('text')}).inject(li);
        var p = new Element('p', {'text': response [2].get('text')}).inject(li);
        li.inject($('commentList')).highlight('#cff');
        $('commentForm').reset();
      }
     }).send();
  });
});

The onSuccess function can take several parameters, but we're only going to use the second, which we'll name response. First, we'll create a new li element. Next, we'll create a new h3 element and give its text the value of key 1 of the response array, which holds our name text. Because the array value is a DOM element, we'll also have to get its text value using the get method. Our last method will inject the h3 element into our li element. Repeat the process for the p element and make note that the array key for response will have to change from 1 to 2. Next, inject the li element into the commentList, which will cause it to appear dynamically on the page.

If you would like to add a small bit of useful eye-candy to the comment, you can use the highlight element method, chained directly after the inject() method. The comment will be highlighted in light blue briefly to let the user know that the page has been updated. For other highlight effects, feel free to experiment with the Fx.Tween class.

Finally, the last line in the onSuccess function will clear the form after it has updated. With the highlight, your finished product should look like the screenshot below.

The Completed Form

An Easy Alternative for Other Types of Forms

If you don't need your form to add to pre-existing content in an element, you can dynamically update any part of your page using the update option rather than onSuccess. The update option will replace a target element's content with the response HTML.

Let's try it.

window.addEvent('domready', function(){
  $('commentForm').addEvent('submit', function(e){
    e.stop();                      
    var req = new Request.HTML({
      url: 'comment.php',
      data: $('commentForm'),
      update: $('commentList') 
    }).send();                    
  });
});

Compared to our earlier code, using update is much easier. However, you'll notice that instead of adding a comment at the end of our comment list, it replaced the existing comment. It's not the perfect fit for a comment form on a blog, but this method can be quite useful for many other types of AJAX requests.

Conclusion

Congratulations. You've just learned the basics of creating a progressively-enhanced AJAX comment form using MooTools. You should be able to take your new knowledge and apply it to other types of forms and AJAX requests. Below, I've listed some resources where you can learn more about MooTools. Have fun.

MooTools Resources

Author

Virtuosi Media is a web development company based in Vancouver, British Columbia. They specialize in designing websites that help their clients' businesses grow. They also provide a variety of articles, tutorials and scripts for web developers.

For more information, visit their website:
http://www.virtuosimedia.com.



Sponsors:

About willCode4Beer