How can I switch to a different theme template file for any node that I want?
I understand how to create sub-themes like node-recipes.tpl.php for a node that has a path of "recipes". But what I want to have control of the entire base template like page.tpl.php.
Can I use some preprocess function in template.php for this?
Right now I have this in my template.php file:
function mythemename_preprocess_node(&$vars) {
// template name for current node id
$suggestions = array('node-'. $vars['nid']);
// additional node template names based on path alias
if (module_exists('path')) {
// we already can have a path alias
if (isset($vars['path'])) {
$alias = $vars['path'];
}else{
// otherwise do standard check
$alias = drupal_get_path_alias('node/'. $vars['nid']);
}
if ($alias != 'node/'. $vars['nid']) {
$add_path = '';
foreach (explode('/', $alias) as $path_part) {
$add_path .= !empty($path_part) ? $path_part.'_' : '';
$suggestions[] = 'node-'. $add_path;
}
// adding the last one (higher priority) for this path only
// node-some-long-path-nofollow.tpl.php (not for anchestors)
$suggestions[] = end($suggestions) .'-nofollow';
}
$suggestions=array_map(stripTag, $suggestions);
//print_r($suggestions);
}
$vars['template_files'] = isset($vars['template_files']) ? array_merge($vars['template_files'], $suggestions) : $suggestions;
}
thanks
Yes,
You can fully control the $vars['template_files'] array. I always suggest adding onto the array rather then overwriting it completely.
I have a module that I maintain that adds a few small suggestions that I use often.
http://github.com/electblake/template_suggestions/blob/master/template_suggestions.module
You can manipulate the $vars['template_files'] array in preprocess_node, preprocess_page, etc.
If you want to switch you page.tpl.php to another theme file do it in the preprocess_page hook...
I'm using this function to create template suggestions that works for me now. Thanks for the suggestions everyone.
/**
* Override or insert PHPTemplate variables into the templates.
* These are the main outer templates such as page.tpl.php
*/
function phptemplate_preprocess_page(&$vars) {
$alias = drupal_get_path_alias($_GET['q']);
if ($alias != $_GET['q']) {
$template_filename = 'page';
foreach (explode('/', $alias) as $path_part) {
$template_filename = $template_filename . '-' . $path_part;
$vars['template_files'][] = $template_filename;
}
}
//----
//print_r(arg());
/* print '<pre>';
print_r($vars);
print '</pre>';*/
//dpm($vars);
//print_r($vars['template_files']);
}
Related
I'm looking forward to implement taxonomy terms based css styling; especially for the body tag which i want to add the current terms.
For now, here's what i have so far :
function _phptemplate_variables($hook, $vars = array()) {
global $node;
switch ($hook) {
case 'page': die ('test');
$vars['body_class'] = '';
if (arg(0) == 'taxonomy' && arg(1) == 'term' && is_numeric(arg(2))) {
$vars['body_class'] = 'theme'.arg(2);
}
if (arg(0) == 'node' && is_numeric(arg(1))) {
$node = node_load(arg(1));
if (is_array($node->taxonomy)) {
foreach ($node->taxonomy as $term) {
$vars['body_class'] .= 'theme'.$term->tid;
}
}
}
if (drupal_is_front_page()) {
$vars['body_class'] .= ' front';
}
break;
}
return $vars;
}
I think the code is OK, but it never get called (see my 'die' function); using simple phptemplate engine and minimal drupal6 install.
What obviousity am I missing here ?
/**
* Override or insert PHPTemplate variables into the templates.
*/
function phptemplate_preprocess_page(&$vars) {
//
}
/**
* Override or insert PHPTemplate variables into the templates.
*/
function phptemplate_preprocess_node(&$vars) {
//
}
Well, years ago we wrote this up http://openconcept.ca/blog/jmlane/taxonomy_specific_css
It would need to be updated I expect for Drupal 6 or 7 but the principals still apply.
For Drupal 7 a more elegant solution might be to use the Context module. See the following posting for detailed information and instructions.
Add a body class based on a node's vocabulary term
The Context modules allows for creating arbitrary contexts for specific Drupal pages, e.g. based on taxonomy terms. These contexts can trigger certain reactions, e.g. add a CSS class with the chosen taxonomy term.
i want to using the taxonomy page template according to the content type? namely, the tag under content type "story" using a tpl.php, and the tag under the content page, using another tpl.php file. how should i do?thank you.
In template.php of your theme:
/**
* Override or insert variables into the page templates.
*
* #param $vars
* An array of variables to pass to the theme template.
*/
function YOURTHEMENAME_preprocess_page(&$vars) {
// ...
$node = $vars['node'];
if ($node && ($node->type=='story')) {
foreach ($node->taxonomy as $term) {
if ($term->name == 'SOMETAG1') {
$vars['template_files'][] = 'page-sometag1';
break;
}
else if ($term->name == 'SOMETAG2') {
$vars['template_files'][] = 'page-sometag2';
break;
}
}
}
// ...
}
Replace uppercase with your values. page-sometag1.tpl.php and page-sometag2.tpl.php files should be in your theme folder.
The ThemeKey module might do this.
(Not sure it can work with both content-type and taxonomy term in the same condition ; but I've seen it used a couple of times to change templates / themes bases on some conditions)
I'm using jCarousel to build a slideshow that displays in a block. The content type has image upload fields and those images are going to display in the carousel. I want that every node has a different images in the carousel. In Views I defined filters by Type. But that takes all the images from every node. How can I solve this?
Are the images you want on a specific page uploaded via that page?
If so, you can use the Node:NID argument.
Under "Action to take if argument is not present:"
check "Provide default argument"
then "Node ID from URL"
Here's more info about the template.php comment:
In page.tpl.php add
<body class="<?php print $body_classes; ?>">
in template.php, add
function phptemplate_preprocess_page(&$vars, $hook) {
// 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[] = phptemplate_id_safe('page-' . $path);
$body_classes[] = phptemplate_id_safe('section-' . $section);
if (arg(0) == 'node') {
if (arg(1) == 'add') {
if ($section == 'node') {
array_pop($body_classes); // Remove 'section-node'
}
$body_classes[] = 'node-add'; // Add '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[] = 'node-' . arg(2); // Add 'node-edit' or 'node-delete'
}
}
}
$vars['body_classes'] = implode(' ', $body_classes); // Concatenate with spaces
}
function phptemplate_id_safe($string) {
if (is_numeric($string{0})) {
// If the first character is numeric, add 'n' in front
$string = 'n'. $string;
}
return strtolower(preg_replace('/[^a-zA-Z0-9_-]+/', '-', $string));
}
Does anyone know how or can guide me in the right direction on how to add a body css class for the current node's taxonomy term? i.e. <body class="term-dogs"> where "dogs" is the taxonomy term name. It could also be just the term ID. Either way is fine I just need a solution. This will be for a Drupal 7 zen sub-theme
This answer took longer than I expected to figure out. The hard part was collecting the terms on the node, since All taxonomy functions relating to nodes have been removed or refactored. Ultimately, page 355 of Pro Drupal 7 Development saved the day with a snippet that does the job previously handled by taxonomy_node_get_terms.
Below is the code that worked for me (look for the part that says "MAGIC BEGINS HERE"). Assuming you're creating a sub-theme of Zen, you'll want to move this to your sub-theme's template.php file and rename it to YOURSUBTHEMENAME_preprocess_html:
/**
* Override or insert variables into the html template.
*
* #param $vars
* An array of variables to pass to the theme template.
* #param $hook
* The name of the template being rendered ("html" in this case.)
*/
function zen_preprocess_html(&$vars, $hook) {
// If the user is silly and enables Zen as the theme, add some styles.
if ($GLOBALS['theme'] == 'zen') {
include_once './' . drupal_get_path('theme', 'zen') . '/zen-internals/template.zen.inc';
_zen_preprocess_html($vars, $hook);
}
// Classes for body element. Allows advanced theming based on context
// (home page, node of certain type, etc.)
if (!$vars['is_front']) {
// Add unique class for each page.
$path = drupal_get_path_alias($_GET['q']);
// Add unique class for each website section.
list($section, ) = explode('/', $path, 2);
if (arg(0) == 'node') {
if (arg(1) == 'add') {
$section = 'node-add';
}
elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
$section = 'node-' . arg(2);
}
// MAGIC BEGINS HERE
$node = node_load(arg(1));
$results = field_view_field('node', $node, 'field_tags', array('default'));
foreach ($results as $key => $result) {
if (is_numeric($key)) {
$vars['classes_array'][] = strtolower($result['#title']);
}
}
// MAGIC ENDS HERE
}
$vars['classes_array'][] = drupal_html_class('section-' . $section);
}
if (theme_get_setting('zen_wireframes')) {
$vars['classes_array'][] = 'with-wireframes'; // Optionally add the wireframes style.
}
// Store the menu item since it has some useful information.
$vars['menu_item'] = menu_get_item();
switch ($vars['menu_item']['page_callback']) {
case 'views_page':
// Is this a Views page?
$vars['classes_array'][] = 'page-views';
break;
case 'page_manager_page_execute':
case 'page_manager_node_view':
case 'page_manager_contact_site':
// Is this a Panels page?
$vars['classes_array'][] = 'page-panels';
break;
}
}
I needed to know how to do this and Matt V's solution worked perfectly. I made a couple of additions to his work. I called drupal_html_class which replaces spaces and invalid characters. And I added in the term ID to allow you to target a term even if the name of the term changes.
// MAGIC BEGINS HERE
$node = node_load(arg(1));
$results = field_view_field('node', $node, 'field_tags', array('default'));
foreach ($results as $key => $result) {
if (is_numeric($key)) {
// Call drupal_html_class to make safe for a css class (remove spaces, invalid characters)
$vars['classes_array'][] = "taxonomy-" . strtolower(drupal_html_class( $result['#title']) );
// Add taxonomy ID. This will allow targeting of the taxonomy class even if the title changes
$vars['classes_array'][] = "taxonomy-id-" . $result['#options']['entity']->tid ;
}
}
// MAGIC ENDS HERE
Not sure what you mean with that body tag, but the classes on the node are generated here:
http://api.drupal.org/api/drupal/modules--node--node.module/function/template_preprocess_node/7
You can add more by implementing yourmodule_preprocess_node($vars) and then add whatever you want to $vars['classes_array']
In the template.php file I inserted the code below:
I found a tutorial online that gives the code, but I'm confused on how to get it to work.
I copied the code below and inserted it into the template.php from the theme HTML5_base.
I duplicated the page.tpl.php file and created custom pages -- page-gallery.tpl.php and page-articles.tpl.php. I inserted some text to the files just see that I've navigated to the pages w/ the changes. It looks like Drupal is not recognizing gallery.tpl.php and page-articles.tpl.php.
In the template.php there are the following functions:
html5_base_preprocess_page()
html5_base_preprocess_node()
html5_base_preprocess_block()
In the tutorial it uses these functions:
phptemplate_preprocess_page()
phptemplate_preprocess_block()
phptemplate_preprocess_node()
function phptemplate_preprocess_page(&$vars)
{
//code block from the Drupal handbook
//the path module is required and must be activated
if(module_exists('path'))
{
//gets the "clean" URL of the current page
$alias = drupal_get_path_alias($_GET['q']);
$suggestions = array();
$template_filename = 'page';
foreach(explode('/', $alias) as $path_part)
{
$template_filename = $template_filename.'-'.$path_part;
$suggestions[] = $template_filename;
}
$vars['template_files'] = $suggestions;
}
}
function phptemplate_preprocess_node(&$vars)
{
//default template suggestions for all nodes
$vars['template_files'] = array();
$vars['template_files'][] = 'node';
//individual node being displayed
if($vars['page'])
{
$vars['template_files'][] = 'node-page';
$vars['template_files'][] = 'node-'.$vars['node']->type.'-page';
$vars['template_files'][] = 'node-'.$vars['node']->nid.'-page';
}
//multiple nodes being displayed on one page in either teaser
//or full view
else
{
//template suggestions for nodes in general
$vars['template_files'][] = 'node-'.$vars['node']->type;
$vars['template_files'][] = 'node-'.$vars['node']->nid;
//template suggestions for nodes in teaser view
//more granular control
if($vars['teaser'])
{
$vars['template_files'][] = 'node-'.$vars['node']->type.'-teaser';
$vars['template_files'][] = 'node-'.$vars['node']->nid.'-teaser';
}
}
}
function phptemplate_preprocess_block(&$vars)
{
//the "cleaned-up" block title to be used for suggestion file name
$subject = str_replace(" ", "-", strtolower($vars['block']->subject));
$vars['template_files'] = array('block', 'block-'.$vars['block']->delta, 'block-'.$subject);
}
Ah! That's a lot of pain to do this.
Why don't you try the Ctools and Panels modules.
Ctools has a lot of useful modules, the one you'd make good use of is called "Page Manager". It will allow you to create custom pages of your choice, and apply custom layouts using the Panels module.
Hope this simplifys things.