Ok... I thought It was gonna be easy but...
I will be as descriptive as possible, with hopes that someone understands what my problem REALLY is:
I wanted to create another right sidebar region in Drupal 6, in the Zen theme. So:
1) I added a new region in my zen theme's .info file, called right_2 so that it seems like this:
regions[left] = left sidebar
regions[right] = right sidebar
regions[right_2] = right sidebar 2 /* this is the region that I added */
regions[navbar] = navigation bar
regions[content_top] = content top
regions[content_bottom] = content bottom
regions[header] = header
regions[footer] = footer
regions[closure_region] = closure
Then I added the code in page.tpl.php :
<?php if ($right_2): ?>
<div id="sidebar-right"><div id="sidebar-right-inner" class="region region-right">
<?php print $right_2; ?>
</div></div> <!-- /#sidebar-right-inner, /#sidebar-right -->
<?php endif; ?>
So far, so good, since I was able to place a block into the newly added region, and it "showed" it in the page... but....... not the way I was expecting it to...
Just by creating a new region in Drupal, Drupal doesn't understand that this region is a "side bar", and thus, it doesn't automatically create the two-sidebars body class in the html markup, and therefore I cannot easily style it.
For example, when I use the regular left sidebar, and right sidebar regions, Drupal prints:
<body class="not-front logged-in page-admin two-sidebars page-admin-build-block section-admin">
...from the page.tpl.php's $body_class line:
<body class="<?php print $body_classes; ?>">
BUT, when I use (assign a block to) my newly created region right sidebar 2 , instead of the default right sidebar , for instance, AND along with the left sidebar , it only prints:
<body class="front logged-in page-home one-sidebar sidebar-left">
It is clear that Drupal is not recognizing that my added region is another sidebar.
It doesn't matter where I put the new region code in page.tpl.php, it doesn't recognize it as a side bar.
This, of course, brings a lot of more troubles when trying to style my theme, since I cannot take advantage of a class like:
.two-sidebars #content
{
width: 560px;
margin-left: 200px; /* The width of #sidebar-left */
margin-right: -760px; /* Negative value of #content's width + left margin. */
}
in my layout.css
This class, is highly important, as you may see: the #content id is a very important part of the layout.
Is this to be considered as a bug?
For example; I just noticed that under /admin/build/block page, it does print the class two-sidebars:
<body class="not-front logged-in page-admin two-sidebars page-admin-build-block section-admin tableHeader-processed">
Is there any way I can tell drupal my right sidebar 2 is to be taken into account to print two-sidebars class in ?
Thank you.
Comments
Comment #1
gpk commentedThose classes are set in http://api.drupal.org/api/function/template_preprocess_page/6. Look at the code that defines $variables['layout'] and $body_classes (which gets transformed into $variables['body_classes']).
In your theme's template.php you could use function mytheme_preprocess_page() to override these values. Simply adding a relevant class if you have 2 right sidebars might be the easiest thing to do and straightforward to pick up with an additional CSS selector in your stylesheet. Also look at how the contrib aquamarine theme does it - this outputs a body class something like region "layout-first-main-last" which would mean we have left sidebar, main content area, and right sidebar. Might give you some ideas).
Comment #2
thebrotherofasis commentedOk... with your help, I am beggining to understand it (bear it in mind that I am not at all an experienced programmer).
1) $body_classes seems to be an array, that takes values based on the following preprocess function, found in the Zen Theme's template.php file:
/**
* Override or insert variables into the page templates.
*
* @param $vars
* An array of variables to pass to the theme template.
* @param $hook
* The name of the template being rendered ("page" in this case.)
*/
function zen_preprocess_page(&$vars, $hook) {
// Add an optional title to the end of the breadcrumb.
if (theme_get_setting('zen_breadcrumb_title') && $vars['breadcrumb']) {
$vars['breadcrumb'] = substr($vars['breadcrumb'], 0, -6) . $vars['title'] . '
';
}
// Add conditional stylesheets.
if (!module_exists('conditional_styles')) {
$vars['styles'] .= $vars['conditional_styles'] = variable_get('conditional_styles_' . $GLOBALS['theme'], '');
}
// Classes for body element. Allows advanced theming based on context
// (home page, node of certain type, etc.)
$body_classes = array($vars['body_classes']);
if (!$vars['is_front']) {
// Add unique classes for each page and website section
$path = drupal_get_path_alias($_GET['q']);
list($section, ) = explode('/', $path, 2);
$body_classes[] = zen_id_safe('page-' . $path);
$body_classes[] = zen_id_safe('section-' . $section);
if (arg(0) == 'node') {
if (arg(1) == 'add') {
if ($section == 'node') {
array_pop($body_classes); // Remove 'section-node'
}
$body_classes[] = 'section-node-add'; // Add 'section-node-add'
}
elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
if ($section == 'node') {
array_pop($body_classes); // Remove 'section-node'
}
$body_classes[] = 'section-node-' . arg(2); // Add 'section-node-edit' or 'section-node-delete'
}
}
}
if (theme_get_setting('zen_wireframes')) {
$body_classes[] = 'with-wireframes'; // Optionally add the wireframes style.
}
$vars['body_classes'] = implode(' ', $body_classes); // Concatenate with spaces
}
2) I have to copy and paste this function, into my subtheme folder's template.php file, and change its name to:
function subthemename_preprocess_page(&$vars, $hook) {
3) Now... looking at this code, I really don't see any reference, to the origination of the two-sidebars class, or other classes related to the number of sidebars in the page.
This, makes me think of the other thing you mention in your message: looking at the Core preprocess API.
4) The two aspects mentioned in includes/theme.inc, that you refered to, are:
and
5) With these elements of the recipe, what kind of information should I include in the overriding function :
function subthemename_preprocess_page(&$vars, $hook) {
etc...
??
6) How can I, for example, force $body_classes array, to have a value? What should the function look like?
Thank you.
Comment #3
gpk commentedYou will see that the Zen preprocessor gets the existing body classes
and then adds some more. You could do something similar, by checking for non-empty 2nd right sidebar.
These pages http://drupal.org/node/223430 and http://drupal.org/node/225125 suggest that the zen preprocessor will be run for the subtheme. This would be worth checking (the documentation is slightly unclear to my eye), but if so you wouldn't need to replicate the code there already, just add your own custom bit.
Comment #4
thebrotherofasis commentedOk... after a lot of trial and error, this overriding function I added to template.php in my subtheme folder....
... the following body classes:
However, as it can be seen in the body classes, I haven't been able to get rid of the class "one-sidebar". Altought my css two-sidebars is overriding it when it comes to content styling, I still wonder how could I tell drupal not to include it in my body classes?
On thing I did notice is that the underlying (core and zen theme) preprocess functions don't scale as I would expect; so I had to add a big ammount of code.
Thank you for your help.
L
Comment #5
gpk commentedSounds like you are making good progress.
>On thing I did notice is that the underlying (core and zen theme) preprocess functions don't scale as I would expect
Are you saying that zen_preprocess_page doesn't get called? If it did then that would improve the "scaling" since a lot of the code in your preprocess is duplication (I presume this is what you were talking about). You can tell by checking the content of $vars[] in your own preprocess hook as passed from the theme system.
You should also find that $vars['body_classes'] includes 'one-sidebar' already - it will have been set by http://api.drupal.org/api/function/template_preprocess_page/6, so you just need to strip that string out.
It takes a while to grok the themeing system but at the end of the day it handles *most* things pretty well.
Comment #6
thebrotherofasis commentedOk, here's where I stand at this point. I will say in detail what I have done.
Note 1) "plc_theme" is the name of my Zen's subtheme
Note 2) Some of my own insights are included in the code, with // comments
1) in plc_theme_template.php
2) in page.tpl.php
Result so far:
The body class that I am getting at this point (example):
Notice that it still prints one-sidebar and sidebar-left. BUT it also prints my so desired .two-right-sidebars class.
So, I noticed that when working out the .css of this body class output, I can put the code of .two-right-sidebars #content below the code .one-sidebar #content in my layout.css file. So this means that in a .ccs file, the code that appears below, seems to override the code above. So...
3) in layout.css added, below the code .two-sidebars #content
4) in layout.css changed
To
And added, below /** sidebar-right **/
This is getting me the desired result: An region called right_2 to be displayed nicely along with the default region right
*****
Indeed. I was mistaken when I said that other template_preprocess stages were not being called... because I could in the end verify that they were being called.
Now, how I verified it was just by assumption: seeing what was printed in
<body class="... etc">, and comparing with all the preprocess functions, both of Drupal API, and the Zen theme.A) What I would like to know is *how* I could "check the content of $vars[] in my own preprocess hook as passed from the theme system". What could I exactly do to know this?
An idea that comes to my mind is by temporarily printing the array at the header or footer in my page.tpl.php.
B) You are right when you notice that "$vars['body_classes'] includes 'one-sidebar' already". This is exactly why I had to write, in my "self-tutorial", all that stuff about css overriding code from "above" with code form "below".
It would be much more convenient to "strip that [one-sidebar class] out". How could I do this?
Thank you again for following up on my issue.
Comment #7
gpk commentedA) From within your preprocess hook you could use http://api.drupal.org/api/function/drupal_set_message/6 to output the content of $vars['body_classes']; but note that the body classes displayed on a given page view would refer to those applicable to the *previous* page view (this is a "timing issue" caused by the fact that the $messages variable has already been populated, in http://api.drupal.org/api/function/template_preprocess_page/6, by the time your hook gets invoked. To get round this you could also temporarliy add
$vars['messages'] .= theme('status_messages');to your preprocess hook).B) Easy, if crude -
$vars['body_classes'] = str_replace('one-sidebar ', '', $vars['body_classes']);Comment #8
thebrotherofasis commentedAfter some days of having written this support request, I found another interesting approach: the one found in the Newswire theme:
In template.php
and in page.tpl.php
Simple... and just fine!
Regards.
Comment #9
thebrotherofasis commented