Как отключить ссылки у родительских пунктов меню?
Я не хочу, чтобы родительские пункты меню моего сайта вели на отдельные страницы. Во-первых, мне не нужны лишние страницы. Во-вторых, эти ссылки усложняют навигацию для мобильных пользователей, которые не могут "навести" курсор на ссылку (чтобы увидеть дочерние элементы).
Лучшим решением было бы отключить ссылки у родительских пунктов меню. Но как это сделать, особенно теперь, когда с выходом WordPress 3.5 плагин Disable Parent Menu Item перестал работать?
Одно из возможных решений можно найти здесь.

Не создавайте фальшивые URL (#
). Это очень плохо для пользователей с программами чтения с экрана: они используют список доступных ссылок для навигации по вашему сайту. То же самое касается ссылок с javascript:
, которые и так не являются элегантной разметкой.
Вам нужно выполнить два шага:
- Пометьте элементы с дочерними элементами до начала работы walker.
- Замените разметку для верхних родительских элементов.
Я буду использовать пустой элемент <a>
здесь, чтобы упростить получение курсора. Вам, вероятно, понадобится что-то подобное в вашей таблице стилей:
.menu > .has-children {
cursor: pointer;
}
Фильтр для пометки родительских элементов взят из этого ответа. Вторая функция просто проверяет наличие этого свойства и проверяет, не является ли сам элемент дочерним.
add_filter( 'wp_nav_menu_objects', 't5_add_has_children_to_nav_items' );
add_filter( 'walker_nav_menu_start_el', 't5_unlink_parent_item', 10, 4 );
/**
* Добавляет свойство 'has_children' к элементам меню
*
* @wp-hook wp_nav_menu_objects
* @param array $items
* @return array
*/
function t5_add_has_children_to_nav_items( $items )
{
$parents = wp_list_pluck( $items, 'menu_item_parent' );
$out = array ();
foreach ( $items as $item )
{
in_array( $item->ID, $parents ) && $item->has_children = TRUE;
$out[] = $item;
}
return $items;
}
/**
* Заменяет разметку верхнего родительского элемента.
*
* @wp-hook walker_nav_menu_start_el
* @param string $item_output
* @param object $item
* @param int $depth
* @param object $args
* @return string
*/
function t5_unlink_parent_item( $item_output, $item, $depth, $args )
{
// не родительский элемент первого уровня
if ( empty ( $item->has_children ) or 0 != $item->menu_item_parent )
return $item_output;
$title = apply_filters(
'the_title',
$item->title,
$item->ID
);
$id = apply_filters(
'nav_menu_item_id',
'menu-item-'. $item->ID,
$item, $args
);
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
$classes[] = 'has-children';
$class_names = join(
' ',
apply_filters(
'nav_menu_css_class',
array_filter( $classes ),
$item,
$args
)
);
$class_names = $class_names
? ' class="' . esc_attr( $class_names ) . '"'
: '';
return "<li$id>$args->before<a class='menu-item has-children'>$title</a>$args->after";
}

Этот ответ лучше моего, но он указывает на фундаментальный недостаток в меню WordPress — для достижения того, что должно быть простой вещью, требуется столько кода :)

@JCL1178 Полагаю, немногие авторы используют верхний уровень без href
. Да и большинство пользовательских тем используют собственный walker в любом случае. Я рассматриваю нативную реализацию как отправную точку, которая работает в большинстве случаев, но не навязывается разработчику.

Спасибо за ваш развернутый ответ, toscho. Видно, что вы вложили в него много труда. На самом деле, в ответе по ссылке, которую я привел, говорится о необходимости удалить символ решетки, так что в ссылке меню ее не будет: она становится ссылкой без href
, то есть без URL, поддельного или иного. Поскольку ваше решение, кажется, также зависит от удаления href
, мне интересно, чем оно лучше для скринридеров. Стоит ли использовать ваш walker?

@JohnK Плагин из той ветки — это, вероятно, худший из возможных способов решения этой проблемы. У вас обязательно возникнут конфликты с другими плагинами, потому что он вызывает wp_print_scripts
второй раз. Это вообще не должно было пройти проверку плагинов... В любом случае, используйте PHP-решение здесь; оно не имеет побочных эффектов, за исключением случаев, когда вы используете плагин с собственным пользовательским walker.

Ссылка была не на плагин, toscho, а на простой, 'ручной' способ замены для создания не кликабельного пункта меню. Кажется, дает тот же эффект, что и ваш код. Хотел бы отдать должное вашей работе, но я могу выбрать ваш ответ как правильный только если вы обоснуете его превосходство над простым способом.

Хороший ответ, и гораздо лучшее решение, чем использование символа решетки в ссылке, как указано в ссылке автора сообщения.

На самом деле, если внимательно прочитать, в том решении предлагается убрать символ решетки, так что в ссылке его не будет.
