3

I added a menu item to the Admin Bar that executes some Javascript to show debug information. The problem is that clicking this item also reloads the page. How can I prevent this?

I was trying to speed up my debug & dev stuff and wanted to add a class to my main wrapper div using jQuery.

Step 1:

Add styles to your head

function my_admin_bar_script_def( $script ) {
$script = '
    jQuery(document).ready( function() {
        jQuery("li#wp-admin-bar-showdebug").click( function() {
            jQuery(".wrap").toggleClass("showdebug");
        } )
    } );
';

return print $script;
}
add_action( 'wp_head', 'my_admin_bar_script_def', 11 );

Step 2:

Add a admin bar menu item:

function my_admin_bar_class_switch() {
global $wp_admin_bar;

$wp_admin_bar->add_menu( 
    array( 
         'parent'   => 'theme_options'
        ,'title'    => __( 'showdebug', TEXTDOMAIN )
        ,'href'     => '' // **interesting problem over here**
    ) 
);
}
add_action( 'admin_bar_menu', 'my_admin_bar_class_switch', 70 );

Problem:

Every time you trigger your toggle function you'll fire up the link and reload the page. Therefore you'll get the initial trigger again. Replacing the link is not possible, because in the $args array for the add_menu() function you only define the href and the link will be printed anyway. Filters or hooks? Not available.

4
  • You could move the "Solution" part to an answer, then we can all vote on it - or even add alternative solutions?
    – Jan Fabry
    Apr 8, 2011 at 14:09
  • @Jan Fabry - done. Good idea. Unmarked the answer as solution.
    – kaiser
    Apr 8, 2011 at 14:18
  • I re-wrote the intro so it looks like a real question, and is more likely to attract Google searches for similar problems. If you don't like it, feel free to edit or rollback!
    – Jan Fabry
    Apr 20, 2011 at 20:07
  • @Jan Fabry - No, it's fine.
    – kaiser
    Apr 21, 2011 at 0:57

2 Answers 2

2

If you return false in that Javascript function the click will not be propagated and the page will also not reload.

Even better, you can specify a onclick attribute for a menu item. So you definition would become this:

function my_admin_bar_class_switch( &$wp_admin_bar ) {
    // $wp_admin_bar is passed by reference, you don't need the global var
    $wp_admin_bar->add_menu( 
        array( 
             'parent'   => 'theme_options'
            ,'title'    => __( 'showdebug', AHF_LANG )
            ,'href'     => '' // This can stay empty
            ,'meta'     => array(
                'onclick' => 'jQuery(".wrap").toggleClass("showdebug"); return false;'
            )
        ) 
    );
}
add_action( 'admin_bar_menu', 'my_admin_bar_class_switch', 70 );

In that case you don't need to hook up the onclick event yourself. I see two other possible errors there: wp_head is an action, not a filter, so by returning the script it won't be printed. Also, you depend on showdebug being part of the id, but because you don't specify the ID it is generated from the title. If that string is translated this ID won't stay the same.

5
  • excellent solution. +1. I wrote the code above as an example. In my theme i don't use wp_head(), but some custom filter that is set after a $var that get's printed after the hooked function, so in my case it's fine that way, but i updated the example. Ad ID) Right. Completely oversaw that trap. thanks!
    – kaiser
    Apr 11, 2011 at 7:35
  • @kaiser: Yes, I thought you had some custom way to add that Javascript. You still need to add <script></script> to your current output.
    – Jan Fabry
    Apr 11, 2011 at 7:38
  • yes and the cdata stuff :)
    – kaiser
    Apr 11, 2011 at 7:43
  • i just exchanged my approach with yours and it works like a charm. Thanks a lot. I guess i can mark this as solution.
    – kaiser
    Apr 11, 2011 at 8:03
  • @kaiser: And that's the wonder of using WPSE as a technical blog where you post your answers to your own daily problems: not only can you pro-actively help others, you can even get better solutions from others!
    – Jan Fabry
    Apr 11, 2011 at 8:16
1

Solution:

Simply set 'href' => '#' to link to a not defined anchor to avoid page reloading.

I know this is really simple, but it took me nearly an hour to get on the right track (thinking too much about filters and hooks to modify the output), so here's my share.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.