Продолжение темы про вывод полей формы в одну строку. На этот раз мы изменим нашу функцию темизации с учетом разметки популярного фреймворка для разработки адаптивных web-проектов - Bootstrap 3.
Bootstrap включает в себя адаптивную резиновую систему разметки, которая масштабируется до 12 столбцов при изменении окна просмотра (при просмотре с различных устройств). Основная задача нашей фукции - обернуть нужные элементы формы в соответствующие контейнеры (div).
Пример двухколоночной разметки:
<div class="row">
<div class="col-md-8">.col-md-8</div>
<div class="col-md-4">.col-md-4</div>
</div>
row - класс, которым оборачивают всю строку. Внутри него размещают столбцы.Размеры столбцов задаются классами, типа col-md-xx (xx-число от 1 до 12). Допустимые преффиксы для колонок - col-xs-, col-sm-, col-md-, col-lg-. Собственно говоря, от преффикса зависит поведение блоков при различной ширине устройства. Итак, с теорией немного разобрались. Теперь перейдем к практике...
Объявляем функцию темизации:
/**
* Реализация hook_theme()
*/
function test_fieldinline_bootstrap_theme() {
return array(
'inline_fields_bootstrap' => array(
'render element' => 'element',
),
);
}
И пишем саму функцию. Для гибкой настройки предусмотрим некоторые ручные настройки для темизации. Список основных настроек (передаем их вместе со свойствами контейнера):
- '#bootstrap_prefix' - префикс для столбцов. Допустимые значения: col-xs-, col-sm-, col-md- (по-умолчанию), col-lg-
- '#not_div' - отключает у дочерних элементов обработку ['#theme_wrappers']. Параметр остался от предыдущей версии функции
- '#bootstrap_size_this' - По умолчанию, мы будем самостоятельно определять ширину колонок, равномерно распределяя их по ширине контейнера. Но, для ручного управления шириной столбцов, предусмотрим возможность передачи дополнительного параметра (передаем вместе со свойствами дочерних элементов)
Ниже приведу код функции theme_inline_fields_bootstrap с комментариями
/**
* theme функция вывода полей в один ряд используя сетку bootstrap (12 клонок)
*/
function theme_inline_fields_bootstrap($variables) {
$form = $variables['element'];
$fields = array();
//Класс префикса сетки bootstrap
$bootstrap_prefix = isset($form['#bootstrap_prefix']) ? $form['#bootstrap_prefix'] : 'col-md-';
//определим количество элементов в контейнере
$max = 12;
$bootstrap_size = 1;
$count = 0;
foreach ($form as $key => $element) {
if (substr($key, 0, 1) != '#') {
$count++;
}
}
//размер колонок
$bootstrap_size = $max > $count ? floor($max / $count) : 1;
//размер последней колонки. Может отличаться от остальных
$bootstrap_size_last = $max - ($count - 1) * $bootstrap_size;
$this_element = 0;
foreach ($form as $key => $element) {
// ищем дочерние поля
if (substr($key, 0, 1) != '#') {
$this_element++;
// если при валидации в поле была допущена ошибка, функция добавит к элементу класс error
_form_set_class($element, array());
if (isset($form['#not_div']) && $form['#not_div']) {
unset($element['#theme_wrappers']);
}
if (isset($element['#bootstrap_size_this']) && is_numeric($element['#bootstrap_size_this']) && $element['#bootstrap_size_this'] > 0 && $element['#bootstrap_size_this'] < $max) {
$bootstrap_size_this = $element['#bootstrap_size_this'];
}
else {
$bootstrap_size_this = ($this_element == $count) ? $bootstrap_size_last : $bootstrap_size;
}
$fields[] = '' . drupal_render($element) . '';
}
}
$form['#children'] = '' . implode('', $fields) . '';
return theme('form_element', array('element' => $form));
}
/*
* Form
*/
function test_fieldinline_bootstrap_form($form, &$form_state, $metal = NULL) {
$form = array();
//первый контейнер. В нем будет три колонки (3-6-3). Ширину дочерних элементов указываем вручную.
$form['cont'] = array(
'#type' => 'fieldset',
'#title' => 'Укажите параметры изделия',
'#collapsible' => FALSE,
'#collapsed' => FALSE,
'#theme' => array('inline_fields_bootstrap'),
'#not_div' => FALSE,
'#bootstrap_prefix' => 'col-md-',
'#title_display' => 'none',
);
$form['cont']['pole4'] = array(
'#type' => 'select',
'#default_value' => 0,
'#options' => array('Сталь', 'Олово'),
'#title' => 'Материал',
'#description' => 'Смотреть по каталогу',
'#bootstrap_size_this' => '3',
);
//второй контейнер. В нем три дочерних элемента, ширина колонок определяется автоматически.
$form['cont']['cont1'] = array(
'#type' => 'markup',
'#title' => '',
'#description' => 'Габаритные размеры изделия',
'#theme' => array('inline_fields_bootstrap'),
'#not_div' => FALSE,
'#bootstrap_prefix' => 'col-xs-',
'#bootstrap_size_this' => '6',
);
$form['cont']['cont1']['pole1'] = array(
'#type' => 'select',
'#title' => 'Ширина',
'#default_value' => 0,
'#options' => array(100, 200, 300, 450),
);
$form['cont']['cont1']['pole2'] = array(
'#type' => 'select',
'#title' => 'Высота',
'#default_value' => '0',
'#options' => array(10, 20, 30, 40),
);
$form['cont']['cont1']['pole3'] = array(
'#type' => 'textfield',
'#title' => 'Длина',
'#default_value' => '',
'#maxlength' => 5,
'#size' => 5,
);
//третий контейнер. Два дочерних элемента. Ширина определяется автоматически.
$form['cont']['cont2'] = array(
'#type' => 'markup',
'#theme' => array('inline_fields_bootstrap'),
'#not_div' => TRUE,
'#title' => 'Вес',
'#description' => 'Масса изделия',
'#bootstrap_prefix' => 'col-xs-',
'#bootstrap_size_this' => '3',
);
$form['cont']['cont2']['pole_value'] = array(
'#type' => 'textfield',
'#default_value' => '',
'#maxlength' => 5,
'#size' => 5,
);
$form['cont']['cont2']['pole_r'] = array(
'#type' => 'select',
'#default_value' => 'kg',
'#options' => array('g' => 'гр', 'kg' => 'кг'),
);
return $form;
}
Ну вот и все.
Готовый пример можно посмотреть на этой странице. Там представлена более сложная форма. Обратите внимание, как меняется положение элементов формы при изменении ширины окна браузера.
P.S. У элемента fieldset есть интересный параметр -'#title_display'. Допустимые значения - 'none', 'after', 'before'. Регулирует положение заголовка контейнера. У меня он дублировалося. Пришлось его отключать, указывая
'#title_display' => 'none',
- 28.07.2015
- 227 просмотров