having fun with code

Ajax comments in Drupal 5: How I made it – Part III

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.

  1.   var commentForm = jQuery('form#comment-form');
  2.   if (!commentForm.length) return;
  3.   var submitBtn = jQuery('#edit-submit');
  4.   if (!submitBtn.length) return;
  5.  
  6.   submitBtn.click(function(ev)
  7.   {
  8.     // …
  9.   }

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.

  1.     // Get Node Id
  2.     var nid = jQuery('#node-nid').text();
  3.     if (!nid) return true; // Do nothing…
  4.     if (parseInt(nid) <= 0) return true;
  5.  
  6.     // Get Comment Text
  7.     var text = jQuery('#edit-comment').val();
  8.     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.

  1.     // Get last comment Id
  2.     var lastComment = jQuery('div.comment:last');
  3.     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:

  1.     // We got both nid and text. Let's create the comment holder
  2.     var comment = jQuery(document.createElement('div'));
  3.     comment.hide();
  4.     if (lastComment.length) {
  5.       lastComment.after(comment);
  6.     } else {
  7.       comment.insertBefore(jQuery('div.box'));
  8.     }

Finally, the load request:

  1.     // Ajax submit/load
  2.     comment.load('/add/comment',
  3.       {  'nid': nid,
  4.         'text': text,
  5.         'lastcid': lastCommentId
  6.       },
  7.       function(responseText, textStatus, XMLHttpRequest) {
  8.         if (textStatus == 'success' && responseText) {
  9.           ajax_insert_comment(comment);
  10.         } else {
  11.           comment.remove();
  12.           alert("Error: No se pudo enviar el comentario");
  13.         }
  14.       }
  15.     );

If the request failed, the container was removed. If the request succeeded, the new comments were added to the page:

  1. ajax_insert_comment = function(comment) {
  2.   // Insert new comments
  3.   comment.show();
  4. };

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:

  1.   // Clear 'new' from previous comments
  2.   jQuery('div.comment').find('span.new').remove();
  3.   // Add 'new' indicator
  4.   var newcomment = jQuery(document.createElement('span'));
  5.   newcomment.addClass('new').html('new');
  6.   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:

  1. ajax_comments = function() {
  2.   var commentForm = jQuery('form#comment-form');
  3.   if (!commentForm.length) return;
  4.   var submitBtn = jQuery('#edit-submit');
  5.   if (!submitBtn.length) return;
  6.  
  7.   submitBtn.val('Enviar comentario');
  8.   submitBtn.click(function(ev)
  9.   {
  10.     // Disable submit button
  11.     submitBtn.val('Enviando…').attr("disabled","disabled");
  12.  
  13.     // Clear the 'edit' link from previous comments
  14.     jQuery('li.edit-comment-link').remove();
  15.  
  16.     // Get Node Id
  17.     var nid = jQuery('#node-nid').text();
  18.     if (!nid) return true; // Do nothing…
  19.     if (parseInt(nid) <= 0) return true;
  20.  
  21.     // Get Comment Text
  22.     var text = jQuery('#edit-comment').val();
  23.     if (!text) return true; // Let Drupal validate the form
  24.  
  25.     // Get last comment Id
  26.     var lastComment = jQuery('div.comment:last');
  27.     var lastCommentId = (lastComment.length)? lastComment.id().split('-')[1] : 0;
  28.  
  29.     // // We got both nid and text. Let's create the comment holder
  30.     var comment = jQuery(document.createElement('div'));
  31.     comment.hide();
  32.     if (lastComment.length) {
  33.       lastComment.after(comment);
  34.     } else {
  35.       comment.insertBefore(jQuery('div.box'));
  36.     }
  37.  
  38.     // Ajax submit/load
  39.     comment.load('/add/comment',
  40.       {  'nid': nid,
  41.         'text': text,
  42.         'lastcid': lastCommentId
  43.       },
  44.       function(responseText, textStatus, XMLHttpRequest) {
  45.         if (textStatus == 'success' && responseText) {
  46.           ajax_insert_comment(comment);
  47.           jQuery('#edit-comment').val('');
  48.         } else {
  49.           comment.remove();
  50.           alert("Error: No se pudo enviar el comentario");
  51.         }
  52.         // Reenable submit button
  53.         submitBtn.val('Enviar comentario').removeAttr("disabled");
  54.       }
  55.     );
  56.  
  57.     return false;
  58.   });
  59. };
  60.  
  61. ajax_insert_comment = function(comment) {
  62.   // Clear 'new' from previous comments
  63.   jQuery('div.comment').find('span.new').remove();
  64.   // Add 'new' indicator
  65.   var newcomment = jQuery(document.createElement('span'));
  66.   newcomment.addClass('new').html('new');
  67.   newcomment.insertBefore(comment.find('div.comment-author'));
  68.   // Remove comment count
  69.   comment.find('span.commentcount').empty();
  70.   // Insert new comments
  71.   comment.show();
  72.   jQuery('#edit-comment').focus();
  73. };
  74.  
  75. jQuery(document).ready(function() {
  76.   ajax_comments();
  77. });

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

Related Posts:

10 Comments to Ajax comments in Drupal 5: How I made it – Part III

  1. December 16, 2008 at 02:26 | Permalink

    Hi Eneko,

    thanks for the example! As a Drupal-Newbie, your site is a good point to start looking under the hood of Drupal.

    My question: Would it work in Drupal 6 too?

    Thanks,

    Fritz

  2. December 17, 2008 at 03:05 | Permalink

    I will give it a try. My next question is a newbie-question too:
    I basically know how to create simple modules with PHP, but:
    How does the JavaScript-code fit in the module? In which file is it?

    Thanks,

    Fritz

  3. December 18, 2008 at 04:00 | Permalink

    I tried it. It did not work yet. Probably some little mistake. I guess, I have to learn how the comments-module, the new module and the javascript-part play together to make it run – if it does work in Drupal 6. And I’m waiting for a Drupal-pro to try it too…

    AJAX-comments seem to be an important module in wordpress. Funny, that Drupal-people don’t show much interest.

    Thanks for your answers! :-)

  4. Alexwebmaster's Gravatar Alexwebmaster
    March 3, 2009 at 05:35 | Permalink

    Hello webmaster
    I would like to share with you a link to your site
    write me here preonrelt@mail.ru

  5. tester's Gravatar tester
    May 6, 2009 at 18:52 | Permalink

    nice

  6. May 16, 2009 at 22:25 | Permalink

    having a problem with this:

    -I’ve got the module enabled and am including your .js file in the page. But when I submit a comment as an authenticated user, the comment is created…but without the author information being saved in the DB.

    How do I get the author info to be saved in the DB?:

  7. June 11, 2009 at 23:42 | Permalink

    i want to add a comments section to my site the files are all html, and i would like to know if anyone has seen a ajax comment script?

    iv tried google but no luck

Leave a Reply

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Additional comments powered by BackType

About the blog

This is a blog about development, focused mainly on Javascript but also other languages like python, shell scripts and more.

About the author

Eneko Alonso is a software engineer and UI developer with more than eight years of experience in software and web development. He lives in San Luis Obispo, California and works at LEVEL Studios.

Contact Info

Contact Info

PromoteJS

JavaScript JS Documentation