Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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?

share|improve this question
add comment

3 Answers 3

up vote 0 down vote accepted

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;
}
share|improve this answer
    
This looks promising, I'll give it a go and report back. Thank you for the quick/detailed response! –  Mr.Brown Feb 28 '11 at 21:28
    
Hmmm.....not sure why but its breaking my theme??? –  Mr.Brown Feb 28 '11 at 21:44
    
breaking how? any errors? –  Bainternet Feb 28 '11 at 22:11
    
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.Brown Feb 28 '11 at 22:17
    
try addin rewind_posts(); before return $classes; –  Bainternet Feb 28 '11 at 23:48
show 1 more comment

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
share|improve this answer
    
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.Brown Mar 5 '11 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.Brown Mar 5 '11 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.Brown Mar 5 '11 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. –  kucrut Mar 5 '11 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.Brown Mar 5 '11 at 19:36
show 3 more comments

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!!!

share|improve this answer
    
Check out the answer i gave to this question, perhaps the code posted will help in this case to. –  t31os Mar 1 '11 at 1:20
    
Thanks, seems like Id have to slightly adapt this to my particular needs though and Im not entirely sure how :( –  Mr.Brown Mar 1 '11 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(); –  t31os Mar 1 '11 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.Brown Mar 4 '11 at 9:30
    
Ive edited my second answer/post. –  Mr.Brown Mar 4 '11 at 22:22
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.