Как вывести webform в попапе

Сегодня мы поговорим о том, как вывести в попапе форму, создаваемую модулем Webform. Выводить ее мы будем с помощью Ctools modal API, более подробно я уже писал о нем в своем уроке Ctools modal API. Работа с модальными окнами.

Шаг 1. Создаем страницу, на которую будет посылаться ajax запрос:

/**
 * Implements hook_menu().
 */
function example_menu() {
  $items = array();
  $items['example/%ctools_js/%node'] = array(
    'page callback' => 'example_page_ajax',
    'page arguments' => array(1, 2),
    'access callback' => '_example_node_access',
    'access arguments' => array(2),
    'delivery callback' => 'ajax_deliver',
    'theme callback' => 'ajax_base_page_theme',
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Determines whether the current user may perform the operation on the node.
 *
 * @param $node
 *   The node object on which the operation is to be performed.
 *
 * @return bool
 *   TRUE if the operation may be performed, FALSE otherwise.
 */
function _example_node_access($node) {
  if (!is_object($node) || $node->type != 'webform') {
    return FALSE;
  }
  
  return node_access('view', $node);
}

/*
 * Show webform in popup.
 */
function example_page_ajax($js = NULL, $node) {
  if (!$js) {
    drupal_goto('node/' . $node->nid);
  }
  
  ctools_include('modal');
  
  $submission = (object) array();

  $form_state = array(
    'title' => $node->title,
    'ajax' => TRUE,
    'build_info' => array(
      'args' => array($node, $submission),
    ),
  );
  
  $commands = ctools_modal_form_wrapper('webform_client_form_' . $node->nid, $form_state);
  
  if (!empty($form_state['executed'])) {
    ctools_include('ajax');
    $commands = array();
    $commands[] = ctools_ajax_command_redirect('node/' . $node->nid . '/done');
  }

  return array('#type' => 'ajax', '#commands' => $commands);
}

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

/**
 * Add js and css files.
 */
function _example_include_modal() {
  static $added = FALSE;
  if (!$added) {

    // Подключаем библиотеки только один раз.
    $added = TRUE;

    // Подключаем библиотеки.
    ctools_include('modal');
    ctools_include('ajax');
    ctools_modal_add_js();

    // Создаем массив с настройками для модального окна.
    $script = array(
      'example' => array(
        'modalSize' => array(
          'type' => 'fixed',
          'width' => 480,
          'height' => 'auto',
          'contentRight' => 30,
          'contentBottom' => 0,
        ),
        'modalOptions' => array(
          'opacity' => (float) 0.4,
          'background-color' => '#000000',
        ),
        'closeText' => '',
        'animation' => 'fadeIn',
        'animationSpeed' => 'fast',
      ),
    );
    drupal_add_js($script, 'setting');
  }
}

Шаг 3. Подключаем библиотеки:

/**
 * Implements hook_init().
 */
function example_init() {
  // Подключаем библиотеки только на главной странице.
  if (drupal_is_front_page()) {
    _example_include_modal();
  }
}

Шаг 4. Выводим ссылку, клик по которой открывает попап. В нужном месте вставляем следующий код:

<a class="ctools-modal-example ctools-use-modal" href="/example/nojs/node_id">Открой меня!</a>

Вот и все. Хочу обратить внимание, что библиотеки мы подключили только на главной, поэтому на других страницах попап работать не будет.

Комментарии (21)

Аватар пользователя Диана
Диана

Добрый день!
Спасибо за статью.
Подскажите плз, после отправки формы, ответ о том, что форма отправлена, должен быть в попапе же? У меня редиректит на страницу node/9/done, что я могла не так сделать?

Аватар пользователя Benya
Benya

Здравствуйте, если Вы копировали код с урока, то поведение правильное, потому что этот кусок кода делает редирект:

$commands[] = ctools_ajax_command_redirect('node/' . $node->nid . '/done');

Если редирект не нужен, то необходимо использовать другие команды

Аватар пользователя Дмитрий
Дмитрий

А не подскажете как показать завершающее сообщение самой вебформы? На этой же странице где она была отправлена, без редиректа.

Аватар пользователя Benya
Benya

Сообщение необходимо показать в попапе или попап должен закрыться и где то на странице показать сообщение?

Аватар пользователя Benya
Benya

Вам нужно использовать команду ajax_command_html для вывода сообщения, а затем через несколько секунд ctools_modal_command_dismiss, чтобы закрыть модальное окно

Аватар пользователя Алексей
Алексей

Не работает с jQuery выше 1.8
Весь мозг сломал пока догадался....

Аватар пользователя Алексей
Алексей

Важное замечание

// $submission = (object) array(); вообще не нужна

$form_state = array(
  'title' => $node->title,
  'ajax' => TRUE,
  'build_info' => array(
    'args' => array($node, FALSE), // Нужно заменить на FALSE - из-за этого генерируется ошибка  Notice:    //Undefined property: stdClass::$is_draft в функции webform_client_form()
  ),
);

А так работает чисто.

Аватар пользователя Benya
Benya

На FALSE нужно заменять только если убираем $submission = (object) array();. Особой разницы нету, передавать пустой объект или FALSE в данном случае

Аватар пользователя Дмитрий
Дмитрий

А у вас такой ошибки не возникало 'Attr.nodeValue' is deprecated. Please use 'value' instead.
И еще есть вопрос. Возможно, что из-за этой ошибки мои команды не выполняются? Аякс-команды после отправки формы.

Аватар пользователя Алексей
Алексей

Но именно когда там стоит пустой объект возникает ошибка после сабмита

Аватар пользователя Benya
Benya

Нет, у меня такой ошибки не было. Ишите проблему ошибки. Аякс команды могут отвалиться из-за ошибок в js

Аватар пользователя Benya
Benya

Когда писал урок, ошибок не было. Предполагаю, что в модуле изменился код. Надо будет посмотреть подробнее, что изменилось...

Аватар пользователя Дмитрий
Дмитрий

А какая у вас версия js подключена

Аватар пользователя Александр
Александр

Спасибо, очень полезный материал. Подскажите пожалуйста как сделать чтобы  ctools_modal_command_dismiss срабатывал через несколько секунд.

Аватар пользователя Александр
Александр

Здравствуйте, отличный материал. Не подскачите как вывести форму написанную в модуле. Спасибо.

Аватар пользователя Benya
Benya

Здравствуйте. Как и любую другую, принцип такой же