How to display the title for each menu item in a span attribute

I'm trying to add a CSS hover effect to my theme's main menu and the effect is based on an attribute passed in

I'm trying to add a CSS hover effect to my theme's main menu and the effect is based on an attribute passed in a <span> element. The problem is that I am unable to produce this dynamically with the title of each menu item. Here is the HTML that I would like to produce:

<nav>
    <a href="#"><span data-hover="Home">Home</span></a>
    <a href="#"><span data-hover="About">About</span></a>
    <a href="#"><span data-hover="Contact">Contact</span></a>
</nav>

Now in WP I tried adding the link_before and link_after attribute in order to add the <span> element but I'm not sure how to produce the title for each menu item for the "data-hover" attribute. Any help would be highly appreciated.

I'm trying to add a CSS hover effect to my theme's main menu and the effect is based on an attribute passed in a <span> element. The problem is that I am unable to produce this dynamically with the title of each menu item. Here is the HTML that I would like to produce:

<nav>
    <a href="#"><span data-hover="Home">Home</span></a>
    <a href="#"><span data-hover="About">About</span></a>
    <a href="#"><span data-hover="Contact">Contact</span></a>
</nav>

Now in WP I tried adding the link_before and link_after attribute in order to add the <span> element but I'm not sure how to produce the title for each menu item for the "data-hover" attribute. Any help would be highly appreciated.

Share Improve this question edited Sep 20, 2013 at 17:05 Mayeenul Islam 12.9k21 gold badges85 silver badges169 bronze badges asked Sep 20, 2013 at 15:52 Daem0nDaem0n 112 silver badges5 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

When calling the wp_nav_menu() function you can pass the <span> tags in the link_before y link_after arguments:

wp_nav_menu(array('link_before' = > '<span>', 'link_after' => '</span>'));

To have differents attributes in the span for each menu item you may need to use a custom nav_walker. For example, the next custom Nav_Walker is the default from Wordpress, I've just modified it to add the <span> with the data-hover attribute:

//First, define the callback when displaying the menu
<nav>
    <?php wp_nav_menu( array( 
            'container'       => '',
            'container_class' => '',
                'theme_location'  => 'topmenu',
            'menu_class'      => 'nav',
                'fallback_cb'      => '',
            'walker' => new Custom_Walker(),
                     ) );
?>

The custom nav walker, in this case Custom_Walker must be in functions.php or included in it:

class Custom_Walker extends Walker_Nav_Menu {
/**
 * @see Walker::$tree_type
 * @since 3.0.0
 * @var string
 */
var $tree_type = array( 'post_type', 'taxonomy', 'custom' );

/**
 * @see Walker::$db_fields
 * @since 3.0.0
 * @todo Decouple this.
 * @var array
 */
var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );

/**
 * @see Walker::start_lvl()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param int $depth Depth of page. Used for padding.
 */
function start_lvl( &$output, $depth = 0, $args = array() ) {
    $indent = str_repeat("\t", $depth);
    $output .= "\n$indent<ul class=\"sub-menu\">\n";
}

/**
 * @see Walker::end_lvl()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param int $depth Depth of page. Used for padding.
 */
function end_lvl( &$output, $depth = 0, $args = array() ) {
    $indent = str_repeat("\t", $depth);
    $output .= "$indent</ul>\n";
}

/**
 * @see Walker::start_el()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param object $item Menu item data object.
 * @param int $depth Depth of menu item. Used for padding.
 * @param int $current_page Menu item ID.
 * @param object $args
 */
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
    $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

    $class_names = $value = '';

    $classes = empty( $item->classes ) ? array() : (array) $item->classes;
    $classes[] = 'menu-item-' . $item->ID;

    $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
    $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';

    $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
    $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';

    $output .= $indent . '<li' . $id . $value . $class_names .'>';

    $atts = array();
    $atts['title']  = ! empty( $item->attr_title ) ? $item->attr_title : '';
    $atts['target'] = ! empty( $item->target )     ? $item->target     : '';
    $atts['rel']    = ! empty( $item->xfn )        ? $item->xfn        : '';
    $atts['href']   = ! empty( $item->url )        ? $item->url        : '';

    $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args );

    $attributes = '';
    foreach ( $atts as $attr => $value ) {
        if ( ! empty( $value ) ) {
            $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
            $attributes .= ' ' . $attr . '="' . $value . '"';
        }
    }

    $item_output  = $args->before;
    $item_output .= '<a'. $attributes .'>';
    $item_output .= $args->link_before;
            // HERE are your <span> tags
            $item_output .= '<span data-hover="'.esc_attr($item->title).'">';
            $item_output .= apply_filters( 'the_title', $item->title, $item->ID );
            $item_output .= '</span>';
            $item_output .= $args->link_after;
    $item_output .= '</a>';
    $item_output .= $args->after;

    $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}

/**
 * @see Walker::end_el()
 * @since 3.0.0
 *
 * @param string $output Passed by reference. Used to append additional content.
 * @param object $item Page data object. Not used.
 * @param int $depth Depth of page. Not Used.
 */
function end_el( &$output, $item, $depth = 0, $args = array() ) {
    $output .= "</li>\n";
}
}

Or maybe better (or not, I'm not sure because it needs a query foreach menu item via the get_post() function if we want to run the filter only for the title of menus and not to all post titles), use the_title filter hook (see toscho answer for a better way to use the_title filter hook if you decide to use this filter instead the custom nav-walker):

function add_span_to_menu($title, $id) {

    //Run this function only for nav_menu_item post types
    $item = get_post( $id );
    if($item->post_type != 'nav_menu_item') return;

    $title = '<span data-hover="'.esc_attr($title).'">'.$title.'</span>';

    return $title;

}
add_filter('the_title', 'add_span_to_menu', 10, 2);

You can filter the nav menu item’s title with the_title.

// from wp-includes/nav-menu-template.php, Walker_Nav_Menu::start_el()
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;

Unfortunately, this filter is used on many other places too, so you have to turn on the filter as late as possible, and you should turn it off when the items have been parsed.

Sample, code, not tested:

// turn it on
add_filter( 'wp_nav_menu_objects', function( $items )
{
    add_filter( 'the_title', 'change_nav_title' );
    return $items;
});
// turn it off
add_filter( 'wp_nav_menu', function( $nav_menu )
{
    remove_filter( 'the_title', 'change_nav_title' );
    return $nav_menu;
});

// change the title
function change_nav_title( $title )
{
    return sprintf(
        '<span data-hover="%1$s">%2$s</span>',
        esc_attr( $title ),
        $title
    );
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742348147a4426967.html

相关推荐

  • How to display the title for each menu item in a span attribute

    I'm trying to add a CSS hover effect to my theme's main menu and the effect is based on an attribute passed in

    2小时前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信