Как отключить ссылки у родительских пунктов меню?
Я не хочу, чтобы родительские пункты меню моего сайта вели на отдельные страницы. Во-первых, мне не нужны лишние страницы. Во-вторых, эти ссылки усложняют навигацию для мобильных пользователей, которые не могут "навести" курсор на ссылку (чтобы увидеть дочерние элементы).
Лучшим решением было бы отключить ссылки у родительских пунктов меню. Но как это сделать, особенно теперь, когда с выходом 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
@JCL1178 Полагаю, немногие авторы используют верхний уровень без href. Да и большинство пользовательских тем используют собственный walker в любом случае. Я рассматриваю нативную реализацию как отправную точку, которая работает в большинстве случаев, но не навязывается разработчику.
fuxia
Спасибо за ваш развернутый ответ, toscho. Видно, что вы вложили в него много труда. На самом деле, в ответе по ссылке, которую я привел, говорится о необходимости удалить символ решетки, так что в ссылке меню ее не будет: она становится ссылкой без href, то есть без URL, поддельного или иного. Поскольку ваше решение, кажется, также зависит от удаления href, мне интересно, чем оно лучше для скринридеров. Стоит ли использовать ваш walker?
JohnK
@JohnK Плагин из той ветки — это, вероятно, худший из возможных способов решения этой проблемы. У вас обязательно возникнут конфликты с другими плагинами, потому что он вызывает wp_print_scripts второй раз. Это вообще не должно было пройти проверку плагинов... В любом случае, используйте PHP-решение здесь; оно не имеет побочных эффектов, за исключением случаев, когда вы используете плагин с собственным пользовательским walker.
fuxia
Ссылка была не на плагин, toscho, а на простой, 'ручной' способ замены для создания не кликабельного пункта меню. Кажется, дает тот же эффект, что и ваш код. Хотел бы отдать должное вашей работе, но я могу выбрать ваш ответ как правильный только если вы обоснуете его превосходство над простым способом.
JohnK
Хороший ответ, и гораздо лучшее решение, чем использование символа решетки в ссылке, как указано в ссылке автора сообщения.
gteh
На самом деле, если внимательно прочитать, в том решении предлагается убрать символ решетки, так что в ссылке его не будет.
JohnK