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.

I would like to add a separator to the admin submenu section, NOT in the top level section.

enter image description here

I'm thinking of using javascript and styling to do the job, but I was wondering if there's a more straightforward method such as that when adding a separator to the top level menu section.

I'm still experimenting on this. I will provide my method once I get it working.

[UPDATED]

share|improve this question
3  
Could you expand upon this question? There are administrative menus all over the place. Alsow, what have you tried? What has your research revealed? –  s_ha_dum Feb 1 '13 at 14:24
1  
    
I agree that this is not the best way to ask, but the question itself is pretty tricky and challenging. Therefore answered. –  kaiser Feb 1 '13 at 15:37
    
Thank you for the info... I'll try to improve the question –  gmaggio Feb 2 '13 at 0:08
1  
So, what did you learn from this lesson? Ask your question with as much detail and information as possible, right? –  kaiser Feb 2 '13 at 3:19

5 Answers 5

Add an admin menu separator

Separators, if this question targets this, are the dividers of the admin menu that separate the menu into sections. Per default it's divided into a "publish" and an "administration" area.

Plugin for the rescue

Here's what we're going to have afterwards: A custom separator.

enter image description here

I wrote a pretty simple plugin that I run as mu-plugin. The usage is, as you can see from the example, very easy and fully aligns with the internal API.

// @example
add_action( 'admin_menu', 'add_admin_menu_separator' );
function add_admin_menu_separator()
{
    add_menu_page( '', '', 'read', 'wp-menu-separator', '', '', '10' );
}

Just load this plugin into your mu-plugins or plugins folder and you're ready to go. The plugin will automatically detect that you want to add a separator and transform the added menu item to one.

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: Admin Menu Separator
 * Description: Adds a separator on whatver priority is needed.
 */

add_filter( 'parent_file', 'admin_menu_separator' );
function admin_menu_separator( $parent_file )
{
    $menu = &$GLOBALS['menu'];
    foreach( $menu as $key => $item )
    {
        if (
            in_array( 'wp-menu-separator', $item )
            AND 5 < count( $item )
        )
        {
            $menu[ $key ][2] = 'separator0';
            $menu[ $key ][4] = 'wp-menu-separator';
            unset(
                 $menu[ $key ][5]
                ,$menu[ $key ][6]
            );
        }
    }
    return $parent_file;
}
share|improve this answer
1  
Very nice, great idea for a plugin –  NTL0820 Feb 1 '13 at 17:19
    
@NTL0820 Thanks :) –  kaiser Feb 1 '13 at 18:41
    
Thanks for the answer, but actually I'm looking for a separator on the admin submenu section –  gmaggio Feb 2 '13 at 0:07
    
@GiraldiMaggio Please add a screenshot to your question, else it's impossible to visualize what you want to have. And with screenshot I don't mean, some purple lines drawn over a default admin menu, I actually mean how you finally want to have it in the UI. –  kaiser Feb 2 '13 at 3:20

NOTE: there might be a more appropriate way to do this, however I am just showing you how another plugin approaches this issue.

The plugin in question is s2Member

enter image description here

How they achieve this is by adding a submenu page item to the parent menu item itself;

    add_submenu_page(
        $parent_slug,                //parent menu slug to attach to
        "",                          //page title (left blank)
                                     //menu title (inserted span with inline CSS)
       '<span style="display:block;  
        margin:1px 0 1px -5px; 
        padding:0; 
        height:1px; 
        line-height:1px; 
        background:#CCCCCC;"></span>',
        "create_users",              //capability (set to your requirement)
        "#"                          //slug (URL) shows Hash domain.com/# incase of mouse over
     );

You can find reference to this within the s2Member plugin itself if you want to inspect it at: plugins\s2member\includes\classes\menu-pages.inc.php starting line 138

For reference on add_menu_page function see:

http://codex.wordpress.org/Function_Reference/add_submenu_page

share|improve this answer
    
Yes! This looks like the more straightforward way of doing it. Now we just need to reposition it, I guess. –  gmaggio Feb 2 '13 at 6:57
    
You could adapt what you have already done in your function to reposition the item in the sub menu, alternatively I recommending reading this answer which speaks of the exact topic (positioning sub menu items). Also if you take a look at the file I mention as part of the s2member plugin you will see that the position of their "dividers" is based upon the order in which they are declaring the sub menu items. –  userabuser Feb 2 '13 at 7:13
up vote -1 down vote accepted

[UPDATED]

This is what I had came up with. Below is a sample of how I would do it on the post menu section:

(Thanks to @userabuser for the advice)

function add_submenu_separator( $menu_ord ) {
  global $submenu;

  // Create 'separator' array for submenu
  $submenuSep = Array ('<div class="separator"></div>', 'read', '#');

    // Note: Use 'div' with class 'separator' to use
    //       WP's built-in separator styling

  $offset = 2; // Position of separator

  // Insert separator into POST menu array
  $post = $submenu['edit.php'];               
  $post = array_slice($post, 0, $offset, true) +
          array($submenuSep) +
          array_slice($post, $offset, NULL, true);
  $submenu['edit.php'] = $post;

  return $menu_ord;
}
add_filter( 'custom_menu_order', 'add_submenu_separator' );

This part is not necessary but if you wish to get rid of the a tag on the separator, you may have to use javascript. So, add the following:

// Add the script
function submenu_scripts() {
  wp_enqueue_script('submenu_script', get_template_directory_uri().'/js/submenu_scripts.js', false, null);
}
add_action('admin_enqueue_scripts', 'submenu_scripts', 100);

Here's how the javascript looks like which I named submenu_scripts.js & placed it in a folder called js:

(function($){
    $(document).ready( function() {

        // Remove 'a' tag on submenu separators
        $('a div[class="separator"]').unwrap();

    });
})(jQuery);

Here's how it should look:

enter image description here

share|improve this answer
2  
Seems like a long way to achieve what you want. Why not just include the div in the array, but instead of a div use a span and give it the class="separator"? –  userabuser Feb 2 '13 at 6:55
    
I guess it is, but that's because I wanted to get rid of the a tag from the separator. Including the div in the array is a good idea. The reason I used div is to use WP's built-in styling for the separator. –  gmaggio Feb 2 '13 at 8:05
    
Seems like a lot of code + (maybe non-accessible) javascript for a simple separator. See my answers. –  kaiser Feb 8 '13 at 9:50
    
@kaiser: Thanks for the code. I had tried it. It's not any shorter than mine. In fact, it's a lot more. As in regards to my javascript, firstly, it is optional, as I had stated, to remove the a tag so the separator doesn't become a hyperlink (personal preference). Secondly, how is that 'non-accessible' may I ask? –  gmaggio Feb 10 '13 at 3:32
1  
@GiraldiMaggio My mistake, as I've misread your JS part. About the overall length: I just counted those lines that actually add & modify the separator and it's 19/23, so yours is shorter by 4 lines, but highly specific, while my solution is reusable and can be used multiple times and uses the default core API. And adding another separator takes one additional line only. If you look at the linked Gist, which I updated several times, you'll also see that I don't run it on every pageload (when it's not necessary), so performant wise... –  kaiser Feb 10 '13 at 9:12

Admin menu & submenu separators

After going over it and extending the core API to allow main menu separators in custom positions, I did a quick run through core menu files, dumped the hell out of everything's that in there and found a solution that allows to use the core API also for custom submenu separators.

The result

This is how our menu will look like, after we added the separators.

Admin menu and sub menu separators

To make this happen, simply add a small plugin, or throw this snippet in your plugins file or functions.php. Here's an example plugin. As you can see, you'll have to add the parent page where you want your separator to appear. Then you have to add the identifier wp-menu-separator. You can adjust the visibility for user by changing the read-capability to whatever the other items in this menu have. The 11 is just the priority. Adjust it to wherever you want the separator to appear inside the menu.

<?php
defined( 'ABSPATH' ) OR exit;
/** Plugin Name: Example Admin Menu Separator */

add_action( 'admin_menu', 'add_admin_menu_separator' );
function add_admin_menu_separator()
{
    add_menu_page( '', '', 'read', 'wp-menu-separator', '', '', '21' );
    add_submenu_page( 'edit.php?post_type=page', 'wp-menu-separator', '', 'read', '11', '' );
}

The Plugin itself

Again this plugin can be used as plugin, part of another plugin or (best) as muplugin.

To follow any updates

Please subscribe/star this GitHub Gist. I will post updates only there.

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: Admin Menu Separator
 * Description: Adds a separator on whatver priority is needed.
 */

add_filter( 'parent_file', 'admin_menu_separator' );
function admin_menu_separator( $parent_file )
{
    $menu = &$GLOBALS['menu'];
    $submenu = &$GLOBALS['submenu'];
    foreach( $submenu as $key => $item )
    {
        foreach ( $item as $index => $data )
        {
            // Check if we got the identifier
            if ( in_array( 'wp-menu-separator', $data, true ) )
            {
                // Set the MarkUp, so it gets used instead of the menu title
                $data[0] = '<div class="separator"></div>';
                // Grab our index and temporarily save it, so we can safely overrid it
                $new_index = $data[2];
                // Set the parent file as new index, so core attaches the "current" class
                $data[2] = $GLOBALS['parent_file'];
                // Reattach to the global with the new index
                $submenu[ $key ][ $new_index ] = $data;
                // Prevent duplicate
                unset( $submenu[ $key ][ $index ] );
                // Get back into the right order
                ksort( $submenu[ $key ] );
            }
        }
    }
    foreach( $menu as $key => $item )
    {
        if (
            in_array( 'wp-menu-separator', $item )
            AND 5 < count( $item )
            )
        {
            $menu[ $key ][2] = 'separator0';
            $menu[ $key ][4] = 'wp-menu-separator';
            unset(
                 $menu[ $key ][5]
                ,$menu[ $key ][6]
            );
        }
    }
    return $parent_file;
}
share|improve this answer

CSS Selector Solution:

add a new admin-styles.css file to your theme with:

.wp-submenu a[href="post-new.php?post_type=city"],
.wp-submenu a[href="post-new.php?post_type=region"] {
  border-bottom:1px solid #ccc
}
.wp-submenu li:last-child a {
  border-bottom:none
}

and load the styles

wp_register_style( 'my_admin_styles', trailingslashit( get_template_directory_uri() ) . 'admin-styles.css');
add_action( 'admin_print_styles', 'admin_styles' );

function admin_styles() { wp_enqueue_style( 'my_admin_styles' ); }
share|improve this answer

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.