Виділення wp_nav_menu () Клас предків без дітей у військово-морській структурі?


30

( Примітка модераторів: Спочатку була названа "wp_nav_menu Клас предків без дітей у структурі навігації")

У мене wp_nav_menuв заголовку є три сторінки. Коли я перебуваю на одній із цих сторінок, що liмістить цю сторінку в меню отримує клас .current_page_item. На цих трьох сторінках є шаблони, і ці шаблони містять власні запити для отримання всіх публікацій певного типу вмісту. Насправді сприймаються "діти" цієї сторінки верхнього рівня насправді не є дітьми, вони просто типу вмісту, який я асоціював із цією сторінкою верхнього рівня за допомогою шаблону.

Я хотів би, щоб пункти меню верхнього рівня отримали 'current-ancestor'клас, коли користувач переглядає одну сторінку певного типу публікації, знову ж таки пов’язану з цією сторінкою лише у власному запиті у файлі шаблону.

Сподіваюся, що це має сенс - якщо ні, то дайте мені знати, де я вас загубив! Дуже вдячний за будь-яку допомогу.

- Призначено для конкретних даних: Наприклад, у мене є статична сторінка під назвою Майстерні, що використовує шаблон. Його слима - цехи . У шаблоні є власна функція get_posts і цикл всередині нього, який витягує та відображає всі повідомлення спеціального типу вмісту, що називається семінарами . Якщо я клацну на одному з цих назви семінарів, я перейду до повного вмісту цього змісту. Структура постійної посилання спеціального типу публікації встановлена ​​на майстерні / ім’я, тому, як бачить користувач, ці частини вмісту є дітьми сторінки Майстерні, коли насправді вони є одним типом вмісту, але не пов'язані зі сторінкою. Саме цей проміжок мені потрібно ефективно закрити в меню, виділяючи пункт меню "Майстерні" під час перегляду вмісту типу "майстерня".

Знову ж таки, сподіваюся, що це має сенс, я думаю, що я сказав «семінар» вище 20 разів одним пунктом!


@Gavin - Чи можете ви включити ще кілька специфік того, що ви намагаєтеся досягти. Простіше написати відповідь конкретними словами, ніж якщо ми спробуємо це зробити абстрактно. Також, якщо ви могли б пояснити свою структуру URL-адрес, пов'язану з ними, було б корисно.
MikeSchinkel

1
@Gavin - Це допомагає. Отже, ваш варіант меню верхнього рівня - це список семінарів на "Майстернях" з контуром, /workshops/і коли користувач перебуває на сторінці семінару (тобто /workshops/example-workshop/), ви хочете, щоб у пункті меню "Майстерні" був current_page_itemпризначений клас , правильно?
MikeSchinkel

wp_nav_menu () викриває клас поточного меню-предка
Даніель Сакс

Відповіді:


29

Є більш просте рішення. Забудьте створити сторінки для кожного типу публікації, щоб ви могли мати елементи навігації, оскільки, як ви вже дізналися, WP не може визнати, що користувацькі типи, які ви переглядаєте, пов'язані з цією сторінкою.

Натомість створіть спеціальне посилання у меню «Знешні вигляд->». Просто введіть URL-адресу, яка поверне ваш власний тип, і дайте їй мітку, а потім натисніть "Додати в меню".

http://example.com/workshops/

або не дуже-постійні посилання:

http://example.com/?post_type=workshops

лише це просто створить кнопку навігації, яка відображатиме всі публікації з цим користувальницьким типом публікації, а також додасть клас поточного меню, коли ви натиснули цей елемент навігації, але він ще не додасть клас наві в жоден URL-адреса, окрім цієї

Потім, після його створення, перейдіть у конфігурацію для цього нового елемента та введіть кулю типу спеціального допису в поле "Атрибут заголовка" (ви також можете використовувати поле опису, але це приховано в параметрах екрана адміністратора за замовчуванням).

Тепер вам потрібно підключити nav_menu_css_classфільтр (який знімається для кожного елемента наві) та перевірити, чи переглядається вміст типу публікації, зазначеного у вашому користувальницькому елементі nav:

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {
    $post_type = get_query_var('post_type');
    if ($item->attr_title != '' && $item->attr_title == $post_type) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}

У цьому випадку ми перевіримо, чи вміст поля атрибутів заголовка не порожній і чи відповідає вони поточному запиту пост_типу. Якщо це так, ми додаємо клас поточного меню до його масиву класів, а потім повертаємо модифікований масив.

Ви можете змінити це, щоб просто відповідати заголовку елемента навігації, але якщо ви з якоїсь причини хочете назвати елемент навігації інакше, ніж звичайний слуп типу публікації, використання поля Атрибут заголовка або Опис надає вам таку гнучкість.

Тепер, коли ви переглядаєте один елемент (або, можливо, навіть архівні списки) типу публікації, який відповідає елементу меню nav, цей елемент буде наданий класу CSS-поточного меню, щоб ваше виділення спрацювало.

Не потрібно жодних сторінок або шаблонів сторінок ;-) Запит URL-адреси забезпечує пошук потрібних публікацій. Ваш шаблон циклу піклується про відображення результатів запиту. Ця функція забезпечує розпізнавання показаних даних та додавання класу CSS.

БОНУС

Ви навіть можете автоматизувати процес за wp_update_nav_menu_itemдопомогою автоматичного створення елементів меню для всіх типів ваших публікацій. У цьому прикладі вам потрібно спочатку отримати $menu_idменю навігації, до якого потрібно додати ці елементи.

$types = get_post_types( array( 'exclude_from_search' => false, '_builtin' => false  ), 'objects' );
foreach ($types as $type) {
    wp_update_nav_menu_item( $menu_id, 0, array(
        'menu-item-type' => 'custom',
        'menu-item-title' => $type->labels->name,
        'menu-item-url' => get_bloginfo('url') . '/?post_type=' . $type->rewrite['slug'],
        'menu-item-attr-title' => $type->rewrite['slug'],
        'menu-item-status' => 'publish'
        )
    );
}

Ось така штука! Я використовую шаблони сторінок лише тому, що макети для цих сторінок досить складні і не просто перераховують сторінки, проте я все одно можу використовувати той фільтр, який ви надали, щоб перевірити ідентифікатор сторінки. Природа цієї теми полягає в тому, що параметри теми дозволяють вам зіставити сторінки ("домашня сторінка" - це сторінка, "про" - це сторінка тощо), так що це повинно працювати ідеально. Дякую за (неймовірно детальну) допомогу!
Гевін

мені довелося видалити current_page_parentелемент навігації, який був моїм блогом, але в іншому випадку він працював. thx
pkyeck

це не працювало для мене, оскільки $item->attr_titleвитягнув НАЗВАННЯ, і я написав назву великими літерами. тому я змінив атрибут $item->post_nameі зараз він працює добре для мене.
honk31

Я намагався зробити так, щоб код працював на мою тему, але не можу змусити його працювати. Клас, застосований до мого батьківського елемента, у меню не буде, коли я перебуваю на типі користувальницької пошти portfolio. Я використав вище код. У чому може бути проблема?
Каспер

4

замість використання

$ post_type = get_query_var ('пост_тип');

Ви можете спробувати:

$ post_type = get_post_type ();

Оскільки іноді тип публікації не встановлюється у варі запиту. Це стосується типового post_type "публікації", тому якщо ви хочете виділити публікацію, яку було зазначено на сторінці з переліком, вам потрібно буде скористатися цією. get_very_var () просто повертає порожній рядок для типів публікацій, які не є звичайними.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {
    $post_type = get_post_type();
    if ($item->attr_title != '' && $item->attr_title == $post_type) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}

2

@Somatic - це фантастика! Я трохи змінив ваш код, щоб він також працював для певної систематики (яку я використовую лише для відповідного post_type). Ідея полягає у використанні атрибута заголовка пункту меню для збереження імені пост_типу ТА назви таксономії, відокремленої комою та двокрапкою, а потім вибухнутої функцією.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {

    # get Query Vars
    $post_type = get_query_var('post_type');  
    $taxonomy = get_query_var('taxonomy');

    # get and parse Title attribute of Menu item
    $title = $item->attr_title; // menu item Title attribute, as post_type;taxonomy
    $title_array = explode(";", $title);
    $title_posttype = $title_array[0];
    $title_taxonomy = $title_array[1];

    # add class if needed
    if ($title != '' && ($title_posttype == $post_type || $title_taxonomy == $taxonomy)) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}

2

Ось моє рішення, якщо ви хочете працювати з wp_list_pages.

додайте це у ваші функції.php

add_filter('page_css_class', 'my_page_css_class', 10, 2);
function my_page_css_class($css_class, $page){
    $post_type = get_post_type();
    if($post_type != "page"){
        $parent_page = get_option('page_for_custom_post_type-'.$post_type);
        if($page->ID == $parent_page)
            $css_class[] = 'current_page_parent';
    }
    return $css_class;
}

Тепер просто додайте в таблицю wp_options новий рядок з option_name з page_for_custom_post_type-хххх і OPTION_VALUE з сторінки-ID і хочете підключитися.

Можливо, ви визнали, що вже є варіант, який називається page_for_posts . Якщо у вас є лише 1 користувальницький тип публікації, ви можете встановити вашу сторінку за адресою /wp-admin/options-reading.php у спадному меню, а навігація правильно встановить поточну сторінку.

Я думаю, що ядро ​​WordPress має розширити цей розділ зі спадним списком для кожного зареєстрованого типу публікації.


2

Я вирішив дотримуватися сторінок і використовувати назву шаблону сторінки як клас на елементі nav. Це дозволяє мені не захаращувати атрибут заголовка, який мені не сподобався в деяких інших рішеннях.

add_filter('nav_menu_css_class', 'mbudm_add_page_type_to_menu', 10, 2 );
//If a menu item is a page then add the template name to it as a css class 
function mbudm_add_page_type_to_menu($classes, $item) {
    if($item->object == 'page'){
        $template_name = get_post_meta( $item->object_id, '_wp_page_template', true );
        $new_class =str_replace(".php","",$template_name);
        array_push($classes, $new_class);
        return $classes;
    }   
}

У мене також додані класи тіла до header.php

<body <?php body_class(); ?>>

Нарешті, це рішення потребує додаткового css, щоб застосувати вибраний / активний стан до елементів навігаційного меню. Я використовую його для відображення архівів таксономії та спеціальних типів публікацій, пов’язаних зі сторінкою, як дітей цієї сторінки:

/* selected states - include sub pages for anything related to products */
#nav-main li.current-menu-item a,
body.single-mbudm_product #nav-main li.lp_products a,
body.tax-mbudm_product_category #nav-main li.lp_products a,
#nav-main li.current_page_parent a{color:#c00;}

Це дало мені таку помилку: Warning: join() [function.join]: Invalid arguments passed in /home/path/to/wp-includes/nav-menu-template.php on line 76 будь-яка ідея, що тут сталося?
Джефф К.

О, я думаю, я бачу, що відбувається. Це тому, що ви повертаєте $ class в операторі if. Просто переміщення return $classesназовні і після цього, ifздається, вирішує вищевказану помилку.
Джефф К.

1

@Somatic - чудовий код! Я сам змінився. Я хотів зберегти атрибут заголовка за призначенням, тому замість цього я помістив кулі типу користувальницького типу в розширені властивості меню Link Relationship (XFN), які можна ввімкнути в параметрах екрана. Я модифікував

if ($item->attr_title != '' && $item->attr_title == $post_type) {

і змінив його на

if ($item->xfn != '' && $item->xfn == $post_type) {

0

Приємна робота соматична.

На жаль, я не розумію, як ви можете перелічити свої власні типи публікацій на сторінці так, як ви пояснюєте. Якщо я не використовую сторінку-portfolio.php і додаю її до сторінки, я отримую лише 404 сторінки.

Якщо я роблю так, як робить Гевін, я трохи змінив вашу функцію, щоб також видалити "current_page_parent" зі сторінки блогу, як це.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2);
function current_type_nav_class($css_class, $item) {
$post_type = get_query_var('post_type');

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); } );
}

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

}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.