Категория:
Опубликовано:

Делаем вертикальные вкладки с описанием

Vertical Tabs with description

Начиная с седьмой версии, в ядре Drupal есть поддержка т.н. "Вертикальных Вкладок" (или "Вертикальных Табов", "Vertical Tabs", как угодно).

Их создание и использование весьма тривиальны, как и весь FAPI 7-ки, и это не может не радовать.

Но, если посмотреть на табы полученные программно и на те, что нам предоставляет ядро (на страницах настройки типов материала или самих материалов и т.п.) - можно увидеть несколько модернизированный их вывод. А именно - у них есть своего-рода субтайтл, или краткое описание, в котором содержится перечень настроек из вкладки.

В этом посте посмотрим как это реализовано, и как мы можем использовать это в своих проектах.

Для начала напишем тестовую формочку с несколькими вертикальными табами:

function mymodule_form($form, &$form_state) {
  // Объявляем контейнер для вертикальных вкладок
  $form['container'] = array(
    '#type' => 'vertical_tabs',
  );

  // Теперь добавим филдсет-вкладку
  $form['container']['first_tab'] = array(
    '#type'        => 'fieldset',
    '#title'       => t('First Tab'),
    '#collapsible' => TRUE,
    '#group'       => 'group_tabs',
    '#attributes'  => array(
      'class' => array('mymodule-first-tab'),
    ),
  );

  // Добавим еще одну филдсет-вкладку
  $form['container']['second_tab'] = array(
    '#type'        => 'fieldset',
    '#title'       => t('Second Tab'),
    '#collapsible' => TRUE,
    '#group'       => 'group_tabs',
    '#attributes'  => array(
      'class' => array('mymodule-second-tab'),
    ),
  );

  // И еще одну
  $form['container']['third_tab'] = array(
    '#type'        => 'fieldset',
    '#title'       => t('Third Tab'),
    '#collapsible' => TRUE,
    '#group'       => 'group_tabs',
    '#attributes'  => array(
      'class' => array('mymodule-third-tab'),
    ),
  );
}

Сейчас у нас есть главный контейнер и 3 вертикальные вкладки. Также, мы добавили вкладкам атрибуты, в которых указали каждой свой класс. Немного позже расскажу зачем это нам.

Добавим немного стандартных элементов формы во вкладки:

// Текстовое поле для первой вкладки
$form['container']['third_tab']['sample_text'] = array(
  '#type'  => 'textfield',
  '#title' => t('Sample text'),
);

// Парочку чекбоксов для второй вкладки
$form['container']['second_tab']['sample_checkbox_one'] = array(
  '#type'          => 'checkbox',
  '#title'         => t('Sample checkbox - One'),
  '#default_value' => TRUE,
);

$form['container']['second_tab']['sample_checkbox_two'] = array(
  '#type'          => 'checkbox',
  '#title'         => t('Sample checkbox - Two'),
  '#default_value' => TRUE,
);

// И селект для третьей вкладки
$form['container']['third_tab']['sample_select'] = array(
  '#type'          => 'select',
  '#title'         => t('Sample select'),
  '#options'       => array(
    'one'   => 'One',
    'two'   => 'Two',
    'three' => 'Tree',
  ),
  '#default_value' => 1,
);

Теперь у нас есть формочка с табами и в каждом свои поля (настройки).

Перейдем к самой магии добавления краткого описания. Для этого нам нужно подключить 2 js-файла:

  • стандартный form.js (в нем объявлена jQuery-функция drupalGetSummary() необходимая для отображения субтайтлов);
  • и свой - в котором будем делать привязку.

Поместим в начало формы:

// Подключаем скрипты
$form['#attached']['js'] = array(
  drupal_add_library('system', 'jquery.form'), // Подключаем скрипт из misc/form.js
  drupal_get_path('module', 'mymodule') . '/mymodule.js', // Свой скрипт из корня модуля
);

Теперь открываем скрипт нашего модуля и наполняем приблизительно следующим содержимым:

(function ($) {
  Drupal.behaviors.mymodule = {
    attach: function (context, settings) {

      // First tab - логика для первого таба
      $('fieldset.mymodule-first-tab', context).drupalSetSummary(function (context) {
        // Получаем значение текстового поля
        var sampleText = $('.form-item-sample-text input', context).val();

        // Возвращаем установленное значение или дефолное
        return sampleText ? Drupal.t('Sample Text: ') + sampleText : Drupal.t('No value');
      });

      // Second tab - логика для второго таба
      $('fieldset.mymodule-second-tab', context).drupalSetSummary(function (context) {
        // Объявляем массив значений
        var vals = [];

        // Наполняем значениями отмеченных чекбоксов
        $('input:checked', context).parent().each(function () {
          vals.push(Drupal.checkPlain($.trim($(this).find('label').text())));
        });

        // Возвращаем значения разделив их запятой
        return vals.join(', ');
      });

      // Third tab - логика для третьего таба
      $('fieldset.mymodule-third-tab', context).drupalSetSummary(function (context) {
        // Получаем выбранное значение селекта
        var selectedText = $('.form-item-sample-select option:selected').text();

        // Возвращаем по аналогии с прошлыми, формируя нужный вывод
        return selectedText ? Drupal.t('Selected Text: ') + selectedText : Drupal.t('No value');
      });
    }
  };
})(jQuery);

Вот так - уже должно работать )).

И вот в этом скрипте мы и использовали те классы, которые присвоили табам.

Ниже привожу полный код формы:

function mymodule_form($form, &$form_state) {
  $form['#attached']['js'] = array(
    drupal_get_path('module', 'node') . '/node.js',
    drupal_get_path('module', 'mymodule') . '/mymodule.js',
  );

  $form['container'] = array(
    '#type' => 'vertical_tabs',
  );

  $form['container']['first_tab'] = array(
    '#type'        => 'fieldset',
    '#title'       => t('First Tab'),
    '#collapsible' => TRUE,
    '#group'       => 'group_tabs',
    '#attributes'  => array(
      'class' => array('mymodule-first-tab'),
    ),
  );

  $form['container']['second_tab'] = array(
    '#type'        => 'fieldset',
    '#title'       => t('Second Tab'),
    '#collapsible' => TRUE,
    '#group'       => 'group_tabs',
    '#attributes'  => array(
      'class' => array('mymodule-second-tab'),
    ),
  );

  $form['container']['third_tab'] = array(
    '#type'        => 'fieldset',
    '#title'       => t('Third Tab'),
    '#collapsible' => TRUE,
    '#group'       => 'group_tabs',
    '#attributes'  => array(
      'class' => array('mymodule-third-tab'),
    ),
  );

  $form['container']['third_tab']['sample_text'] = array(
    '#type'  => 'textfield',
    '#title' => t('Sample text'),
  );

  $form['container']['second_tab']['sample_checkbox_one'] = array(
    '#type'          => 'checkbox',
    '#title'         => t('Sample checkbox - One'),
    '#default_value' => TRUE,
  );

  $form['container']['second_tab']['sample_checkbox_two'] = array(
    '#type'          => 'checkbox',
    '#title'         => t('Sample checkbox - Two'),
    '#default_value' => TRUE,
  );

  $form['container']['third_tab']['sample_select'] = array(
    '#type'          => 'select',
    '#title'         => t('Sample select'),
    '#options'       => array(
      'one'   => 'One',
      'two'   => 'Two',
      'three' => 'Tree',
    ),
    '#default_value' => 1,
  );
}
Если у Вас возникли вопросы, замечания, предложения или просто благодарность - пишите в комментариях.
Делитесь полезными материалами в социальных сетях.

Комментарии

Скажите пожалуйста, а с помощью чего вы так красивенько подсвечиваете код в нодах?

Сейчас используется highlightjs.org, для Друпал есть соответствующий модуль

В будущем планирую перейти на prism (тоже есть интеграция).

Помимо них есть еще много хайлайтеров, можно поискать в интернете.

спасибо. буду их пробовать.
ваш привлек тем, что при копировании кода номера строк не копируются.

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

Prism - там можно добавить плагин нумерации, но нужно присваивать доп. класс к <pre>.