Drupal + Omega + Bootstrap: быстрое создание полностью кастомных тем оформления без верстки (Часть 2. Bootstrap)

  • Tutorial
Первая часть, введение

В первой части статьи я рассказал о прекрасном фреймворке Omega для Drupal, который позволяет создавать собственные темы оформления, основанные на сетке (grid), произвольно настраивать и менять расположение и размеры регионов без каких-либо модификаций HTML-кода шаблонов. На этом можно было бы и остановиться, но существует прекрасный мощный CSS-фреймворк Bootstrap, имеющий собственную реализацию сетки, большое количество готовых CSS и JS компонентов, которые очень легко стилизовать, а также огромное сообщество, благодаря которому мы получаем наиболее качественный и «вылизанный» код по сравнению с конкурентами.

В этой части статьи я расскажу, как привязать Bootstrap к Omega. Но если вас по какой-либо причине не устраивает Bootstrap, то подобным образом можно прикрутить к Omega любой другой фреймворк на ваш вкус. Как и в первой части статьи, я не претендую на какую-то уникальность, просто описываю те вещи, которые можно почерпнуть из документации. Здесь будет много кода и мало картинок.

Сначала опять немного теории, чтобы получить представление о том, с чем нам предстоит работать. Итак, структура фреймворка Omega:

  1. Базовая тема Alpha, в которой заложен тот самый функционал, позволяющий задавать расположение зон и регионов через настройки темы, а также вводящий в наше распоряжение базовую сетку (grid) разных типов (Fixed и Fluid) и количества колонок (12, 16, 24).
  2. Базовая тема Omega, являющаяся субтемой базовой темы Alpha, в которой переопределены основные шаблоны Drupal для HTML5.
  3. Стартовые наборы (Starter kit), на основе которых нам предлагается создавать субтемы на базе Omega либо вручную, либо автоматически с использованием модуля Omega Tools.

Таким образом, для того, чтобы использовать Bootstrap совместно с Omega, необходимо сделать следующее:

  1. Создать базовую тему, являющуюся субтемой Omega, которая будет подключать Bootstrap и переопределять CSS-классы сетки Omega (grid-*) в Bootstrap (span*), а также добавлять необходимые CSS-классы для стандарных компонентов Drupal (например для кнопок, системных сообщений, «хлебных крошек», нумерации страниц и прочего).
  2. Создать стартовый набор для нашей базовой темы, чтобы быстро создавать субтемы с помощью Omega Tools.

Базовую тему будем создавать из стартового набора Omega HTML5 Startkit.

Подготовка базовой темы и стартового набора

  1. Копируем директорию omega/starterkits/omega-html5 рядом с директорией omega и переименовываем ее в omega_bootstrap.
  2. Переименовываем файлы starterkit_omega_html5.infoomega_bootstrap.info, css/global.csscss/omega-bootstrap.css и удаляем YOURTHEME-alpha-default-narrow.css, YOURTHEME-alpha-default-normal.css, YOURTHEME-alpha-default-wide.css, YOURTHEME-alpha-default.css.
  3. Скачиваем Bootsrtap и складываем файлы bootstrap.css и bootstrap-responsive.css в директорию css, а для файла bootstrap.js создаем директорию js. Использовать минифицированные версии нет необходимости, сжать CSS и JS мы сможем в дальнейшем стандартными средствами Drupal.

Далее начинаем редактировать файл настроек темы omega_bootstrap.info. Сначала меняем параметры name = Omega with Bootstrap и starterkit = FALSE.

Для удобства параметры в этом файле разделены на разделы.

В разделах ADDITIONAL REGIONS и ZONES можем добавить необходимые нам зоны или регионы.

В разделе OPTIONAL STYLESHEETS меняем все [global.css] на [omega-bootstrap.css] и задаем в параметре name что-то вроде Omega Bootstrap custom styles. Сюда мы также можем добавить дополнительные CSS (например, подключить FontAwesome), которые сможем потом включать-выключать в настройках темы в разделе Toggle styles (включение/отключение стилей).

Ниже раздела OPTIONAL STYLESHEETS создаем разделы OPTIONAL LIBRARIES и CSS GRID SYSTEMS:

; OPTIONAL LIBRARIES

libraries[bootstrap][name] = 'Bootstrap'
libraries[bootstrap][description] = 'Sleek, intuitive, and powerful front-end framework for faster and easier web development.'
libraries[bootstrap][css][0][file] = bootstrap.css
libraries[bootstrap][css][0][options][weight] = 1
libraries[bootstrap][css][1][file] = bootstrap-responsive.css
libraries[bootstrap][css][1][options][weight] = 2
libraries[bootstrap][js][0][file] = bootstrap.js
libraries[bootstrap][js][0][options][weight] = -1

; CSS GRID SYSTEMS

grids[bootstrap][name] = Bootstrap
grids[bootstrap][layouts][normal] = Normal
grids[bootstrap][columns][12] = 12 Columns

Формат описания этих разделов мы взяли из alpha.info и omega.info.

Стартовый набор создаем также из Omega HTML5 Startkit:

  1. Копируем директорию omega/starterkits/omega-html5 рядом с omega_bootstrap, переименовываем в omega-html5-bootstrap.
  2. Переименовываем starterkit_omega_html5.info в starterkit_omega_html5_bootstrap.info, удаляем YOURTHEME-alpha-default-narrow.css, YOURTHEME-alpha-default-normal.css, YOURTHEME-alpha-default-wide.css, YOURTHEME-alpha-default.css.
  3. В файле starterkit_omega_html5_bootstrap.info меняем параметры name = Omega HTML5 Starterkit with Bootstrap и base theme = omega_bootstrap.

Наши базовая тема и стартовый набор готовы к использованию. Но это еще не конец, а скорее только начало.

Создание субтемы

Для более наглядного представления процесса, который будет происходить дальше, создадим новую тему способом, описанным в первой части статьи, с помощью Omega Tools, только в Base theme (базовая тема) выбираем Omega with Bootstrap, а в Starterkit (стартовый набор) — наш Omega HTML5 Starterkit with Bootstrap (рис. 1).

1. image 2. image 3. image 4. image 5. image

Устанавливаем нашу тему по умолчанию и переходим в настройки.

  1. На вкладке Grid settings (настройка сетки) в Grid system (тип сетки) появился новый тип Bootstrap, его и выбираем (рис. 2).
  2. На вкладке Zone and region configuration (конфигурация зон и регионов) добавляем классы Bootstrap к зонам и регионам. В разделе Configuration зоны в поле Additional zone classes задаем значение row, а в поле Additional wrapper classes — значение container. В настройках регионов в поле Additional region classes задаем нужный класс span* по необходимому нам количеству колонок. Omega позволяет задавать произвольные классы зонам и регионам, чем мы и воспользовались сейчас, но в дальнейшем мы автоматизируем этот процесс (рис. 3).
  3. На вкладке Toggle libraries (включение/отключение библиотек) отключаем все стандартные библиотеки Omega и включаем нашу Bootstrap (рис. 4).
  4. На вкладке Toggle styles (включение/отключение стилей) также отключаем все стили в разделе Enable optional stylesheets (включить дополнительные стили), кроме Omega Bootstrap custom styles (all) — omega-bootstrap.css и Your custom global styles (all) — global.css (рис. 5).

Все остальные настройки задаем в соответствии с рекомендациями из первой части статьи и сохраняем их. Затем мы можем нажать кнопку Export theme settings, скопировать настройки и вставить их в файл omega-html5-bootstrap/starterkit_omega_html5_bootstrap.info, заменив ими настройки в разделе THEME SETTINGS (DEFAULTS). В этом случае все новые темы из нашего стартового набора сразу будут настроены нужным нам образом.

Темизация

Bootstrap для стилизации элементов использует классы, которые отличаются от стандартных классов Drupal. Поэтому необходимо добавить классы Bootsrtap в вывод стандартных элементов Drupal. Для этого будем использовать стандартные возможности темизации Drupal, а именно переопределим нужные нам theme_-функции. Подробнее о возможностях темизации Drupal можно узнать из раздела документации Using the theme layer (http://drupal.org/node/933976).

Функции темизации будем переопределять в файле template.php в корне нашей базовой темы omega_bootstrap, в этом случае они будут наследоваться всеми нашими субтемами.

Для начала избавимся от необходимости вручную добавлять классы container и row зонам, а также классы span* регионам. Для этого добавим в template.php функцию omega_bootstrap_process():

omega_bootstrap_process()
/**
 * Implements hook_process().
 */
function omega_bootstrap_process(&$vars, $hook) {
  if (!empty($vars['elements']['#grid']) || !empty($vars['elements']['#data']['wrapper_css'])) {
    if (!empty($vars['elements']['#grid'])) {
      foreach (array('prefix', 'suffix', 'push', 'pull') as $quality) {
        if (!empty($vars['elements']['#grid'][$quality])) {
          array_unshift($vars['attributes_array']['class'], 'offset' . $vars['elements']['#grid'][$quality]); # Добавляем класс offset* региону
        }
      }

      array_unshift($vars['attributes_array']['class'], 'span' . $vars['elements']['#grid']['columns']); # Добавляем класс span* региону
    }
  
    $vars['attributes'] = $vars['attributes_array'] ? drupal_attributes($vars['attributes_array']) : '';
  }

  if (!empty($vars['elements']['#grid_container']) || !empty($vars['elements']['#data']['css'])) {

    if (!empty($vars['elements']['#grid_container'])) {
      $vars['content_attributes_array']['class'][] = 'container'; # Добавляем класс container зоне
    }

    $vars['content_attributes'] = $vars['content_attributes_array'] ? drupal_attributes($vars['content_attributes_array']) : '';
  }

  alpha_invoke('process', $hook, $vars);
}

Код мы позаимствовали из функции alpha_process(), которую можно найти в файле omega/alpha/template.php. Как видите, еще нужно добавить row, для этого скопируем файлы шаблонов из omega/alpha/templates/zone.tpl.php и omega/omega/templates/zone--content.tpl.php в директорию omega_bootstrap/templates и отредактируем следующим образом.

Файл zone.tpl.php
<?php 
/**
 * @file
 * Alpha's theme implementation to display a zone.
 */
?>
<?php if ($wrapper): ?><div<?php print $attributes; ?>><?php endif; ?>  
  <div<?php print $content_attributes; ?>><div class="row">
    <?php print $content; ?>
  </div></div>
<?php if ($wrapper): ?></div><?php endif; ?>

Файл zone--content.tpl.php
<?php if ($wrapper): ?><div<?php print $attributes; ?>><?php endif; ?>
  <div<?php print $content_attributes; ?>><div class="row">
    <?php if ($breadcrumb): ?>
      <div id="breadcrumb" class="grid-<?php print $columns; ?>"><?php print $breadcrumb; ?></div>
    <?php endif; ?>    
    <?php if ($messages): ?>
      <div id="messages" class="grid-<?php print $columns; ?>"><?php print $messages; ?></div>
    <?php endif; ?>
    <?php print $content; ?>
  </div></div>
<?php if ($wrapper): ?></div><?php endif; ?>

Теперь можно убрать ненужные классы из настроек темы и задавать количество колонок в регионе обычным способом.

Теперь приступим к украшательствам. Код берем из соответствующих функций, немного модифицируем его под наши нужды и добавляем классы Bootstrap.

«Хлебные крошки»
Так как для вывода системных элементов мы используем модуль Delta Blocks, то переопределяем его функцию темизации.

/**
 * Implements theme_delta_blocks_breadcrumb().
 */
function omega_bootstrap_delta_blocks_breadcrumb($variables) {
  $output = '';
   
  if (!empty($variables['breadcrumb'])) {  
    if ($variables['breadcrumb_current']) {
      $variables['breadcrumb'][] = l(drupal_get_title(), current_path(), array('html' => TRUE));
    }
  
    $output = '<div id="breadcrumb" class="clearfix"><ul class="breadcrumb">';
    $switch = array('odd' => 'even', 'even' => 'odd');
    $zebra = 'even';
    $last = count($variables['breadcrumb']) - 1;    
    
    foreach ($variables['breadcrumb'] as $key => $item) {
      $zebra = $switch[$zebra];
      $attributes['class'] = array('depth-' . ($key + 1), $zebra);
      
      if ($key == 0) {
        $attributes['class'][] = 'first';
      }
      
      if ($key == $last) {
        $attributes['class'][] = 'last';
      }
      else {
        $item .= '<span class="divider">/</span>';
      }

      $output .= '<li' . drupal_attributes($attributes) . '>' . $item . '</li>';
    }
      
    $output .= '</ul></div>';
  }
  
  return $output;
}

Системные сообщения
Классы messages меняем на alert.

/**
 * Implements theme_status_messages().
 */
function omega_bootstrap_status_messages($variables) {
  $display = $variables['display'];
  $output = '';

  $status_heading = array(
    'status' => t('Status message'), 
    'error' => t('Error message'), 
    'warning' => t('Warning message'),
  );
  
  $class = array(
    'status' => 'alert alert-success', 
    'error' => 'alert alert-error', 
    'warning' => 'alert',
  );

  foreach (drupal_get_messages($display) as $type => $messages) {
    $output .= "<div class=\"{$class[$type]}\">\n";
    if (!empty($status_heading[$type])) {
      $output .= '<h2 class="element-invisible">' . $status_heading[$type] . "</h2>\n";
    }
    if (count($messages) > 1) {
      $output .= " <ul>\n";
      foreach ($messages as $message) {
        $output .= '  <li>' . $message . "</li>\n";
      }
      $output .= " </ul>\n";
    }
    else {
      $output .= $messages[0];
    }
    $output .= "</div>\n";
  }
  return $output;
}

Кнопки-владки
Мне больше нравятся nav-pills, можно заменить на nav-tabs.

/**
 * Implements theme_menu_local_tasks().
 */
function omega_bootstrap_menu_local_tasks(&$variables) {
  $output = '';

  if (!empty($variables['primary'])) {
    $variables['primary']['#prefix'] = '<h2 class="element-invisible">' . t('Primary tabs') . '</h2>';
    $variables['primary']['#prefix'] .= '<ul class="nav nav-pills">';
    $variables['primary']['#suffix'] = '</ul>';
    $output .= drupal_render($variables['primary']);
  }
  if (!empty($variables['secondary'])) {
    $variables['secondary']['#prefix'] = '<h2 class="element-invisible">' . t('Secondary tabs') . '</h2>';
    $variables['secondary']['#prefix'] .= '<ul class="nav nav-pills">';
    $variables['secondary']['#suffix'] = '</ul>';
    $output .= drupal_render($variables['secondary']);
  }

  return $output;
}

Кнопки форм
Добавляем класс btn.

/**
 * Implements theme_button().
 */
function omega_bootstrap_button($variables) {
  $element = $variables['element'];
  $element['#attributes']['type'] = 'submit';
  element_set_attributes($element, array('id', 'name', 'value'));

  $element['#attributes']['class'][] = 'btn';
  
  switch($element['#id']) { # Разукрашиваем основные кнопки
    case strpos($element['#id'], 'edit-submit') === 0: $element['#attributes']['class'][] = 'btn-primary'; break;
    case 'edit-preview': $element['#attributes']['class'][] = 'btn-warning'; break;
    case 'edit-delete': $element['#attributes']['class'][] = 'btn-danger'; break;
  }

  $element['#attributes']['class'][] = 'form-' . $element['#button_type'];
  if (!empty($element['#attributes']['disabled'])) {
    $element['#attributes']['class'][] = 'form-button-disabled btn-disabled';
  }

  return ' <input' . drupal_attributes($element['#attributes']) . ' /> ';
}

Нумерация страниц
Класс pagination.

/**
 * Implements theme_pager().
 */
function omega_bootstrap_pager($variables) {
  $tags = $variables['tags'];
  $element = $variables['element'];
  $parameters = $variables['parameters'];
  $quantity = $variables['quantity'];
  global $pager_page_array, $pager_total;

  // Calculate various markers within this pager piece:
  // Middle is used to "center" pages around the current page.
  $pager_middle = ceil($quantity / 2);
  // current is the page we are currently paged to
  $pager_current = $pager_page_array[$element] + 1;
  // first is the first page listed by this pager piece (re quantity)
  $pager_first = $pager_current - $pager_middle + 1;
  // last is the last page listed by this pager piece (re quantity)
  $pager_last = $pager_current + $quantity - $pager_middle;
  // max is the maximum page number
  $pager_max = $pager_total[$element];
  // End of marker calculations.

  // Prepare for generation loop.
  $i = $pager_first;
  if ($pager_last > $pager_max) {
    // Adjust "center" if at end of query.
    $i = $i + ($pager_max - $pager_last);
    $pager_last = $pager_max;
  }
  if ($i <= 0) {
    // Adjust "center" if at start of query.
    $pager_last = $pager_last + (1 - $i);
    $i = 1;
  }
  // End of generation loop preparation.

  $li_first = theme('pager_first', array('text' => (isset($tags[0]) ? $tags[0] : t('« first')), 'element' => $element, 'parameters' => $parameters));
  $li_previous = theme('pager_previous', array('text' => (isset($tags[1]) ? $tags[1] : t('‹ previous')), 'element' => $element, 'interval' => 1, 'parameters' => $parameters));
  $li_next = theme('pager_next', array('text' => (isset($tags[3]) ? $tags[3] : t('next ›')), 'element' => $element, 'interval' => 1, 'parameters' => $parameters));
  $li_last = theme('pager_last', array('text' => (isset($tags[4]) ? $tags[4] : t('last »')), 'element' => $element, 'parameters' => $parameters));

  if ($pager_total[$element] > 1) {
    if ($li_first) {
      $items[] = array(
        'data' => $li_first,
      );
    }
    if ($li_previous) {
      $items[] = array(
        'data' => $li_previous,
      );
    }

    // When there is more than one page, create the pager list.
    if ($i != $pager_max) {
      if ($i > 1) {
        $items[] = array(
          'data' => '<span>…</span>',
        );
      }
      // Now generate the actual pager piece.
      for (; $i <= $pager_last && $i <= $pager_max; $i++) {
        if ($i < $pager_current) {
          $items[] = array(
            'data' => theme('pager_previous', array('text' => $i, 'element' => $element, 'interval' => ($pager_current - $i), 'parameters' => $parameters)),
          );
        }
        if ($i == $pager_current) {
          $items[] = array(
            'class' => array('active'), 
            'data' => "<span>$i</span>",
          );
        }
        if ($i > $pager_current) {
          $items[] = array(
            'data' => theme('pager_next', array('text' => $i, 'element' => $element, 'interval' => ($i - $pager_current), 'parameters' => $parameters)),
          );
        }
      }
      if ($i < $pager_max) {
        $items[] = array(
          'data' => '<span>…</span>',
        );
      }
    }
    // End generation.
    if ($li_next) {
      $items[] = array(
        'data' => $li_next,
      );
    }
    if ($li_last) {
      $items[] = array(
        'data' => $li_last,
      );
    }
    return '<h2 class="element-invisible">' . t('Pages') . '</h2><div class="pagination pagination-centered">' . theme('item_list', array(
      'items' => $items, 
    )) . '</div>';
  }
}

И так далее по такому же принципу. Если нужно в стандартный вывод Drupal добавить классы Bootstrap — просто переопределяем функцию темизации (или шаблон), все это делается стандартными средствами Drupal. Какие-то дополнительные функции можете позаимствовать из Drupal-темы Bootstrap. Также можно дополнить эти функции дополнительными параметрами, которые можно будет менять в настройках темы. Примеры настроек: символ-разделитель в «хлебных крошках», nav-tabs или nav-pills, размер и расположение нумератора страниц (pagination-large / pagination-small / pagination-mini и pagination-centered / pagination-right). Подробнее об этом можно почитать в документации Creating advanced theme settings (http://drupal.org/node/177868).

Использование

Ну а теперь перейдем к практической части и посмотрим, как всем этим можно пользоваться. Для начала я бы рекомендовал настроить вспомогательную сетку-оверлей под ширину колонок Bootstrap. Для этого нужно отыскать PNG от базовой темы Alpha, модифицировать в их в графическом редакторе и переопределить класс alpha-grid-debug в нашем omega-bootstrap.css.

Обратите внимание, что для минимальная версия jQuery для работы JS-компонентов Bootstrap — 1.7, поэтому необходимо подключить ее (или более свежую) при помощи модуля jQuery Update.

С помощью модуля Block Class (который упоминался в первой части статьи) очень удобно добавлять необходимые классы блокам, например стандартный well (см. рис. 6).

В настройках отображений модуля Views есть стандартная возможность задавать произвольные классы практически всем компонентам, что открывает очень широкие возможности для использования Bootstrap.

Пример 1: вывод материалов сеткой. Для этого достаточно добавить лишь добавить класс row всему представлению Other — CSS class, а в настройках класса строки форма вывода Format — Unformatted list — Settings — Row class задать класс с нужным количеством колонок, например span2.

Пример 2: вывод новостей по помощью Bootstrap-компонента Media object. Для этого добавляем в Format — Unformatted list — Settings — Row class класс media, в параметрах поля с изображением Style settings — Customize field and label wrapper HTML — Create a CSS class добавить класс pull-left, и в таких же параметрах поля с текстом добавить класс media-body. Другие поля можно добавить в это же поле через Rewrite results — Rewrite the output of this field, не забыв при этом сами эти поля отключить для вывода (Exclude from display).

Также с помощью модуля Views Bootstrap (спасибо mrded) для оформления Views можно использовать такие компоненты Bootstrap как Thumbnails и Carousel.

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

Рисунок 6. Готовая тема с включенными отладочными блоками.



Спасибо за внимание! Надеюсь, статья окажется полезной и расширит границы вашего использования Drupal.
Поделиться публикацией

Комментарии 17

    0
    Благодарю, хороший материал! То, что нужно и как раз вовремя! Пожалуй, сэкономлю 20 тысяч и натяну дизайн на друпал сам.
      0
      Очень хороший подход. Только нужно подготовить дизайнера и заказчика к тому, что будет использорваться bootstrap, который накладывает некоторые ограничения на дизайн.
        0
        Только нужно подготовить дизайнера и заказчика к тому, что будет использорваться bootstrap, который накладывает некоторые ограничения на дизайн.
        Например, какие?
          0
          Например при использовании grid, элементы должны быть расположены по правилам грида, а не «там где захотелось». Та к же, как пример, могу привести то, что дизайнер должен знать об унификации отступов и расстояний (margin, padding) у всех элементов. В противном же случае простая и быстрая верстка превратится в сложную и мучительную.
          Из личного опыта.
            0
            Например при использовании grid, элементы должны быть расположены по правилам грида, а не «там где захотелось». Та к же, как пример, могу привести то, что дизайнер должен знать об унификации отступов и расстояний (margin, padding)

            Есть подозрение, что через какое-то время без всего этого любая верстка превратится в сложную и мучительную.
              0
              Я полностью согласен. Но в различных проектах часто упускается этот момент, и тогда страдают все. Вот и решил напомнить. А вслучае с использованием bootsrap потери времени, при невыполнении вышеописанного условия просто колосальные.
              0
              Для дизайнеров есть Twitter bootstrap grid template. Нормальные дизайнеры всегда работают с сеткой
                +1
                | Нормальные дизайнеры всегда работают с сеткой
                Глупости какие...!
            0
            спасибо, интересный пост
              0
              И чем это легче, чем обычный путь создания темы?
                0
                Для меня, лично, ничем. Я делаю свои темы с тем же Twitter bootstrap. Самое простое решение — тема Bootstrap и ничего лишнего. если нужны регионы, можно поставить свои.

                Я, честно говоря, не вижу смысла в модуле Block Class, к чему нагружать систему лишним модулем, если можно переопределить вывод конкретного блока или оттемизировать шаблон вывода блока.

                По поводу
                Обратите внимание, что для использования JS-компонентов Bootstrap необходимо подключить jQuery 1.7.x с помощью модуля jQuery Update.

                Стоит уточнить, что минимальная версия jQuery для работы с Twitter bootstrap — 1.7, я включаю 1.8, сайт Bootstrap использует версию 1.9
                  0
                  Для меня, лично, ничем. Я делаю свои темы с тем же Twitter bootstrap. Самое простое решение — тема Bootstrap и ничего лишнего. если нужны регионы, можно поставить свои.

                  Ну а кто мешает, пожалуйста. Появился способ автоматизировать часть рутины — я просто рассказал о нем. Я тоже создавал вручную поля в нодах, пока не появился CKK, делал функции вывода страниц и блоков до Views, расставлял регионы руками, пока не появилась Omega. Одним готовые решения облегчают жизнь, другие выбирают собственные велосипеды.

                  Я, честно говоря, не вижу смысла в модуле Block Class, к чему нагружать систему лишним модулем, если можно переопределить вывод конкретного блока или оттемизировать шаблон вывода блока.

                  Ну например если у вас пара десятков типовых блоков часть из которых нужно загнать в well, а часть нет. Для каждого создавать отдельный шаблон, просто чтобы добавить класс? Или городить в CSS конструкции вида #block-block-1, #block-block-2, #block-block-3, ..., #block-block-N { ... }? Переопределить template_preprocess_block? Ну так пожалуйста, никто не запрещает. Block Class последний вариант и использует, какая разница будет это в теме или в отдельном модуле?

                  Когда возникла необходимость (в связи с переходом на Bootstrap) добавлять классы блокам, я тоже недолго думая добавил их в препроцесс. Потом задумался об автоматизации и написании простенького модуля. Потом поискал готовое решение, и нашел его в виде уже готового простенького модуля Block Class, который меня полностью устраивает. Ну а теперь делюсь этим с остальными.

                  Стоит уточнить, что минимальная версия jQuery для работы с Twitter bootstrap — 1.7, я включаю 1.8, сайт Bootstrap использует версию 1.9

                  Спасибо, я и имел в виду минимальную версию, внес уточнение в пост.
                    0
                    >Я тоже создавал вручную поля в нодах, пока не появился CKK

                    Комментарий хороший, так что не в упрёк вам, а просто для информирования публики:

                    Модуль Content Construction Kit (CCK) сейчас называется Fields и является частью ядра (начиная с 7 версии).

                    drupal.org/project/cck

                    Для использующих Drupal это стало приятной неожиданностью примерно 5 (пять) лет назад.

                    groups.drupal.org/fields-core

                    Ваш капитан очевидность

                    P.S.
                    А статья — да, тоже интересная, есть над чем поразмыслить.
                0
                Не совсем понял, зачем это. Омега и bootsrap это два совершенно разных фреймворка, со своими сетками. В чем смысл их совместного использования. На drupal.org есть уже несколько тем на базе bootstrap. Чем они не подходят?
                  0
                  Кажется, я рассказал об этом в первом абзаце.

                  Расскажу еще раз, может быть более популярно. Лично мне сетка в Bootstrap нравится больше, а качество кода и компонентов у Bootstrap намного выше. Но у Omega есть отличный функционал, который позволяет менять расположение регионов просто в настройках темы, не прибегая к правке кода page.tpl.php, чего в других темах нет. Скрестить этот функционал Omega с возможностями Bootstrap и есть цель моей статьи.
                  0
                  Подскажите, а в zone--content.tpl.php не нужно ли заменить
                  class="grid-<?php print $columns; ?>"
                  на
                  class="span<?php print $columns; ?>"?
                    0
                    В шаблоне zone--content.tpl.php эти классы используются при выводе системных «хлебных крошек» и сообщений:

                        <?php if ($breadcrumb): ?>
                          <div id="breadcrumb" class="grid-<?php print $columns; ?>"><?php print $breadcrumb; ?></div>
                        <?php endif; ?>    
                        <?php if ($messages): ?>
                          <div id="messages" class="grid-<?php print $columns; ?>"><?php print $messages; ?></div>
                        <?php endif; ?>
                    

                    Т. к. мы отключили вывод этих системных компонентов при настройке темы в первой части статьи в разделе 6. Toggle advanced elements (включение/отключение дополнительных элементов), то приведенная выше часть кода ни на что не влияет, ее можно просто удалить.

                    Ну а если не планируете переопределять вывод этих компонентов с помощью Delta Blocks, то тогда да, необходимо будет заменить.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое