wp_page_menu forward compatibility with wp_nav_menu

You’ve styled your wordpress menu’s like the following:

#site-navigation li.menu-item-has-children {
    position: relative;
}

#site-navigation ul.sub-menu {
    position: absolute;
    min-width: 100%;
    top: 100%;
    left: 0;
}
/* etcetera etcetera */

However, when you’ve not set a menu for your menu locations, dropdowns no longer work, current menu items are no longer styled, etcetera, etcetera. How do we fix it?

wp_page_menu() doesn’t use the recommended classes (like sub-menu, current-menu-item, current-menu-parent, etcetera). wp_page_menu() does supply us with other classes using underscores (page_item, current_page_item, etcetera).

Luckily we can fix this with the wp_page_menu filter. Below code runs on wp_page_menu output if it was called from wp_nav_menu (it checks theme_location argument from the wp_nav_menu() call). It first inserts spaces for each class attribute so no partial classnames are replaced.

/**
 * Fix page menu classes.
 *
 * @param string $menu HTML output of the page menu.
 * @param array The arguments passed to wp_page_menu().
 * @return string
 */
function my_theme_page_menu($menu, $args)
{
    if (isset($args['theme_location'])) {
        $replace = array(
            '@<li\s+>@i'                         => '<li>', // replace space in li without attributes
            '@class=[\'"]\s*([^\'"]+)\s*[\'"]@i' => 'class=" $1 "', // add a space inside class attribute so we can replace safely.
            '@ page_item @'                      => ' page_item menu-item ',
            '@ page_item_has_children @'         => ' page_item_has_children menu-item-has-children ',
            '@ children @'                       => ' children sub-menu "',
            '@ current_page_item @'              => ' current_page_item current-menu-item ',
            '@ current_page_parent @'            => ' current_page_parent current-menu-parent ',
            '@ current_page_ancestor @'          => ' current_page_ancestor current-menu-ancestor ',
            '@class="\s+([^"]+)\s+"@i'           => 'class="$1"' // replace beginning and end spaces.
        );
        $menu = preg_replace(array_keys($replace), array_values($replace), $menu);
    }

    return $menu;
}

add_filter('wp_page_menu', 'my_theme_page_menu', 10, 2);

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd met *