В предыдущем посте я приводил пример, демонстрирующий использование Ctools modal API с помощью одной формы. В этом же я сделаю акцент на использовании еще одного мощного инструмента, а именно, Ctools multistep wizard - как с так и без задействования modal API.
Отбросим лирику и воздержимся от упоминания того, что при разработке сайта с помощью данного инструмента можно делать и няшные формы создания ноды, и создания юзера, а также регистрации и т.п. А с использованием всплывающих окон (попап-ов) этот процесс перейдет на визуально новый уровень.
Итак, как обычно, начнем с hook_menu(). Объявляем страничку, с которой будем вызывать многошаговую форму и саму страницу формы:
/**
* Implements hook_menu().
*/
function multi_example_menu() {
$items['example/%ctools_js/form'] = array(
'title' => 'Example form',
'page callback' => 'multi_example_form',
'page arguments' => array(1),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['example-link'] = array(
'title' => 'Example form link',
'page callback' => 'multi_example_link',
'page arguments' => array(1),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
Функции, генерирующие объявленные страницы:
/**
* Page callback: Handles multistep precessing.
*
* @return string
* Multistep wizard output.
*
* @see multi_example_menu()
*/
function multi_example_form($js = NULL, $step = NULL) {
if ($js) {
ctools_include('modal');
ctools_include('ajax');
}
// Define array for ctools multistep wizard.
$form_info = array(
'id' => 'multi_example',
'path' => "example/" . ($js ? 'ajax' : 'nojs') . "/form/%step",
'show trail' => TRUE,
'show back' => TRUE,
'show cancel' => TRUE,
'show return' => FALSE,
'next callback' => 'multi_example_wizard_next',
'finish callback' => 'multi_example_wizard_finish',
'cancel callback' => 'multi_example_wizard_cancel',
// Define forms order.
'order' => array(
'start' => t('Enter your info'),
'second' => t('What do you know?'),
'third' => t('What do think about drupal?'),
'fourth' => t('Do you like cookies?'),
),
// Define forms
'forms' => array(
'start' => array(
'form id' => 'multi_example_form_start'
),
'second' => array(
'form id' => 'multi_example_form_second'
),
'third' => array(
'form id' => 'multi_example_form_third'
),
'fourth' => array(
'form id' => 'multi_example_form_fourth'
),
),
);
// We're not using any real storage here, so we're going to set our
// object_id to 1. When using wizard forms, id management turns
// out to be one of the hardest parts. Editing an object with an id
// is easy, but new objects don't usually have ids until somewhere
// in creation.
//
// We skip all this here by just using an id of 1.
$object_id = 1;
if (empty($step)) {
// We reset the form when $step is NULL because that means they have
// for whatever reason started over.
multi_example_cache_clear($object_id);
$step = 'start';
}
// This automatically gets defaults if there wasn't anything saved.
$object = multi_example_cache_get($object_id);
// live $form_state changes.
$form_state = array(
'ajax' => $js,
// Put our object and ID into the form state cache so we can easily find it.
'object_id' => $object_id,
'object' => &$object,
);
// Send this all off to our form. This is like drupal_get_form only wizardy.
ctools_include('wizard');
$form = ctools_wizard_multistep_form($form_info, $step, $form_state);
$output = drupal_render($form);
if ($js) {
// If javascript is active, we have to use a render array.
$commands = array();
if ($output === FALSE || !empty($form_state['complete'])) {
// Dismiss the modal.
$commands[] = ajax_command_html('#ctools-sample', render(multi_example_get_result($object)));
$commands[] = ctools_modal_command_dismiss();
}
elseif (!empty($form_state['cancel'])) {
// If cancelling, return to the activity.
$commands[] = ctools_modal_command_dismiss();
}
else {
$commands = ctools_modal_form_render($form_state, $output);
}
print ajax_render($commands);
}
else {
if ($output === FALSE || !empty($form_state['complete'])) {
return render(multi_example_get_result($object)) . "\n\r" . l(t('Back'), 'example-link');
}
elseif (!empty($form_state['cancel'])) {
drupal_goto('example-link');
}
else {
return $output;
}
}
}
