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).
/**
* 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();
}
}