how would I go about creating a filter for the body_class()
tag that allows me to add the the parent pages slug name as a class to the body whenever visiting a subpage or post?
3 Answers
here:
add_filter('body_class','body_class_slugs');
function body_class_slugs($classes) {
global $posts,$post;
if(is_single() || is_page()){ //only on a single post or page
if (isset($posts)){
$classes[] = $post[0]->post_name; //posts is an array of posts so we use the first one by calling [0]
}
elseif (isset($post)){
$classes[] = $post->post_name;
}
}
return $classes;
}
-
This looks promising, I'll give it a go and report back. Thank you for the quick/detailed response!– Mr.BrownCommented Feb 28, 2011 at 21:28
-
-
-
The only thing that loads is the Body tag...Firebugs not reporting any errors though. It seems to prevent everything else aside from the Body tag to be instantiated for some reason. I think it might be one of the global variables but I dunno??– Mr.BrownCommented Feb 28, 2011 at 22:17
-
Try this:
function my_body_class( $classes ) {
global $post;
# Page
if ( is_page() ) {
# Has parent / is sub-page
if ( $post->post_parent ) {
# Parent post name/slug
$parent = get_post( $post->post_parent );
$classes[] = 'parent-slug-'.$parent->post_name;
# Parent template name
$parent_template = get_post_meta( $parent->ID, '_wp_page_template', true);
if ( !empty($parent_template) )
$classes[] = 'parent-template-'.sanitize_html_class( str_replace( '.', '-', $parent_template ), '' );
}
}
return $classes;
}
add_filter( 'body_class', 'my_body_class' );
You'll get two additional classes:
- parent-slug-postname
- parent-template-templatename
-
Thanks kucrut! It doesnt seem to instantiate any new classes on pages with posts though. It would also be more useful if the new classes being created by the filter were also present while visiting the parent itself. (Im using these new classes to help with dynamic highlighting a image sprite menu)– Mr.BrownCommented Mar 5, 2011 at 4:59
-
I tried adding
|| is_post()
to the first if statement but it didnt seem to work and broke my theme while visiting a post.– Mr.BrownCommented Mar 5, 2011 at 5:13 -
The thing is I'm trying to take advantage of the old school trick where the body contains the same class as the nav when visiting a particular section in order to keep that section highlighted with CSS. So really, all i need a unique class for each page that stays present the entire time you visit any subpages or posts of each section of the site....does that make sense?– Mr.BrownCommented Mar 5, 2011 at 5:17
-
To get what you need, just replace parent-slug with page and replace parent-template with page-template so parent/child page will have the same classes. Commented Mar 5, 2011 at 12:38
-
Hmmm...All that does is change the names of the classes though, correct? I just tried it and thats the only thing noticeably different.– Mr.BrownCommented Mar 5, 2011 at 19:36
I tried looking in wordpresses post-template.php file where the body class is located and found the function that generates the class I want to be added when Im also on subpages or posts and copied it into my functions.php...then I added the is_single()
and is_page()
and that seemed to at least partly work however I cant get it to grab the template ID correctly yet like it does on its own when visiting a parent page.
This is what I tried:
add_filter('body_class','body_class_slugs');
function body_class_slugs($classes) {
global $wp_query, $wpdb;
if (is_single() || is_page() || is_page_template()) {
$classes[] = 'page-template';
$classes[] = 'page-template-' . sanitize_html_class( str_replace( '.', '-', get_post_meta( $page_id, '_wp_page_template', true ) ), '' );
}
return $classes;
}
This is what's outputed:
<body class="single single-post postid-852 single-format-standard page-template page-template-">
Notice page-template-, thats the class I need but with the rest of the template name...so it would be page-template-NAME-php.
My goal is to basically always have the parent template name class present in the body tag when visiting ANY page, ie. Pages, Subpages, Posts, etc...
EDIT 1
So I managed to get t31os's code working even though Im not sure I even did it right?
I placed his filter in my functions.php first:
add_filter( 'template_include', 'var_template_include', 1000 );
function var_template_include( $t ){
$GLOBALS['current_theme_template'] = basename($t);
return $t;
}
function get_current_template( $echo = false ) {
if( !isset( $GLOBALS['current_theme_template'] ) )
return false;
if( $echo )
echo $GLOBALS['current_theme_template'];
else
return $GLOBALS['current_theme_template'];
}
Then I added my last bit of code that I barrowed from wordpresses core post-template.php
file & added $classes[] = 'page-template-' . get_current_template();
as he recommended like so:
add_filter('body_class','body_class_slugs');
function body_class_slugs($classes) {
global $wp_query, $wpdb;
if (is_page_template() || is_page() || is_single()) {
$classes[] = 'page-template-' . sanitize_html_class( str_replace( '.', '-', get_current_template() ) );
}
return $classes;
}
You'll also notice I didnt want it to read - page-template-name.php so I added the sanitize_html_class( str_replace( '.', '-', get_current_template() ))
to remove the period.
This is one step closer, but unfortunately it still doesn't retrieve the parent template name in that way when visiting single posts or subpages, it only grabs the current template in use. This is also not very useful on single post pages since it renders: page-template-single-php
instead of the actual single template being used since I have several different ones.....hence why retrieving the parent template name to be displayed on all associated pages would be the most useful.
Any additional help is super appreciated!!! -- Its almost working!!!
-
Check out the answer i gave to this question, perhaps the code posted will help in this case to.– t31osCommented Mar 1, 2011 at 1:20
-
Thanks, seems like Id have to slightly adapt this to my particular needs though and Im not entirely sure how :(– Mr.BrownCommented Mar 1, 2011 at 1:47
-
If you add the code i posted in that answer to your theme's function file, you can then update your above code to call on the function, eg.
$classes[] = 'page-template-' . get_current_template();
– t31osCommented Mar 1, 2011 at 10:32 -
Can you elaborate on how to add this to your original function though? I dont understand how to do that yet.– Mr.BrownCommented Mar 4, 2011 at 9:30
-