Feb
23
2014

Code to Add a New Menu Item Type

My latest diversion.

The code at this link adds a new meta box on the Appearance>Menu screen. The defaults are Page, Custom, and Category. This particular one adds a divider type. It doesn’t have any code beyond getting the meta box to show. There is a plugin that adds a custom menu item called Dynamic Menu Item that could be edited to see how it pulls it off.

I’m looking mostly for my own curiosity but I was also trying to find out what it would take, or if it was even possible, to add a dynamic menu that shows all the sub-sites in a multi-site install.

The relevant comment says:
I did create the metabox and displays where it should. Code below(the display part is just copied from Custom Link).


//handler for adding dividers
function add_divider_function()
{
	global $_nav_menu_placeholder, $nav_menu_selected_id;
	$_nav_menu_placeholder = 0 > $_nav_menu_placeholder ? $_nav_menu_placeholder - 1 : -1;

	$current_tab = 'create';
	if ( isset( $_REQUEST['customlink-tab'] ) && in_array( $_REQUEST['customlink-tab'], array('create', 'all') ) ) {
		$current_tab = $_REQUEST['customlink-tab'];
	}

	$removed_args = array(
		'action',
		'customlink-tab',
		'edit-menu-item',
		'menu-item',
		'page-tab',
		'_wpnonce',
	);
	?>
	<div class="customlinkdiv" id="customlinkdiv">

			<input type="hidden" value="custom" name="menu-item[<?php echo $_nav_menu_placeholder; ?/>][menu-item-type]" />

		<p id="menu-item-name-wrap">
				<label class="howto" for="custom-menu-item-name">
					<span>< ?php _e('Title'); ?></span>
					<input id="custom-menu-item-name" name="menu-item[<?php echo $_nav_menu_placeholder; ?/>][menu-item-title]" type="text" class="regular-text menu-item-textbox input-with-default-title" title="< ?php esc_attr_e('Leave blank for empty divider'); ?>" />
				</label>
			</p>

		<p class="button-controls">
			<span class="add-to-menu">
				<img decoding="async" class="waiting" src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?/>" alt="" />
				<input type="submit"<?php disabled( $nav_menu_selected_id, 0 ); ?/> class="button-secondary submit-add-to-menu" value="< ?php esc_attr_e('Add a Divider to the Menu'); ?>" name="add-custom-menu-item" id="submit-customlinkdiv" />
			</span>
		</p>

	</div><!-- /.customlinkdiv -->

	< ?php
}

//configure admin menus
function configure_admin_menus()
{
	remove_meta_box('add-category','nav-menus','side');
	add_meta_box('add-divider','Divider','add_divider_function','nav-menus','side', 'default');
}
add_action( 'admin_head', 'configure_admin_menus', 99 );

2 Comments+ Add Comment

  • Another relevant post and snippet.

    What I ended up doing for this, was adding a new post type that was hidden everywhere on the site except the nav menus. I then added just a single entry of that post type type, and hid some of the fields.

    
    < ?php
    
    function navMenuColumns_init() {
        register_post_type('menu_column',
            array(
                'labels' => array(
                    'name'              => __('Menu Columns'),
                    'singular_name'     => __('Menu Column')
                ),
                'supports' => array('title'),
    
                // Doesn't need to be listed most places as it's not a valid content item on it's own
                'public'                => false, // Base setting. More specific settings below
                'exclude_from_search'   => false,
                'publicly_queryable'    => false,
                'show_ui'               => false,
                'show_in_menu'          => false,
                'show_in_nav_menus'     => true,  // The only thing this is used for
                'show_in_admin_bar'     => false,
                'has_archive'           => false,
            )
        );
    
        $_version = (float)get_option('navMenuColumns_version', 0.0);
    
        if ($_version < 1.0) {
            navMenuColumns_install10();
        }
    
        add_action('admin_footer', 'navMenuColumns_adminFooter');
    }
    
    function navMenuColumns_install10() {
        $navMenuPost = wp_insert_post(array(
            'post_type'     => 'menu_column',
            'post_title'    => 'Column',
            'post_status'   => 'publish'
        ), true);
    
        if (!is_wp_error($navMenuPost)) {
            update_option('navMenuColumns_version', 1.0);
        }
    }
    
    function navMenuColumns_adminFooter() {
        ?><script>
            jQuery(document).ready(function($) {
                // Hides most of the fields when editing a Menu Column item.
                $('#menu-to-edit').on('click', 'a.item-edit', function() {
                    var $li = $(this).parents('li.menu-item');
    
                    if ($li.find('.item-type').text() == 'Menu Column') {
                        $li.find('p.description').hide();
                        $li.find('p.link-to-original').hide();
                        $li.find('p.field-move').show();
                    }
                });
            });
        </script>< ?php
    }
    
    add_action('init', 'navMenuColumns_init');
    
    ?>
    

    This allows the user to add this as a normal menu item. This won’t play well with functions that build the menu markup for you, but if you traverse the menu item and build the markup for you, you can target this post type with custom markup.