Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Short Version:

Custom menu with a custom post type that supports a custom taxonomy. The custom post type works, the menu for it works and stays open. The custom taxonomy works, but the sidebar menu doesn't stay open. I need to make the category keep the submenu open, as it does natively (when not placed in another menu).

Long version:

I've got a custom menu created with add_menu_page:

add_menu_page(
  'Directory',           // Page Title
  'Directory',           // Menu Title
  'manage_options',      // Capability
  'directory',           // Slug
  null,                  // Rendering Function
  'div'                  // Menu Icon (or "div" for CSS)
);

I have also created a custom Post Type and a custom Taxonomy. I want to make these appear within my custom menu, which according to the show_in_menu argument (See wiki, can't post the link), this should be supported natively.

However, it simply does not work correctly. True, this option does stick the "Manage Directory" link into my custom menu, but it does not move the "Add Contact" or "Directory Categories (Custom taxonomy)" links into the menu.

Here are a few previews:

Custom Menu: http://radleygh.com/images/chrome_2013-114-14-14-16-91.png

Default Menu: http://radleygh.com/images/chrome_2013-114-14-14-53-25.png

As you can see, the Default Menu has three links. I need to move all of these to my custom men (Where I will be adding submenus).

One trick I learned awhile back is that you can create submenus for existing pages, and they will behave as if they are the real menu. At least, this works for most things. It does not work with my taxonomy. See the code below:

add_submenu_page( // Manage Directory
  'directory',
  'Manage Directory',                  // Page Title
  'Manage Directory',                          // Menu Title
  'manage_options',                    // Capability
  'edit.php?post_type=directory_post'  // Slug
);
add_submenu_page( // Add Contact
  'directory',
  'Add Contact',                            // Page Title
  'Add Contact',                            // Menu Title
  'manage_options',                         // Capability
  'post-new.php?post_type=directory_post'   // Slug
);
add_submenu_page( // Categories
  'directory',
  'Categories',                             // Page Title
  'Categories',                             // Menu Title
  'manage_options',                         // Capability
  'edit-tags.php?taxonomy=directory_category&post_type=directory_post'  // Slug
);

The above code gives me the links I want, and the "slug" for each is smart enough to point to the correct pages. In fact, it's as if the links are the native ones. But of course, they aren't.

The problem though, is that for some reason the "Categories" link alone does not keep the menu open. The others do.

I believe the issue is that the taxonomy does not support the "show_in_menu" argument. Even though the argument is "broken" as I explained above, it does at least keep the menu open.


Here is the definition for the directory post type and taxonomy, in full

// Register the post type and custom category (aka taxonomy)
function dir_register_directory() {
  $args = array(
    'labels' => array(
          'name' => 'Directory Listings',
          'singular_name' => 'Directory Listing',
          'add_new' => 'Add Contact',
          'add_new_item' => 'Add New Contact',
          'edit_item' => 'Edit Contact',
          'new_item' => 'New Contact',
          'all_items' => 'Manage Directory',
          'view_item' => null, // Don't need to view these
          'search_items' => 'Search Directory',
          'not_found' =>  'No contacts found',
          'not_found_in_trash' => 'No contacts found in Trash', 
          'parent_item_colon' => '',
          'menu_name' => 'Directory'
        ),
    'capability_type'     => 'post',
    'hierarchical'        => false,

    'public'              => true,
    'show_in_menu'        => 'directory', // Nest the link under custom menu
    'show_in_nav_menus'   => false, // Do NOT show these listings under Appearance > Menus

    'publicly_queryable'  => false, // Will not show up in search results
    'query_var'           => false, // Cannot access via ?{query_var}=
    'rewrite'             => false, // Entries should not be accessed by URL

    'has_archive'         => 'directory_category', // Use our custom taxonomy
    'menu_position'       => 1,  // Should be on top of the parent menu's list
    'supports'            => array(
          'page-attributes', // Used for Sort Order
        )
   );
   register_post_type( 'directory_post', $args );

  // Create a custom category section for the Directory page
  register_taxonomy(
    'directory_category',
    'directory_post',
    array(
      'rewrite' => false,
      'hierarchical' => true,
      'sort' => true,
      'public' => true,
      'show_in_nav_menus'   => false, // Do NOT show these listings under Appearance > Menus
    )
  );

  register_taxonomy_for_object_type( 'directory_category', 'directory_post' );
}
add_action('init', 'dir_register_directory');
share|improve this question
    
I'm rather confused as to what you are doing here. Why are you creating menus independently? You could have these created automatically when you register your post type. This would eliminate your 'categories' issue entirely. Am I missing something? –  vancoder Apr 24 '13 at 22:07
    
There will be many more links within that menu, including at least one other custom post type. I would prefer to keep my plugin as one menu and would like to have control over it, rather than creating at least three separate primary menus. –  RadGH Apr 24 '13 at 22:29
    
This kind of relates. –  vancoder Apr 24 '13 at 22:56
add comment

1 Answer 1

up vote 1 down vote accepted

I could not find a built-in way to accomplish this solution, but I have created a workaround

I realized, if the menu won't stay open, why not open it myself?

I created the following two functions, which are easy enough to understand. They need to be called in a javascript file which is loaded via admin script (see the function wp_enqueue_script and the action hook admin_enqueue_scripts).

Usage:

jQuery(function() {
  // Deactivate all currently active menus
  wp_deactivate_menus();

  // Activate the parent menu with an id #menu-pages, as well as the submenu item with
  // the specific slug "edit.php?post_type=page"
  wp_activate_menu('#menu-pages', 'edit.php?post_type=page');
});

Functions:

// Deactivate all active / expanded Wordpress menus
function wp_deactivate_menus() {
  var $sidebar = jQuery("#adminmenu");
  var $active_menus = $sidebar.children('li.current, li.wp-has-current-submenu, li.wp-menu-open');

  // Close all open menus
  $active_menus.each(function() {
    var $this = jQuery(this);

    // Conditional classes
    if ($this.hasClass('wp-has-current-submenu')) 
      $this.addClass('wp-not-current-submenu');

    // Unconditional classes
    $this
      .removeClass('current')
      .removeClass('wp-menu-open')
      .removeClass('wp-has-current-submenu')
      .addClass('wp-not-current-submenu');

    // Remove "current" from all submenu items, too
    $this.find('ul.wp-submenu li a.current').removeClass('current');
  });
}

// Activate a Wordpress menu and optionally highlight a submenu slug within that category
// menu_id = String, such as "#my-menu-id". (Not necessarily an ID, but a selector to select the <li>) 
// slug = String, such as "edit.php?post-type=page". Must be exactly the same href as the submenus a[href]
function wp_activate_menu( menu_id, slug ) {
  var $sidebar = jQuery("#adminmenu");
  var $menu = $sidebar.find( menu_id );

  if (!$menu || $menu.length < 1) return false;

  // Conditional classes
  if ($menu.hasClass('wp-has-submenu'))
    $menu.addClass('wp-has-current-submenu');

  // Unconditional classes
  $menu
    .addClass('current')
    .addClass('wp-menu-open')
    .removeClass('wp-not-current-submenu');

  if (typeof slug == 'undefined') return;

  // Begin activating the submenu
  var $submenu = $menu.find('a[href="' + slug + '"]');

  if (!$submenu || $submenu.length < 1) return;

  $submenu.parent('li').addClass('current');
}

A little extra

This code can activate a wordpress menu. Any menu. However, it does not check if it should activate the menu. Do that yourself. I used the following if statement:

// getParameterByName function provided by:
// http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values
if (
  getParameterByName('taxonomy') == 'directory_category'
  && getParameterByName('post_type') == 'directory_post'
)
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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