Drupal + Omega + Bootstrap: fast creation of completely custom themes without layout (Part 2. Bootstrap)
- Tutorial
First part, introduction
In the first part of the article, I talked about the excellent Omega framework for Drupal, which allows you to create your own custom themes based on the grid, arbitrarily configure and change the location and size of regions without any modifications to the HTML code of the templates. We could stop here, but there is a wonderful powerful Bootstrap CSS framework with its own implementation of the grid, a large number of ready-made CSS and JS components that are very easy to style, and also a huge community, thanks to which we get the highest quality and “licked” code compared to competitors.
In this part of the article, I’ll show you how to bind Bootstrap to Omega. But if for some reason Bootstrap does not suit you, then in this way you can tie any other framework of your choice to Omega. As in the first part of the article, I do not pretend to be any uniqueness, I just describe those things that can be learned from the documentation. There will be a lot of code and few pictures.
First, again, a little theory to get an idea of what we have to work with. So, the structure of the Omega framework:
Thus, in order to use Bootstrap with Omega, you need to do the following:
We will create the basic theme from the Omega HTML5 Startkit.
Next, we start editing the theme settings file
For convenience, the parameters in this file are divided into sections.
In the sections
In the section,
Below the section
We took the format for the description of these sections from
We also create the starter kit from Omega HTML5 Startkit:
Our basic theme and starter kit are ready to use. But this is not the end, but rather only the beginning.
For a more visual representation of the process that will happen next, we will create a new theme in the manner described in the first part of the article using Omega Tools, only in the Base theme (base theme) we select Omega with Bootstrap , and in Starterkit (starter set) our Omega HTML5 Starterkit with Bootstrap (Figure 1).
1. 2. 3. 4. 5. Install our theme by default and go to the settings.
We set all other settings in accordance with the recommendations from the first part of the article and save them. Then we can click the Export theme settings button , copy the settings and paste them into the file
Bootstrap uses classes to style elements that are different from the standard Drupal classes. Therefore, you must add the Bootsrtap classes to the output of the standard Drupal elements. To do this, we will use the standard features of Drupal's theming, namely, we will redefine the necessary
We will redefine the theming functions in the file
To get started, get rid of the need to manually add classes
We borrowed the code from a function
Now you can remove unnecessary classes from the theme settings and set the number of columns in the region in the usual way.
Now we proceed to the decorations. We take the code from the corresponding functions, slightly modify it to our needs and add the Bootstrap classes.
And so on according to the same principle. If you need to add Bootstrap classes to the standard Drupal output - just redefine the theming function (or template), all this is done using standard Drupal tools. You can borrow some additional features from the Bootstrap Drupal theme . You can also supplement these functions with additional parameters that can be changed in the theme settings. Examples of settings: the separator character in bread crumbs,
Well, now let's move on to the practical part and see how all this can be used. For starters, I would recommend setting up an auxiliary overlay grid to fit the width of the Bootstrap columns. To do this, find PNG from the Alpha base theme, modify them in a graphical editor and redefine the class
Please note that for the minimum version of jQuery for the Bootstrap JS components to work - 1.7, so you need to connect it (or more recent) using the jQuery Update module .
Using the Block Class module (which was mentioned in the first part of the article), it is very convenient to add the necessary classes to blocks, for example, the standard one
In the display settings of the Views module, there is a standard ability to set arbitrary classes to almost all components, which opens up very wide possibilities for using Bootstrap.
Example 1: mesh output. To do this, just add the class to the
Example 2: displaying news using the Bootstrap component of a Media object . To do this, add to the Format - Unformatted list - Settings - Row class class
Also, using the Views Bootstrap module (thanks to mrded ), Bootstrap components such as Thumbnails and Carousel can be used to style Views .
And finally, a small demonstration of some of the capabilities of the resulting topic blank.
Figure 6. Ready theme with debugging blocks enabled.
Thanks for attention! I hope this article is helpful and extends the scope of your use of Drupal.
In the first part of the article, I talked about the excellent Omega framework for Drupal, which allows you to create your own custom themes based on the grid, arbitrarily configure and change the location and size of regions without any modifications to the HTML code of the templates. We could stop here, but there is a wonderful powerful Bootstrap CSS framework with its own implementation of the grid, a large number of ready-made CSS and JS components that are very easy to style, and also a huge community, thanks to which we get the highest quality and “licked” code compared to competitors.
In this part of the article, I’ll show you how to bind Bootstrap to Omega. But if for some reason Bootstrap does not suit you, then in this way you can tie any other framework of your choice to Omega. As in the first part of the article, I do not pretend to be any uniqueness, I just describe those things that can be learned from the documentation. There will be a lot of code and few pictures.
First, again, a little theory to get an idea of what we have to work with. So, the structure of the Omega framework:
- The basic Alpha theme, which contains the very functionality that allows you to set the location of zones and regions through the theme settings, as well as introducing at our disposal a basic grid of various types (Fixed and Fluid) and the number of columns (12, 16, 24).
- The Omega Core Theme, a sub-theme of the Alpha Core Theme, in which the core Drupal HTML5 templates are redefined.
- Starter kit, on the basis of which we are invited to create sub-themes based on Omega either manually or automatically using the Omega Tools module.
Thus, in order to use Bootstrap with Omega, you need to do the following:
- Create a basic theme, which is an Omega sub-theme, that will connect Bootstrap and redefine the CSS classes of the Omega grid (grid- *) in Bootstrap (span *), as well as add the necessary CSS classes for standard Drupal components (for example, buttons, system messages, "Breadcrumbs", pagination, etc.).
- Create a starter kit for our basic theme to quickly create sub-themes using Omega Tools.
We will create the basic theme from the Omega HTML5 Startkit.
Preparation of the basic theme and starter kit
- Copy the directory
omega/starterkits/omega-html5
next to the directoryomega
and rename it toomega_bootstrap
. - Rename the files
starterkit_omega_html5.info
→omega_bootstrap.info
,css/global.css
→css/omega-bootstrap.css
and deleteYOURTHEME-alpha-default-narrow.css, YOURTHEME-alpha-default-normal.css, YOURTHEME-alpha-default-wide.css, YOURTHEME-alpha-default.css
. - Download the Bootsrtap and dump files
bootstrap.css
andbootstrap-responsive.css
the directorycss
and the filebootstrap.js
create a directoryjs
. There is no need to use minified versions, we will be able to compress CSS and JS in the future using standard Drupal tools.
Next, we start editing the theme settings file
omega_bootstrap.info
. First, change the parameters name = Omega with Bootstrap
and starterkit = FALSE
. For convenience, the parameters in this file are divided into sections.
In the sections
ADDITIONAL REGIONS
and ZONES
we can add the zones or regions we need. In the section,
OPTIONAL STYLESHEETS
we change everything [global.css]
to [omega-bootstrap.css]
and set name
something like this in the parameter Omega Bootstrap custom styles
. Here we can also add additional CSS (for example, enable FontAwesome), which we can then turn on / off in the theme settings in the Toggle styles section (enable / disable styles). Below the section
OPTIONAL STYLESHEETS
we create sections OPTIONAL LIBRARIES
and 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
We took the format for the description of these sections from
alpha.info
and omega.info
. We also create the starter kit from Omega HTML5 Startkit:
- Copy the directory
omega/starterkits/omega-html5
next toomega_bootstrap
, rename toomega-html5-bootstrap
. - Rename
starterkit_omega_html5.info
tostarterkit_omega_html5_bootstrap.info
, deleteYOURTHEME-alpha-default-narrow.css, YOURTHEME-alpha-default-normal.css, YOURTHEME-alpha-default-wide.css, YOURTHEME-alpha-default.css
. - In the file
starterkit_omega_html5_bootstrap.info
we change the parametersname = Omega HTML5 Starterkit with Bootstrap
andbase theme = omega_bootstrap
.
Our basic theme and starter kit are ready to use. But this is not the end, but rather only the beginning.
Sub Subject Creation
For a more visual representation of the process that will happen next, we will create a new theme in the manner described in the first part of the article using Omega Tools, only in the Base theme (base theme) we select Omega with Bootstrap , and in Starterkit (starter set) our Omega HTML5 Starterkit with Bootstrap (Figure 1).
1. 2. 3. 4. 5. Install our theme by default and go to the settings.
- On the Grid settings tab in the Grid system (grid type), a new Bootstrap type has appeared , and select it (Fig. 2).
- On the Zone and region configuration tab, add Bootstrap classes to zones and regions. In the Zone configuration section, in the Additional zone classes field, set the value
row
, and in the Additional wrapper classes field - valuecontainer
. In the region settings, in the Additional region classes field, set the desired classspan*
for the required number of columns. Omega allows you to set arbitrary classes for zones and regions, which we have used now, but in the future we will automate this process (Fig. 3). - On the Toggle libraries tab (enable / disable libraries), turn off all standard Omega libraries and enable our Bootstrap (Fig. 4).
- On the Toggle styles tab (enable / disable styles), also disable all styles in the Enable optional stylesheets section , except for Omega Bootstrap custom styles (all) - omega-bootstrap.css and Your custom global styles (all) - global. css (fig. 5).
We set all other settings in accordance with the recommendations from the first part of the article and save them. Then we can click the Export theme settings button , copy the settings and paste them into the file
omega-html5-bootstrap/starterkit_omega_html5_bootstrap.info
, replacing them with the settings in the section THEME SETTINGS (DEFAULTS)
. In this case, all new themes from our starter kit will be immediately configured in the way we need.Theming
Bootstrap uses classes to style elements that are different from the standard Drupal classes. Therefore, you must add the Bootsrtap classes to the output of the standard Drupal elements. To do this, we will use the standard features of Drupal's theming, namely, we will redefine the necessary
theme_
functions for us . You can learn more about the possibilities of Drupal theming from the documentation section Using the theme layer ( http://drupal.org/node/933976 ). We will redefine the theming functions in the file
template.php
at the root of our base topic omega_bootstrap
, in which case they will be inherited by all of our subtopics. To get started, get rid of the need to manually add classes
container
and row
zones, as well as classesspan*
regions. To do this, add to the template.php
function omega_bootstrap_process()
:omega_bootstrap_process ()
/**
* Implements hook_process().
*/functionomega_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);
}
We borrowed the code from a function
alpha_process()
that can be found in the file omega/alpha/template.php
. As you see, you still need to add row
, for this we copy the template files from omega/alpha/templates/zone.tpl.php
and omega/omega/templates/zone--content.tpl.php
to the directory omega_bootstrap/templates
and edit it as follows.Zone.tpl.php file
<?php/**
* @file
* Alpha's theme implementation to display a zone.
*/?><?phpif ($wrapper): ?><div<?phpprint $attributes; ?>><?phpendif; ?>
<div<?phpprint $content_attributes; ?>><div class="row">
<?phpprint $content; ?>
</div></div>
<?phpif ($wrapper): ?></div><?phpendif; ?>
Zone file - content.tpl.php
<?phpif ($wrapper): ?><div<?phpprint $attributes; ?>><?phpendif; ?>
<div<?phpprint $content_attributes; ?>><div class="row">
<?phpif ($breadcrumb): ?>
<divid="breadcrumb" class="grid-<?phpprint $columns; ?>"><?phpprint $breadcrumb; ?></div>
<?phpendif; ?>
<?phpif ($messages): ?>
<divid="messages" class="grid-<?phpprint $columns; ?>"><?phpprint $messages; ?></div>
<?phpendif; ?>
<?phpprint $content; ?>
</div></div>
<?phpif ($wrapper): ?></div><?phpendif; ?>
Now you can remove unnecessary classes from the theme settings and set the number of columns in the region in the usual way.
Now we proceed to the decorations. We take the code from the corresponding functions, slightly modify it to our needs and add the Bootstrap classes.
"Breadcrumbs"
Так как для вывода системных элементов мы используем модуль Delta Blocks, то переопределяем его функцию темизации.
/**
* Implements theme_delta_blocks_breadcrumb().
*/functionomega_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;
}
System messages
Классы
messages
меняем на alert
./**
* Implements theme_status_messages().
*/functionomega_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;
}
Button Buttons
Мне больше нравятся
nav-pills
, можно заменить на nav-tabs
./**
* Implements theme_menu_local_tasks().
*/functionomega_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;
}
Form Buttons
Добавляем класс
btn
./**
* Implements theme_button().
*/functionomega_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
Класс
pagination
./**
* Implements theme_pager().
*/functionomega_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>';
}
}
And so on according to the same principle. If you need to add Bootstrap classes to the standard Drupal output - just redefine the theming function (or template), all this is done using standard Drupal tools. You can borrow some additional features from the Bootstrap Drupal theme . You can also supplement these functions with additional parameters that can be changed in the theme settings. Examples of settings: the separator character in bread crumbs,
nav-tabs
or nav-pills
, the size and location of the page numbering ( pagination-large
/ pagination-small
/ pagination-mini
and pagination-centered
/ pagination-right
). You can read more about this in the documentation Creating advanced theme settings ( http://drupal.org/node/177868 ).Using
Well, now let's move on to the practical part and see how all this can be used. For starters, I would recommend setting up an auxiliary overlay grid to fit the width of the Bootstrap columns. To do this, find PNG from the Alpha base theme, modify them in a graphical editor and redefine the class
alpha-grid-debug
in ours omega-bootstrap.css
. Please note that for the minimum version of jQuery for the Bootstrap JS components to work - 1.7, so you need to connect it (or more recent) using the jQuery Update module .
Using the Block Class module (which was mentioned in the first part of the article), it is very convenient to add the necessary classes to blocks, for example, the standard one
well
(see Fig. 6).In the display settings of the Views module, there is a standard ability to set arbitrary classes to almost all components, which opens up very wide possibilities for using Bootstrap.
Example 1: mesh output. To do this, just add the class to the
row
entire Other - CSS class view , and in the line class settings, the Format - Unformatted list - Settings - Row class output form set the class with the desired number of columns, for example span2
. Example 2: displaying news using the Bootstrap component of a Media object . To do this, add to the Format - Unformatted list - Settings - Row class class
media
, in the parameters of the field with the image Style settings - Customize field and label wrapper HTML - Create a CSS class add a class pull-left
, and in the same parameters of the field with text add a class media-body
. Other fields can be added to the same field through Rewrite results - Rewrite the output of this field , without forgetting to turn off these fields themselves for output (Exclude from display) . Also, using the Views Bootstrap module (thanks to mrded ), Bootstrap components such as Thumbnails and Carousel can be used to style Views .
And finally, a small demonstration of some of the capabilities of the resulting topic blank.
Figure 6. Ready theme with debugging blocks enabled.
Thanks for attention! I hope this article is helpful and extends the scope of your use of Drupal.