Jerarquía de tipo de publicación personalizada de WordPress y resaltado de menú (current_page_parent)

7 minutos de lectura

avatar de usuario
craig

Creé un tipo de publicación personalizada de ‘cartera’ y una página con una plantilla que recupera todas las publicaciones que coinciden con ese tipo de publicación personalizada.

El problema es que cuando profundizo en la publicación real, la publicación parece estar debajo de ‘blog’ en el resaltado del menú principal (muestra current_page_parent como una clase)

La URL del enlace permanente es correcta: www.site.com/portfolio/post-slug

Pero el menú cree que el padre es ‘blog’.

Esto es obviamente un problema jerárquico, pero no sé qué hacer para solucionarlo.

Parece que este es un problema con el código principal de WordPress; el código que genera las clases de menú agrega current_page_parent a su página de blog en todas partes, excepto cuando se visualizan plantillas de página estáticas.

(Esto ha sido discutido de pasada en http://core.trac.wordpress.org/ticket/13543).

Sin embargo, puede solucionar esto con algún código personalizado utilizando el filtro page_css_class. Por ejemplo, agregue algo similar a functions.php (no 100% probado):

function my_page_css_class($css_class, $page) {
    if (get_post_type()=='portfolio' || is_page(57)) {
        if ($page->ID == get_option('page_for_posts')) {
            foreach ($css_class as $k=>$v) {
                if ($v=='current_page_parent') unset($css_class[$k]);
            }
        }
        if ($page->ID==57) {
            $css_class[]='current_page_parent';
        }
    }
    return $css_class;
}
add_filter('page_css_class','my_page_css_class',10,2);

Reemplazando 57 con el ID de la página de sus portafolios, por supuesto. Eso elimina current_page_parent al imprimir la página del blog y agrega current_page_parent a la página de su cartera, ya sea al ver una sola cartera o al ver la página de carteras en sí.

  • Lo he hecho con CSS y clases de cuerpo por ahora. Gracias por la función sin embargo.

    –Craig

    18 de julio de 2010 a las 14:38

avatar de usuario
Tanuki

Aquí está mi versión optimizada/extendida de las soluciones sugeridas anteriormente, que está prácticamente completamente automatizada. No se necesitan más atributos de menú o CSS adicionales.

Esta versión obtiene dinámicamente una lista de tipos de publicaciones personalizadas y, si el tipo de publicación actual es un tipo de publicación personalizada, elimina la clase ‘current_page_parent’ de todos los elementos del menú.

Además, verifica cada elemento del menú para ver si es para una página con una plantilla de página como “page-{custom_post_type_slug}.php”, y si es así, agregará la clase ‘current_page_parent’.

La prioridad del filtro es 1, ya que algunos temas reemplazan a current_page_parent/etc. clases con una clase como ‘activa’ (por ejemplo, ‘raíces’ hace esto), por lo que este filtro debe ejecutarse primero.

Por último, hace uso de 3 variables estáticas ya que esta función se llama repetidamente y estas (obviamente) siguen siendo las mismas en todas las llamadas.

function theme_current_type_nav_class($css_class, $item) {
    static $custom_post_types, $post_type, $filter_func;

    if (empty($custom_post_types))
        $custom_post_types = get_post_types(array('_builtin' => false));

    if (empty($post_type))
        $post_type = get_post_type();

    if ('page' == $item->object && in_array($post_type, $custom_post_types)) {
        $css_class = array_filter($css_class, function($el) {
            return $el !== "current_page_parent";
        });

        $template = get_page_template_slug($item->object_id);
        if (!empty($template) && preg_match("/^page(-[^-]+)*-$post_type/", $template) === 1)
            array_push($css_class, 'current_page_parent');

    }

    return $css_class;
}
add_filter('nav_menu_css_class', 'theme_current_type_nav_class', 1, 2);

PD. Solo para señalar una deficiencia en todas las soluciones que no son CSS que he visto hasta ahora, incluida la mía: algo que no se tiene en cuenta es resaltar el elemento del menú padre/ancestro de un elemento que se vincula a una página que muestra publicaciones de la costumbre actual tipo de mensaje. Considere un tipo de publicación personalizada “producto” y un menú como:

Home  Company  News  Contact
      |
      \--About Us
      \--Products

“Productos” es una página con una plantilla “page-product.php” y muestra una descripción general de las publicaciones de tipo ‘producto’. Se destaca debido a la solución publicada. Sin embargo, ‘Compañía’ como su padre/ancestro también debe estar resaltado, pero no lo está. Algo para tener en cuenta.

  • Gracias. Esto resolvió mi problema con la publicación del blog que recibía una clase activa mientras veía un tipo de publicación personalizada

    – Mattijs

    13 de febrero de 2015 a las 5:14

Boleto de WP: http://core.trac.wordpress.org/ticket/16382

function fix_blog_menu_css_class( $classes, $item ) {
    if ( is_tax( 'my-cat-tax' ) || is_singular( 'my-post-type' ) || is_post_type_archive( 'my-post-type' ) ) {
        if ( $item->object_id == get_option('page_for_posts') ) {
            $key = array_search( 'current_page_parent', $classes );
            if ( false !== $key )
                unset( $classes[ $key ] );
        }
    }

    return $classes;
}
add_filter( 'nav_menu_css_class', 'fix_blog_menu_css_class', 10, 2 );

avatar de usuario
petirrojos vayu

Investigué un poco más sobre esto y encontré otra forma de hacerlo.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2);
function current_type_nav_class($css_class, $item)
{
    if (get_post_type() === 'portfolio') {
        $current_value="current_page_parent"; 
        $css_class = array_filter($css_class, function ($element) use ($current_value) {
            return ($element != $current_value);
        });
    }

    $post_type = get_query_var('post_type');
    if ($item->attr_title !== '' && $item->attr_title === $post_type) {     
        array_push($css_class, 'current_page_parent');
    };

    return $css_class;
}

Recibí ayuda de esta publicación y luego la modifiqué para eliminar también la clase “current_page_parent” de la página del blog.
https://wordpress.stackexchange.com/questions/3014/highlighting-wp-nav-menu-ancestor-class-wo-children-in-nav-structure/3034#3034

Cordialmente Vayu

Como se explica en https://core.trac.wordpress.org/ticket/16382, .current_page_parent coincide con “cualquier cosa que no sea una página” en aras de la compatibilidad con versiones anteriores (tenga en cuenta que esto se consideró al revés hace 10 años …) por lo que los temas de hoy en día realmente no deberían seguir usándolo.

Entonces, la solución más simple y la más eficiente (ya que, a diferencia de las respuestas anteriores, no requiere ejecutar código adicional en cada carga de página), es modificar el CSS de su tema para reemplazar el uso del .current_page_parent selector de clase con .current-menu-parent, que hace lo correcto. (NB guiones bajos vs guiones.)

Si está utilizando un tema de terceros y no desea modificarlo directamente, puede sobrescribir sus propiedades en su propia hoja de estilo. Por ejemplo, si su tema tiene:

.current_page_parent > a {
    border-bottom: 4px solid blue;
}

luego, en la hoja de estilo de su tema hijo, haría esto para cancelar sus efectos y aplicarlos a la clase correcta:

.current_page_parent > a {
    border-bottom: transparent !important;  /* Cancel out incorrect styling */
}
.current-menu-parent > a {
    border-bottom: 4px solid blue;   /* Add styling correctly */
}

Este es solo un ejemplo: la forma correcta dependerá de cómo su tema diseñe estos enlaces.

  • Estaba teniendo el mismo problema, ¡pero estas propiedades me ayudaron 7 años después! Gracias 😉

    – Krys

    10 de septiembre de 2021 a las 7:32


avatar de usuario
panadero

Aquí hay una solución que funcionó para mí, sin tener que definir mi tipo de publicación personalizada o la identificación del menú o la identificación de la página en el código:

http://dtbaker.net/web-development/how-to-stop-wordpress-automatically-highlighting-the-blog-page-in-the-menu/

function dtbaker_wp_nav_menu_objects($sorted_menu_items, $args){
    // this is the code from nav-menu-template.php that we want to stop running
    // so we try our best to "reverse" this code wp code in this filter.
    /* if ( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && empty( $wp_query->is_page ) && $home_page_id == $menu_item->object_id )
            $classes[] = 'current_page_parent'; */

    // check if the current page is really a blog post.
    //print_r($wp_query);exit;
    global $wp_query;
    if(!empty($wp_query->queried_object_id)){
        $current_page = get_post($wp_query->queried_object_id);
        if($current_page && $current_page->post_type=='post'){
            //yes!
        }else{
            $current_page = false;
        }
    }else{
        $current_page = false;
    }


    $home_page_id = (int) get_option( 'page_for_posts' );
    foreach($sorted_menu_items as $id => $menu_item){
        if ( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && empty( $wp_query->is_page ) && $home_page_id == $menu_item->object_id ){
            if(!$current_page){
                foreach($sorted_menu_items[$id]->classes as $classid=>$classname){
                    if($classname=='current_page_parent'){
                        unset($sorted_menu_items[$id]->classes[$classid]);
                    }
                }
            }
        }
    }
    return $sorted_menu_items;
}
add_filter('wp_nav_menu_objects','dtbaker_wp_nav_menu_objects',10,2);

  • Estaba teniendo el mismo problema, ¡pero estas propiedades me ayudaron 7 años después! Gracias 😉

    – Krys

    10 de septiembre de 2021 a las 7:32


¿Ha sido útil esta solución?