В Drupal 7 появился новый AJAX Framework, который позволяет абстрагироваться от написания Javascript кода.
Ниже приведён пример модуля, создающий блок с последними комментариями и ссылкой "more", клик на которой подгружает следующую пачку комментариев.
1. Создаём функцию, которая возвращает содержимое блока (т.е. последние комментарии и ajax ссылку "more"):
/**
* Возвращает html код содержимого блока.
*/
function _last_comments_block_content($from_cid = NULL) {
// Выбираем комментарии из базы
$query = db_select('comment', 'c')
->fields('c', array('cid', 'nid', 'subject'))
->condition('status', COMMENT_PUBLISHED)
->orderBy('cid', 'DESC')
->range(0, 10);
if (!is_null($from_cid)) {
$query->condition('cid', $from_cid, '<');
}
$items = array();
foreach ($query->execute() as $comment) {
$items[] = l($comment->subject, 'node/' . $comment->nid, array('fragment' => 'comment-' . $comment->cid));
$last_cid = $comment->cid;
}
$content = theme('item_list', array('items' => $items));
$content .= '<div class="more-link">' . l('more', 'last-comments/' . $last_cid . '/nojs', array(
'attributes' => array(
'class' => array('use-ajax'),
'title' => 'More comments',
)
)) . '</div>';
return $content;
}
Чтобы наделить ссылку ajax функциями, ей нужно присвоить класс use-ajax
и добавить к адресу аргумент nojs
, чтобы в callback функции можно было опознать пользователей с отключённым javascript.
2. Создаём блок:
/**
* Implements hook_block_info().
*/
function last_comments_block_info() {
$blocks['last-comments'] = array('info' => 'Last comments');
return $blocks;
}
/**
* Implements hook_block_view().
*/
function last_comments_block_view($delta = '') {
$block = array();
if ($delta == 'last-comments') {
$block['subject'] = 'Last comments';
$block['content'] = '<div id="last-comments">' . _last_comments_block_content() . '</div>';
// подключаем необходимые ajax библиотеки
drupal_add_library('system', 'drupal.ajax');
drupal_add_library('system', 'jquery.form');
}
return $block;
}
Для работы AJAX-фреймворка, нужно не забыть подключить библиотеки drupal.ajax
(файл misc/ajax.js
) и jquery.form
(файл misc/form.js
).
3. Регистрируем адрес, по которому будут возвращаться данные:
/**
* Implements hook_menu().
*/
function last_comments_menu() {
$items['last-comments/%'] = array(
'title' => 'Last comments',
'page callback' => 'last_comments_ajax_callback',
'page arguments' => array(1),
'delivery callback' => 'ajax_deliver', // данные, возвращённые ф-ей last_comments_ajax_callback(), будут отданы в json формате
'access arguments' => array('access content'),
);
return $items;
}
В первом аргументе будет содержаться id последнего показанного комментария.
4. Реализуем callback указанный в hook_menu:
/**
* Menu callback.
*/
function last_comments_ajax_callback($from_cid, $mode = NULL) {
// Если у посетителя отключён javascript, то показываем ему сообщение
if ($mode != 'ajax') {
drupal_set_message('Enable Javascript');
drupal_goto(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '<front>');
}
// обновляем содержимое блока
$commands[] = ajax_command_html('#last-comments', _last_comments_block_content($from_cid));
return array(
'#type' => 'ajax',
'#commands' => $commands,
);
}
В калбаке возвращается не html код блока, а набор команд для AJAX-фреймворка. Например с помощью команды:
ajax_command_html('some-selector', 'some-text')
мы как бы говорим браузеру — заменить текст в селекторе some-selector
на some-text
, а браузер на это выполняет js код:
$('some-selector').html('some-text');
Встроенных команд не так много, но выручает универсальная ajax_command_invoke, с помощью которой можно дёргать любые методы jQuery. Например, чтобы сменить адрес у ссылки (атрибут href
) нужно добавить:
$commands[] = ajax_command_invoke('some-selector', 'attr', array('href', '/my/new/path'));
Что равносильно js коду:
$('some-selector').attr('href', '/my/new/path');
Ну вот и всё. Мы написали модуль без единой строчки яваскрипта. Исходники прилагаются.
Подробнее про Javascript, jQuery и AJAX разжевано в видео от лулаботов — jQuery and JavaScript in Drupal (конкретно про AJAX рассказывается в главе 10, по времени это 1:56).
Похожая статья на английском — Make a link use ajax in Drupal 7 (it's easy).
Видео урок на английском — Создание AJAX ссылок в Drupal 7.
Комментарии
В 8-ке этот вариант отдачи информации станет еще менее затратным http://drupal.org/node/1599108#comment-6161572
@andypost отлично. надеюсь когда-нибудь увижу в drupal ленивую загрузку целых модулей
Такой вопрос.
Сделал ajax при клике на ссылку. После ajax отрабатывает:
на текущую ссылку.
Но после обновления href ссылки ajax продолжает работать по старому href.
Как сделать ребилд ajax элемента не используя js кода? Вообще есть такая возможность?
Т.к. я вообще нихрена не нагуглил... :(
попробуйте удалить у ссылки класс ajax-processed ну и с Drupal.attachBehaviors поиграться
Спасибо, а как Drupal.attachBehaviors вызвать не из js, а как-нибудь используя команды?
никак
Кто подскажет можно ли (если ДА то как?) использовать в commands селектор текущего контекста? Например в Jquery селектор "THIS".
Что-то вроде этого:
$commands[] = ajax_command_remove(this);
никак нельзя, это основная проблема ajax-фреймворка
Привет.
Спасибо за статью, очень помогла. Но возник вопрос:
есть форма, которая выводится функцией:
Вызов происходит
Но остался вопрос, как задать темизацию этой формы. То есть выводит эти поля в столбец. А мне надо вывести их в строчку.
P.S. На самом деле конечно полей больше...
Какое отношение вопрос имеет к ajax ссылкам?
ну форма появляется после ajax ссылке.
То есть ajax должен возвращать форму обработанную как-то.
И где-то. А вот где и как, пока не могу найти :(
Сорри если не там задал вопрос.
Прочитайте статью внимательно - в menu callback для ajax ссылок надо возвращать команды, плюс формы в друпале вызываются с помощью drupal_get_form().
Можно ли в данном случае отключить троббер как в формах:
Или только через стили?
Выключить тробер полностью:
Убрать только тект тробера:
У меня из за чего то вставка идёт всей страницы, а не блока, который запрашиваю и вставляю в ajax_command_html.
Какая должна быть кнопка, по которой происходит клик на страницы, которая будет вызывать адресс, по которому будет происходить возврат данных?
это ссылка, а не кнопка
Ладно, вроде разобрался, что это ссылка, при том должна создаваться через l()
но почему если эту же ссылку вставлю через js, с соблюдением того же пути и классов, то она не будет работать?
(Это для того, что она не должна быть всегда, а только при определённых условиях и заменять обычную кнопку.)
Наверно потому, что не вызываете Drupal.attachBehaviors
Добавить комментарий