Drupal

Revenge of the node comments: a pure jQuery comment pager

A previous post described how to reposition node comments with Drupal's hook_menu_alter(), to facilitate a tabbed interface. One side effect that popped up was pagers – when a pager link was clicked, the tab state got reset. The solution was to refresh the #comments div with AJAX. As an interesting twist, it uses the ability of jQuery's $() to construct a new DOM object from HTML. This means that no new menu callback is needed in Drupal; it fetches the comments directly from the href in the pager link. While a little inefficient, this technique has the cool benefit of being able to grab any content from anywhere on your site, with merely a URL and a selector. It also degrades gracefully for non-javascript users; since without JS the tabs appear as sequential blocks the pager will function normally. (The following code is based on the AJAX Comments project).


Filed under:

A previous post described how to reposition node comments with Drupal's hook_menu_alter(), to facilitate a tabbed interface. One side effect that popped up was pagers – when a pager link was clicked, the tab state got reset. The solution was to refresh the #comments div with AJAX. As an interesting twist, it uses the ability of jQuery's $() to construct a new DOM object from HTML. This means that no new menu callback is needed in Drupal; it fetches the comments directly from the href in the pager link. While a little inefficient, this technique has the cool benefit of being able to grab any content from anywhere on your site, with merely a URL and a selector. It also degrades gracefully for non-javascript users; since without JS the tabs appear as sequential blocks the pager will function normally.

comments in a tab

(The following code is based on the AJAX Comments project).

/**
 * Attaches the ahah behavior to each ahah form element.
 */
Drupal.behaviors.ajax_comments_pager = function(context) {
  $('#comments .pager:not(.pager-processed)', context).addClass('pager-processed').each(
    function() {
    $target = $(this);
    $target
      .find('li > a')
      .click(function () {
        $(this).animate({paddingRight:16}, 'fast').addClass('throbber').removeAttr('style');
        Drupal.turn_over_page($target, $(this).attr('href'), true, function(){}, function(){
          $(this).removeClass('throbber');
        });
        return false;
      });
  });
}
 
/**
 * Turn over a single page.
 *
 *   @param target
 *     The .pager element.
 *   @param url
 *     New page URL.
 *   @param scroll
 *     Is scroll to comments header needed.
 *   @param success_callback
 *     Function which will be called after pagination
 *     (or immediately if pager does not exists).
 *   @param error_callback
 *     Function which will be called on AJAX error.
 */
Drupal.turn_over_page = function(target, url, scroll, success_callback, error_callback) {
  if (target.length && url) {
    ajaxPath = url;
    $.ajax({
      url: ajaxPath,
      type: 'GET',
      success: function(response) {
        $newComments = $(response).find('#comments');
        $("#comments").replaceWith($newComments);
        Drupal.attachBehaviors($newComments.parent());
        if (scroll) {
          offset = $('#product-tabs').offset();
          $('html,body').animate({scrollTop: offset.top});
        }
      },
      error: function() {
        error_callback();
        alert(Drupal.t("An error occurred at @path.", {'@path': ajaxPath}));
      },
      dataType: 'html'
    });
  }
  else {
    success_callback();
  }
}

Similar posts

Get notified on new marketing insights

Be the first to know about new B2B SaaS Marketing insights to build or refine your marketing function with the tools and knowledge of today’s industry.