УрокРабота с AJAX в Drupal

AJAX - Asynchronous Javascript and XML. Использование AJAX позволяет делать запросы к серверной части сайта и получать от него ответ без перезагрузки страницы. Преимущество использования AJAX в том, что загружается только необходимая часть - соответственно, загрузка происходит быстрее (не надо подгружать остальные элементы сайта).

Я хочу рассмотреть следующий пример: на сайте в блоке есть список заголовков нод. При нажатии на заголовок в контентную область загружается содержимое ноды без перезагрузки страницы.

Первым шагом создаём свой модуль. Назовём его, к примеру, nloader (англ. node loader - загрузчик материалов).

Файл nloader.info:

name = Node loader
description = Allows load node's content using AJAX
core = 6.x

Далее рядом создаём nloader.module (Drupal 6):

<?php
 
/**
 * Implementation of hook_block()
 */
function nloader_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    // Заголовок блока в разделе /admin/build/block
    $block[] = array(
      'info' => t('Block with node titles'), 
    );
    return $block;
  }
  else if ($op == 'view') {
    // Подгружаем скрипт, который будет отслеживать нажатие на заголовок материала
    // и отправлять запрос на сервер
    drupal_add_js(drupal_get_path('module', 'nloader') . '/nloader.js');
    // Содержимое блока при просмотре
    $block = array(
      'subject' => t('Last nodes'), 
      'content' => nloader_block_content(),
    );
    return $block;
  }
}
 
function nloader_block_content() {
  $amount = 10;  // Количество заголовков в блоке
  // Выбираем из базы заголовки и айдишники 10ти последних нод
  $result = db_query_range('SELECT title, nid FROM {node} WHERE status = 1 ORDER BY created DESC', 0, $amount);
  $output = array(); //Сюда будем помещать массив с заголовками нод
  while ($node = db_fetch_object($result)) {
    // Добавляем аттрибут rel, чтобы в коде был отображён nid материала
    // По этому nid будет загружаться материал
    $output[] = l($node->title, 'node/'. $node->nid, array('attributes' => array('rel' => $node->nid)));  
  }
  // Возвращаем список с заголовками материалов, присвоив этому списку класс nloader
  return theme('item_list', $output, NULL, 'ul', array('class' => 'nloader'));
}
 
/**
 * Implementation of hook_menu()
 */
function nloader_menu() {
  //Здесь создаём страницу на сайте, на которую будет передан AJAX запрос
  $items = array();
  $items['nloader_ajax'] = array(
    'title' => 'Ajax callback', // Заголовок страницы
    'page callback' => 'nloader_ajax_callback', // Имя функции, которая вызывается при переходе на  страницу
    'access callback' => TRUE, // Страница доступна для всех пользователей
    'type' => MENU_CALLBACK, // Указываем тип страницы - обычная страница
  );
  return $items;
}
 
/**
 * Эта функция вызывается при открытии страницы /nloader_ajax
 * либо при передаче на неё запросов (чем мы и воспользуемся!)
 */
function nloader_ajax_callback() {
  if ($_POST['nid']) {
    // Если в запросе был передан nid материала - загружаем его и возвращаем содержимое
    // предварительно проверив содержимое на корректность (оно должно состоять только из цифр)
    if (ctype_digit($_POST['nid'])) {
      $nid = $_POST['nid'];
      // Загружаем содержимое материала из базы вместе с его фильтром
      $content = db_fetch_object(db_query_range('SELECT body, filter FROM {node_revisions} WHERE nid = %d', $nid, 0, 1));      
      if ($content->body) {
        // Если содержимое получено - отдаём его клиенту, отфильтровав перед отправкой
        print check_markup($content->body, $content->filter);
      }
      else {
        // Если содержимое не найдено - выводим соответствующую надпись
        print 'Содержимое не найдено';
      }
    }
  }
  else {
    // Если на страницу просто зайти - делаем вид что её не существует
    drupal_not_found();
  } 
}

Теперь создаём в этой же папке nloader.js. Его содержимое:

Drupal.behaviors.nloader = function (context) {
  $('.nloader a', context).click(function () {
    // Получаем аттрибут rel у ссылки (туда мы вывели nid материала)
    var rel = $(this).attr('rel');
    // Если этот nid получен - отправляем запрос на сервер 
    if (rel) {
      // Первый параметр - страница, на которую отправляется запрос
      //  в нашем случае это /nloader_ajax. Будет вызвана функция nloader_ajax_callback()
      // Второй параметр - список переменных, которые передаются на сервер. Мы отдаём nid.
      // Третий параметр - функция, которая будет вызвана, когда получится ответ от сервера. 
      // В этой функции data - это содержимое нашего материала, либо текст 'Содержимое не найдено'
      $.post(
        Drupal.settings.basePath + 'nloader_ajax',
        {
          nid: rel
        },
        function (data) {
          // Здесь скорее всего вам надо будет поменять селектор $('.content') на другой,
          // в зависимости от того, куда вам нужно положить содержимое материала.
          // Селекторы выбираются так же, как и в css. Пример: $('#content .node_container')
          $('.content', context).html(data);
        }
      );      
    }
    //Чтобы основное нажатие на кнопку не отработало, и не перекинуло на новую страницу
    return false;
  });
};

Вот и вся хитрость. На самом деле - это самый простой пример использования AJAX..

Скачать исходники

Комментарии

Аватар пользователя Константин
Константин написал:

А для drupal 7 также будет?

12.01.2012 15:36
Аватар пользователя Spleshka
Spleshka написал:

Да, только hook_block разбился на подхуки. А сам смысл работы не изменился.

13.01.2012 22:31
Аватар пользователя OS_
OS_ написал:

Подскажите.

$(document).ready(function()
{
  $('.paragraf a').bind('click',function(){
   $('#bd').load( 'Drupal.settings.basePath + guest_book');
 
    return false;
    });
 });

Мне нужно подгрузить значения из БД, а получается, что загружается и значения из БД и вся страница /guest_book в #bd

19.01.2012 13:31
Аватар пользователя Spleshka
Spleshka написал:

покажите серверную часть кода, или вы только из какого-то региона хотите данные получить?

20.01.2012 02:26
Аватар пользователя Аллаур
Аллаур написал:

А пример что получилось посмотреть можно?

17.07.2013 01:26
Аватар пользователя ShamAn
ShamAn написал:

Делал не блоком, а в выводе на странице вызывал первую функцию. в итоге получил список первых нужных ссылок, но по нажатию он по ним переходит перегружая всю страницу

04.09.2013 06:58

Комментировать