Создание AJAX ссылок с использованием Drupal Ajax Framework

В этой заметке мы рассмотрим как использовать Drupal Ajax Framework для создания AJAX ссылок.

Чтобы продемонстрировать как это работает напишем небольшой модуль Author deck (машинное имя author_deck) который будет предоставлять блок Author info. В этом блоке будет отображаться имя пользователя (username) и аватар, а вся остальная информация будет подгружаться с помощью AJAX при нажатии на ссылку More info.

Итак приступим к написанию модуля:

Первым делом создадим файл author_deck.info:

name = Author deck
description = Provide author deck block.
core = 7.x
package = Custom

Далее создадим файл author_deck.module и объявим в нем хуки hook_block_info() и hook_block_view():

module_load_include('inc', 'author_deck', 'author_deck.blocks');
 
/**
 * Implements hook_block().
 */
function author_deck_block_info() {
  $blocks['author_deck'] = array(
    'info' => t('Author info'),
    'cache' => DRUPAL_NO_CACHE,
  );
 
  return $blocks;
}
 
/**
 * Implements hook_block_view().
 */
function author_deck_block_view($delta = '') {
  $block = array();
 
  switch ($delta) {
    case 'author_deck':
      $block['subject'] = t('Author info');
      $block['content'] = author_deck_get_author_deck_block();
      break;
  }
  return $block;
}

Функция author_deck_get_author_deck_block()с помощью которой мы получаем содержимое блока будет содержаться в файле author_deck.blocks.inc. Создадим этот файл со следующим содержимым:

/**
 * Reture content of author deck block.
 */
function author_deck_get_author_deck_block() {
  // check if it node view page
  if(arg(0) == 'node' && is_numeric(arg(1)) && ((arg(2) == '' || arg(2) == 'view'))) {
    $node = menu_get_object();
    if ($node->uid != 0) {
      drupal_add_library('system', 'drupal.ajax');
      $author = user_load($node->uid);
      return theme('author_deck', array('user' => $author));
    }
  }
}

Разберем код этой функции:

Первым делом мы проверяем является ли страница на которой мы находимся страницей отображения материала node/%node или node/%node/view так как на других страницах этот блок отображать нет смысла.

Далее получаем объект нода с помощью функции menu_get_object(). После этого проверяем не является ли автор анонимом. И наконец если все условия выполнены подключаем библиотеку ajax.js, загружаем объект автора нода и передаем его в функцию темизации которую мы опишем далее.

Добавляем hook_theme() в файл author_deck.module и опишем в нем две функции темизации:

/**
 * Implements hook_theme().
 */
function author_deck_theme($existing, $type, $theme, $path) {
  return array(
    'author_deck' => array(
      'variables' => array(
        'user' => NULL,
      ),
      'file' => 'author_deck.theme.inc',
    ),
    'author_deck_more_info' => array(
      'variables' => array(
        'user' => NULL,
        'fields' => array(),
      ),
      'file' => 'author_deck.theme.inc',
    ),
  );
}

Первая функции theme_author_deck будет использоваться для темизации содержимого блока, а функция theme_author_deck_more_info для темизации подгружаемого через AJAX содержимого.

Теперь создадим файл author_deck.theme.inc и добавим в него первую функцию темизации:

/**
 * Theme author deck block.
 */
function theme_author_deck($vars) {
  $output = '';
 
  $user = $vars['user'];
 
  $output .= '<h3>' . $user->name . '</h3>';
 
  if (!empty($user->picture)) {
    $image_data = array(
      'path' => $user->picture->uri,
      'style_name' => 'thumbnail',
    );
 
    $output .= theme('image_style', $image_data);
  }
 
  $output .= '<div id="author-deck-more-info-wrapper">';
    $output .= l(
      t('More info'),
      'author-more-info/' . $user->uid . '/nojs',
      array('attributes' => array('class' => array('use-ajax')))
    );
  $output .= '</div>';
 
  return $output;
}

Тут надо обратить внимание на создание ссылки More info. Это и будет AJAX ссылка при нажатии на которую будет подгружаться информация об авторе. Во первых мы добавляем в нее специальный класс use-ajax с помощью которого Drupal Ajax Framework понимает какие ссылки нужно обрабатывать с помощью AJAX, во вторых вторым параметром мы передаем строку nojs которую Drupal Ajax Framerowk в последствии превратит в строку ajax, таким образом можно определить включен ли JavaScript в браузере пользователя нажавшего на ссылку.

Теперь опишем обработчик страницы (page callback) для ссылки More info. Для этого добавим hook_menu() в файл author_deck.module:

/**
 * Implements hook_menu().
 */
function author_deck_menu() {
  $items['author-more-info/%user/%'] = array(
    'page callback' => 'author_deck_get_author_more_info',
    'page arguments' => array(1, 2),
    'delivery callback' => 'ajax_deliver',
    'access callback' => TRUE,
    'file' => 'author_deck.pages.inc',
  );
  return $items;
}

Отличительной чертой от обычного обработчика страницы тут является параметр delivery callback в который мы передаем функцию ajax_deliver. В отличии от стандартного обработчика drupal_deliver_html_page который заворачивает содержимое страницы в остальной HTML функция ajax_deliver формирует ответ специально для Drupal Ajax Framework обработчика.

Следующим шагом создадим файл author_deck.pages.inc в котором будет находится функция author_deck_get_author_more_info формирующая набор AJAX команд:

/**
 * Get author more info.
 */
function author_deck_get_author_more_info($user, $js) {
  if ($js != 'ajax') {
    drupal_goto('user/' . $user->uid);
  }
  $fields = array(
    'field_first_name' => t('First name'),
    'field_last_name' => t('Last name'),
    'field_age' => t('Age'),
  );
 
  $output = theme('author_deck_more_info', array('user' => $user, 'fields' => $fields));
 
  $commands = array();
  $commands[] = ajax_command_replace('#author-deck-more-info-wrapper', $output);
  return array('#type' => 'ajax', '#commands' => $commands);
}

В этой функции первым делом мы проверяем равен ли параметр $js строке ajax чтобы определить что у пользователя включен JavaScript, если это не так то мы просто перенаправляем пользователя на страницу автора где он сможет просмотреть всю информацию об авторе.

Далее передаем в функцию theme_author_deck_more_info массив полей которые мы хотим получить и объект пользователя (автора). Получив необходимый HTML мы возвращаем одну единственную команду ajax_command_replace чтобы заменить содержимое элемента с id author-deck-more-info-wrapper (контейнера в котором содержится ссылка More info) новым содержимым с информацией об авторе.

Теперь добавим в файл author_deck.theme.inc недостающую функцию темизации:

/**
 * Theme author deck more info.
 */
function theme_author_deck_more_info($vars) {
  $output = '';
 
  $user = $vars['user'];
  $fields = $vars['fields'];
 
  foreach ($fields as $field_name => $label) {
    $field_items = field_get_items('user', $user, $field_name);
    if ($field_items) {
      $rendered_field = render(field_view_value('user', $user, $field_name, $field_items[0]));
      if (!empty($rendered_field)) {
        $output .= '<strong>' . $label . ':</strong> '. $rendered_field . '<br />';
      }
    }
  }
 
  return $output;
}

И наконец когда наш модуль author_deck готов проверим его в действии:

Первым делом создадим соответствующие поля в разделе Account settings:

Создание дополнительных полей для учетной записи

Далее заполним эти поля для администратора, также загрузим аватар.

Заполнение полей учетной записи

Включаем модуль author_deck.

Включение модуля author_deck

Размещаем блок Author info в регион Sidebar first.

Размещаем блок Author info в первую боковую панель

Создаем тестовую статью. На странице статьи видим наш блок Author info в котором значится имя пользователя автора статьи и аватар, а также присутствует ссылка More info

Отображение блока Author info

Нажав на ссылку видим что ссылка заменилась на загруженную посредством AJAX дополнительную информацию об авторе.

Отображение блока Author info после нажатия на AJAX ссылку

Итак мы рассмотрели простой пример использования Drupal Ajax Framework для создания AJAX ссылок. AJAX ссылки это очень полезный инструмент с помощью которого можно делать приятный для пользователя и интуитивный интерфейс сайтов и веб приложений.

Исходники модуля author_deck

Поделись с друзьями: