Есть такой модуль — Vote Up Down. Весьма полезный, когда речь заходит обо всяких рейтингах, кармах и прочих количественных измерениях деятельности пользователей на сайте. Сам по себе он (модуль) вполне адекватный, в особенности если использовать подмодуль vud_field
. К слову, есть тенденция к замене всех составляющих Vote Up Down на одно это поле — вполне в духе седьмого Друпала.
Так или иначе, иногда требуется выполнить на сайте действия непосредственно после очередного пользовательского голоса. И получить по AJAXу ответ от сервера. Самый примитивный пример: голос за/против пользователя изменяет его рейтинг по определенной формуле — и нам надо обновить не только сам виджет голосовалки, но и рейтинг пользователя в каком-нибудь другом месте на странице.
Очевидно, нужно зацепиться в JavaScript-е за какое-нибудь событие. Можно было бы подвесить обработчик .click()
на кнопках голоса, но не тут-то было: когда обработчику будет передан контроль — вновь созданный голос еще не будет сохранен на сайте, и следовательно данные, которые мы получим в ответ, не будут актуальными.
Но — есть в jQuery возможность зацепиться за ajaxComplete
. Это событие происходит всякий раз, когда очередной запрос ajax был завершен. Посмотрим, как это применить к Vote Up Down.
PHP-часть, использующую ajax_command()
, оставим за бортом: благо в интернете немало руководств на эту тему для Drupal 7. Например, раз и два. Перейдем сразу к JavaScript-у:
(function ($) {
$(document).ready( function() {
$(document).ajaxComplete(processAjaxCallback);
});
function updateRates() {
//этот код отправит запрос по адресу /path/to/my/ajax
//в ответ мы ожидаем JSON с командами
var settings = {url : '/path/to/my/ajax'};
var ajax = new Drupal.ajax(false, false, settings);
ajax.eventResponse(ajax, {});
}
})(jQuery);
А теперь самое интересное — функция-обработчик события ajaxComplete. Первое, что нам нужно в ней сделать — это определить, что мы реагируем именно на событие голосования (мало ли какие еще ajax-вызовы у нас есть). Для этого у функции-обработчика есть аргумент: объект options, а точнее его свойство url. Это URL, по которому был совершен запрос — по нему-то мы и поймем, что имеем дело с нужным событием. URL-ов, по которым Vote Up Down отправляет голоса, два (они чуть-чуть отличаются). Нас в них интересуют — тип голоса (vote или votereset, последний это сброс голоса), сущность, за которую голосует пользователь (node, user, comment) и хэш. Хэш нужен, потому что, во-первых, модуль Vote Up Down использует его, чтоб отличать одно действие по голосованию от другого, и во-вторых — на случай повторных запросов. Итак, URL-ы вот такие:
- vote/entitytype/%/%/%/%/hash/…
- votereset/entitytype/%/%/%/hash/…
Код функции-обработчика:
function processAjaxCallback(event, response, options) {
if (processAjaxCallback.voteHash == 'undefined') {
//в статической переменной будем хранить хэш последнего запроса
processAjaxCallback.voteHash = 'none';
}
var url_parts = options.url.split("/");
//проверим, "наш" ли это запрос
if ((url_parts[1] !== 'vote') && (url_parts[1] !== 'votereset')) {
return ;
}
var newVoteHash;
if (url_parts[1] == 'vote') {
var newVoteHash = url_parts[7];
} else {
//как показано выше, в случае votereset хэш на другой позиции URL
var newVoteHash = url_parts[6];
}
//если хэш отличается, значит это новый запрос - запускаем нужные действия
if (processAjaxCallback.voteHash != newVoteHash) {
updateRates();
//и сохраняем новый хэш в статической переменной
processAjaxCallback.voteHash = newVoteHash;
}
return ;
}
})(jQuery);