By default, the WordPress commenting system is woefully inadequate - one my biggest objections being that to post a comment, the page needs to refresh. You could switch to a third party system like Livefyre [Broken URL Removed] or Disqus, but if you'd prefer to keep everything in house or do some other kind of customization, then posting comments by AJAX is the least you should do.

You can see an example of this working here on MakeUseOf - when you post a comment, you won't leave the page - instead we'll send it through an AJAX call, and then send a quick "thank you" note back. Read on for a full tutorial.

For using non-WordPress functions as AJAX, please read my previous tutorial, and be sure to check out all the WordPress related articles.

Introduction

There are a two separate parts needed to get AJAX WordPress comments working, so lets explain those first to give you an overview of the whole process.

  • Some Javascript on the page that intercepts the user clicking the Add Comment submit button, that also makes it an AJAX call and also handles the response.
  • A PHP handler that hooks into the comment_post action

Javascript

First off, this is going to need jQuery, as does anything remotely exciting in web development nowadays. If you're not sure if it's already being loaded, go ahead and skip down to the Javascript code and try it anyway - if you have Firebug and the console log says "jQuery is undefined" when you refresh the page, then add this line to your functions.php file to ensure it's being loaded.

function google_jquery() {

if ( !is_admin() ) { wp_deregister_script('jquery'); wp_register_script('jquery', ("http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"), false);

wp_enqueue_script('jquery'); } }

add_action('wp_print_scripts ', 'google_jquery');

Note, that's an elaborate way of loading jQuery because we'll be using the latest version from Google CDNs, which is faster and more up to date than the one included by default with WordPress - so it might be a good idea to add that anyway even if jQuery is already loaded elsewhere.

Now, for the actual Javascript that will handle the comment form, we have a few options. The easiest is to just paste the code into your single.php template - assuming you don't have commenting enabled for pages as well.

Alternatively, you could paste into an existing .js file used by your theme, or create a new .js file in your theme directory. If you choose to put it into your own separate .js file and not paste it directly into your theme template, be sure to add the following lines to your functions.php, and note the filename is assumed to be ajaxcomments.js in the root of your theme folder.

add_action('init', 'ajaxcomments_load_js', 10);

function ajaxcomments_load_js(){

wp_enqueue_script('ajaxcomments', get_stylesheet_directory_uri().'/ajaxcomments.js');

}

Here is the Javascript to handle the comment form (or you can view it on pastebin):

<script type="text/javascript">

// AJAXified commenting system

jQuery('document').ready(function($){

var commentform=$('#commentform'); // find the comment form

commentform.prepend('<div id="comment-status" ></div>'); // add info panel before the form to provide feedback or errors

var statusdiv=$('#comment-status'); // define the infopanel

commentform.submit(function(){

//serialize and store form data in a variable

var formdata=commentform.serialize();

//Add a status message

statusdiv.html('<p>Processing...</p>');

//Extract action URL from commentform

var formurl=commentform.attr('action');

//Post Form with data

$.ajax({

type: 'post',

url: formurl,

data: formdata,

error: function(XMLHttpRequest, textStatus, errorThrown){

statusdiv.html('<p class="wdpajax-error" >You might have left one of the fields blank, or be posting too quickly</p>');

},

success: function(data, textStatus){

if(data=="success")

statusdiv.html('<p class="ajax-success" >Thanks for your comment. We appreciate your response.</p>');

else

statusdiv.html('<p class="ajax-error" >Please wait a while before posting your next comment</p>');

commentform.find('textarea[name=comment]').val('');

}

});

return false;

});

});</script>

To break the code down, we're first creating jQuery objects of the comment form (which assumes your comment form has the default css ID of "commentform"), and adding an empty info panel above it which we'll later use to display messages to the user about the progress of posting their comment.

commentform.submit is used to 'hijack' the submit button. We then serialize the form data (turn it into one long line of data), give a "Processing" message to the user in that info panel, and go ahead with an AJAX request. The AJAX request is a standard format, but not really in the scope of this tutorial today - suffice to say it reacts to either a success or error, and blanks out the form if successful to prevent the same comment being accidentally posted twice. Adjust the messages and errors as appropriate, or add some suitable styling to your theme's stylesheet if you'd like the error messages to stand out somehow. The last line - return false - prevents the form from completing it's default action.

PHP Handler

Lastly, we need something to prevent the page refresh and send the appropriate response back to the user as well as notifying the admin if the comment needs moderating, or notifying the author of a new comment. For this, we hook into the comment_post action which occurs just after it's added to the database, and detect if it was an AJAX request. Add this to your functions.php file:

(Also available at this pastebin)

add_action('comment_post', 'ajaxify_comments',20, 2);

function ajaxify_comments($comment_ID, $comment_status){

if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'){

//If AJAX Request Then

switch($comment_status){

case '0':

//notify moderator of unapproved comment

wp_notify_moderator($comment_ID);

case '1': //Approved comment

echo "success";

$commentdata=&get_comment($comment_ID, ARRAY_A);

$post=&get_post($commentdata['comment_post_ID']);

wp_notify_postauthor($comment_ID, $commentdata['comment_type']);

break;

default:

echo "error";

}

exit;

}

}

Spot Problems

If the page is still refreshing instead of posting through AJAX, it's likely to be one of two problems. One - you might not have jQuery loaded. Install Firebug, or enable Chrome developer tools, and check the console log for errors. If jQuery isn't found, go back up to the JavaScript section and read the first bit on adding jQuery to your theme. The second possibility is that your theme does something special to the comment form and it's ID is no longer "commentform". Check the source code, then adjust the var commentform=$('#commentform') line in the JavaScript to be the correct ID - that might work.

As ever, I'm around to help out further as much as I can, but please post links to an example URL where I can take a quick look.