In Ajax comments in Drupal 5: How I made it parts I and II we saw the code needed on the back-end. Now, let’s see what goes on the client side: the Javascript.
Submitting the comment with an ajax request
Basically, to add a comment we need the node id (nid) and the comment text. The code in the back-end will handle the user info and permissions. The first thing we do is find the comment form and the submit button. Then we hook the click event on the submit button.
-
var commentForm = jQuery('form#comment-form');
-
if (!commentForm.length) return;
-
var submitBtn = jQuery('#edit-submit');
-
if (!submitBtn.length) return;
-
-
submitBtn.click(function(ev)
-
{
-
// …
-
}
When the user clicks the submit button, we get the node id (we could have done on domready) and the comment text. If the comment is empty, we don’t do anything, so the comment will be submitted the standard way and Drupal will fail the comment form validation.
-
// Get Node Id
-
var nid = jQuery('#node-nid').text();
-
if (!nid) return true; // Do nothing…
-
if (parseInt(nid) <= 0) return true;
-
-
// Get Comment Text
-
var text = jQuery('#edit-comment').val();
-
if (!text) return true; // Let Drupal validate the form
Since we don’t want to get back just the comment added but all the new comments added by any user on this node, we want to pass the last comment id on screen.
-
// Get last comment Id
-
var lastComment = jQuery('div.comment:last');
-
var lastCommentId = (lastComment.length)? lastComment.id().split('-')[1] : 0;
Due to my limited knowledge of jQuery at the time, I used the load function for the ajax request. The problem with this function is that, from what I know, it only works on elements already included in the DOM. So before the request, I had to create a container for the new comments. The point of insertion will differ if the page already has comments or not:
-
// We got both nid and text. Let's create the comment holder
-
var comment = jQuery(document.createElement('div'));
-
comment.hide();
-
if (lastComment.length) {
-
lastComment.after(comment);
-
} else {
-
comment.insertBefore(jQuery('div.box'));
-
}
Finally, the load request:
-
// Ajax submit/load
-
comment.load('/add/comment',
-
{ 'nid': nid,
-
'text': text,
-
'lastcid': lastCommentId
-
},
-
function(responseText, textStatus, XMLHttpRequest) {
-
if (textStatus == 'success' && responseText) {
-
ajax_insert_comment(comment);
-
} else {
-
comment.remove();
-
alert("Error: No se pudo enviar el comentario");
-
}
-
}
-
);
If the request failed, the container was removed. If the request succeeded, the new comments were added to the page:
-
ajax_insert_comment = function(comment) {
-
// Insert new comments
-
comment.show();
-
};
And that was it! Ajax comments in Drupal working like a charm.
Adding/removing the “new” indicator
Now that I had my Ajax comments working I wanted them to look better. For example, I wanted the new added comments to have the “new” indicator, while at the same time I wanted to remove the indicator from the comments already on the screen. On ajax_insert_comment:
-
// Clear 'new' from previous comments
-
jQuery('div.comment').find('span.new').remove();
-
// Add 'new' indicator
-
var newcomment = jQuery(document.createElement('span'));
-
newcomment.addClass('new').html('new');
-
newcomment.insertBefore(comment.find('div.comment-author'));
And many other tweaks like that.
The code
Here is the whole code for ajax comment submission I currently use:
-
ajax_comments = function() {
-
var commentForm = jQuery('form#comment-form');
-
if (!commentForm.length) return;
-
var submitBtn = jQuery('#edit-submit');
-
if (!submitBtn.length) return;
-
-
submitBtn.val('Enviar comentario');
-
submitBtn.click(function(ev)
-
{
-
// Disable submit button
-
submitBtn.val('Enviando…').attr("disabled","disabled");
-
-
// Clear the 'edit' link from previous comments
-
jQuery('li.edit-comment-link').remove();
-
-
// Get Node Id
-
var nid = jQuery('#node-nid').text();
-
if (!nid) return true; // Do nothing…
-
if (parseInt(nid) <= 0) return true;
-
-
// Get Comment Text
-
var text = jQuery('#edit-comment').val();
-
if (!text) return true; // Let Drupal validate the form
-
-
// Get last comment Id
-
var lastComment = jQuery('div.comment:last');
-
var lastCommentId = (lastComment.length)? lastComment.id().split('-')[1] : 0;
-
-
// // We got both nid and text. Let's create the comment holder
-
var comment = jQuery(document.createElement('div'));
-
comment.hide();
-
if (lastComment.length) {
-
lastComment.after(comment);
-
} else {
-
comment.insertBefore(jQuery('div.box'));
-
}
-
-
// Ajax submit/load
-
comment.load('/add/comment',
-
{ 'nid': nid,
-
'text': text,
-
'lastcid': lastCommentId
-
},
-
function(responseText, textStatus, XMLHttpRequest) {
-
if (textStatus == 'success' && responseText) {
-
ajax_insert_comment(comment);
-
jQuery('#edit-comment').val('');
-
} else {
-
comment.remove();
-
alert("Error: No se pudo enviar el comentario");
-
}
-
// Reenable submit button
-
submitBtn.val('Enviar comentario').removeAttr("disabled");
-
}
-
);
-
-
return false;
-
});
-
};
-
-
ajax_insert_comment = function(comment) {
-
// Clear 'new' from previous comments
-
jQuery('div.comment').find('span.new').remove();
-
// Add 'new' indicator
-
var newcomment = jQuery(document.createElement('span'));
-
newcomment.addClass('new').html('new');
-
newcomment.insertBefore(comment.find('div.comment-author'));
-
// Remove comment count
-
comment.find('span.commentcount').empty();
-
// Insert new comments
-
comment.show();
-
jQuery('#edit-comment').focus();
-
};
-
-
jQuery(document).ready(function() {
-
ajax_comments();
-
});
As you can see, when I wrote this code back in July, I have just started using jQuery and I didn’t know much about event handling. So I used the old return true/false to stop the submit event if needed. Also, now that I see the code again I can think on better ways to do parts of it. Well, that’s a good sign: it means I’m getting better :)
Series:
Ajax comments in Drupal 5: How I made it – Part I
Ajax comments in Drupal 5: How I made it – Part II
Ajax comments in Drupal 5: How I made it – Part III
See the ajax comments in action
Please, note this is a WordPress based blog. The Drupal website where I have implemented the ajax comments is www.spaniards.es