2

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 3

0

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

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
8
  • 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
    Commented 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.Brown
    Commented 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.Brown
    Commented 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.Brown
    Commented Mar 5, 2011 at 19:36
0

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

5
  • Check out the answer i gave to this question, perhaps the code posted will help in this case to.
    – t31os
    Commented 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.Brown
    Commented 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();
    – t31os
    Commented 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.Brown
    Commented Mar 4, 2011 at 9:30
  • Ive edited my second answer/post.
    – Mr.Brown
    Commented Mar 4, 2011 at 22:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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