Discussion:
Adding new Menu Modules to Wordpress
BenderisGreat
2014-01-29 21:21:39 UTC
Permalink
I have searched around, and have not been able to find the solution myself.
I would like to add a new module of items to the Appearance->Menus page in
the backend.

This is the page:
Loading Image...
<http://codex.wordpress.org/images/c/ca/appearance-menus.png>

Where it says Pages, Links, Categories. Is it possible to add an additional
section there with unique menu items specific to a plugin. The links I
would like to add in a custom module are dynamic, created using rewrite
rules.



--
View this message in context: http://wordpress-hackers.1065353.n5.nabble.com/Adding-new-Menu-Modules-to-Wordpress-tp43267.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
Dobri
2014-01-29 21:33:05 UTC
Permalink
Hi,

Just speaking from experience, I tried to do something like that a couple of months ago and reached pretty much nowhere using multiple approaches. Menu items seem to be semi-hardcoded. What I ended up doing in the end is I used custom links and used their title/link/alt fields as parameters that are parsed by a custom walker. Here's some code if you'd like to look into the idea:

//you need a custom walker class. you can override start_el and a bunch of other methods, look into the definition of Walker_Nav_Menu
class Custom_Walker extends Walker_Nav_Menu
{
function start_el(&$output, $item, $depth=0, $args=array())
{
//If it's a subitem, ignore and revert to regular Walker
if( 0 != $depth )
{
parent::start_el($output, $item, $depth, $args);
}
else
{
//If the title of the thing begins with the word Divider
if(preg_match('/^Divider/',$item->title) == 1)
{
global $wp_query;
//assure proper indentation
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

//open the divider li
$output .= $indent . '<li class="noLink">';

//generate the inside code
$item_output = $args->before;
$item_output .= $args->link_before . apply_filters( 'the_title', $item->attr_title, $item->ID ) . $args->link_after;
$item_output .= $args->after;

//finish it up
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
else
{
parent::start_el($output, $item, $depth, $args);
}
}
}
}

and wherever you render the menu:

$walker = new Custom_Walker();
wp_nav_menu(array('theme_location' => 'rail_menu', …, 'walker' => $walker));

Not very extensible as you might imagine though. The code above adds a little divider element if the title of the custom link begins with Divider. I'd be happy to see someone else offer a better solution, I'd implement it myself right away.

~Dobri
Post by BenderisGreat
I have searched around, and have not been able to find the solution myself.
I would like to add a new module of items to the Appearance->Menus page in
the backend.
http://codex.wordpress.org/images/c/ca/appearance-menus.png
<http://codex.wordpress.org/images/c/ca/appearance-menus.png>
Where it says Pages, Links, Categories. Is it possible to add an additional
section there with unique menu items specific to a plugin. The links I
would like to add in a custom module are dynamic, created using rewrite
rules.
--
View this message in context: http://wordpress-hackers.1065353.n5.nabble.com/Adding-new-Menu-Modules-to-Wordpress-tp43267.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
Nikola Nikolov
2014-01-29 21:37:51 UTC
Permalink
From what I tracked in source for the past couple of minutes is that pretty
much these are just normal meta boxes, just registered for the nav-menu
screen with context set to "side".

I'll do some tests and poke around and come back with any findings.
Hi,
Just speaking from experience, I tried to do something like that a couple
of months ago and reached pretty much nowhere using multiple approaches.
Menu items seem to be semi-hardcoded. What I ended up doing in the end is I
used custom links and used their title/link/alt fields as parameters that
are parsed by a custom walker. Here's some code if you'd like to look into
//you need a custom walker class. you can override start_el and a bunch of
other methods, look into the definition of Walker_Nav_Menu
class Custom_Walker extends Walker_Nav_Menu
{
function start_el(&$output, $item, $depth=0, $args=array())
{
//If it's a subitem, ignore and revert to regular Walker
if( 0 != $depth )
{
parent::start_el($output, $item, $depth, $args);
}
else
{
//If the title of the thing begins with the word Divider
if(preg_match('/^Divider/',$item->title) == 1)
{
global $wp_query;
//assure proper indentation
$indent = ( $depth ) ? str_repeat(
"\t", $depth ) : '';
//open the divider li
$output .= $indent . '<li class="noLink">';
//generate the inside code
$item_output = $args->before;
$item_output .= $args->link_before
. apply_filters( 'the_title', $item->attr_title, $item->ID ) .
$args->link_after;
$item_output .= $args->after;
//finish it up
$output .= apply_filters(
'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
else
{
parent::start_el($output, $item, $depth, $args);
}
}
}
}
$walker = new Custom_Walker();
wp_nav_menu(array('theme_location' => 'rail_menu', ..., 'walker' =>
$walker));
Not very extensible as you might imagine though. The code above adds a
little divider element if the title of the custom link begins with Divider.
I'd be happy to see someone else offer a better solution, I'd implement it
myself right away.
~Dobri
Post by BenderisGreat
I have searched around, and have not been able to find the solution
myself.
Post by BenderisGreat
I would like to add a new module of items to the Appearance->Menus page
in
Post by BenderisGreat
the backend.
http://codex.wordpress.org/images/c/ca/appearance-menus.png
<http://codex.wordpress.org/images/c/ca/appearance-menus.png>
Where it says Pages, Links, Categories. Is it possible to add an
additional
Post by BenderisGreat
section there with unique menu items specific to a plugin. The links I
would like to add in a custom module are dynamic, created using rewrite
rules.
--
http://wordpress-hackers.1065353.n5.nabble.com/Adding-new-Menu-Modules-to-Wordpress-tp43267.html
Post by BenderisGreat
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
Nikola Nikolov
2014-01-29 22:45:59 UTC
Permalink
I was actually able to create a custom meta box, render some sample data in
it, have functional "Select all" link and be able to add the item to the
menu and save it. It seemed like the url parameter of the menu item was not
going through, but I guess you might have to hook to the
'wp_setup_nav_menu_item' filter and correct your items from there. You
might also have to poke around in order to see how things work. I would
suggest looking at the following function:
- wp_nav_menu_item_taxonomy_meta_box<https://github.com/WordPress/WordPress/blob/c944323a4fef0dbfff96662c55c4fdbfc9d548ba/wp-admin/includes/nav-menu.php#L867>-
this renders the taxonomies metabox - so where you would select
categories for instance.

I'm not a 100% sure if the "admin_head-nav-menus.php" action hook is the
correct place to register the meta box, but since the "add_metaboxes" hook
doesn't fire on the nav-menus.php page. Besides in the source(for
/wp-admin/nav-menus.php) the function that registers the meta boxes is
actually just called midst-page I assume that it should work fine.

A lot of the HTML classes and ids are related to some of the
functionality(most notably the select all link and add to menu button), so
if you change one class/id and don't change the related one, things might
stop working. I didn't go through the JS code in order to find what the
correlation is and therefore what the format should be, but I assume for
the add to menu button you want to have it's id be
"submit-{$wrapping_div_id}", where $wrapping_div_id would be the ID of the
div that holds all of your content - in the example code that would be <div
id="my-plugin-div">.

You can see the code here - https://gist.github.com/nikolov-tmw/8698598
From what I tracked in source for the past couple of minutes is that
pretty much these are just normal meta boxes, just registered for the
nav-menu screen with context set to "side".
I'll do some tests and poke around and come back with any findings.
Post by Dobri
Hi,
Just speaking from experience, I tried to do something like that a couple
of months ago and reached pretty much nowhere using multiple approaches.
Menu items seem to be semi-hardcoded. What I ended up doing in the end is I
used custom links and used their title/link/alt fields as parameters that
are parsed by a custom walker. Here's some code if you'd like to look into
//you need a custom walker class. you can override start_el and a bunch
of other methods, look into the definition of Walker_Nav_Menu
class Custom_Walker extends Walker_Nav_Menu
{
function start_el(&$output, $item, $depth=0,
$args=array())
{
//If it's a subitem, ignore and revert to regular Walker
if( 0 != $depth )
{
parent::start_el($output, $item, $depth, $args);
}
else
{
//If the title of the thing begins with the word Divider
if(preg_match('/^Divider/',$item->title) == 1)
{
global $wp_query;
//assure proper indentation
$indent = ( $depth ) ?
str_repeat( "\t", $depth ) : '';
//open the divider li
$output .= $indent . '<li class="noLink">';
//generate the inside code
$item_output = $args->before;
$item_output .=
$args->link_before . apply_filters( 'the_title', $item->attr_title,
$item->ID ) . $args->link_after;
$item_output .= $args->after;
//finish it up
$output .= apply_filters(
'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
else
{
parent::start_el($output, $item, $depth, $args);
}
}
}
}
$walker = new Custom_Walker();
wp_nav_menu(array('theme_location' => 'rail_menu', ..., 'walker' =>
$walker));
Not very extensible as you might imagine though. The code above adds a
little divider element if the title of the custom link begins with Divider.
I'd be happy to see someone else offer a better solution, I'd implement it
myself right away.
~Dobri
Post by BenderisGreat
I have searched around, and have not been able to find the solution
myself.
Post by BenderisGreat
I would like to add a new module of items to the Appearance->Menus page
in
Post by BenderisGreat
the backend.
http://codex.wordpress.org/images/c/ca/appearance-menus.png
<http://codex.wordpress.org/images/c/ca/appearance-menus.png>
Where it says Pages, Links, Categories. Is it possible to add an
additional
Post by BenderisGreat
section there with unique menu items specific to a plugin. The links I
would like to add in a custom module are dynamic, created using rewrite
rules.
--
http://wordpress-hackers.1065353.n5.nabble.com/Adding-new-Menu-Modules-to-Wordpress-tp43267.html
Post by BenderisGreat
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
BenderisGreat
2014-01-31 01:28:16 UTC
Permalink
Great work Nikola! Thank you for taking a look and going out of your way to
provide example source code!



--
View this message in context: http://wordpress-hackers.1065353.n5.nabble.com/Adding-new-Menu-Modules-to-Wordpress-tp43267p43280.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
BenderisGreat
2014-05-22 05:57:15 UTC
Permalink
I have been making use of the code Nikola shared for a few months. Recently
however I need to create tiered menu items. That means generating fake
page_ids for the parent - I am stuck on if this is even possible.

Could it be possible to use a string as the ID rather than an integer? If
that was/is possible then I could use the title field. It does not seem to
work though. So from my testing, it requires a real page_id attached to a
post.

Does anyone know of a way to create a tiered nav_menu_item dynamically,
without creating a real page for each post item?



--
View this message in context: http://wordpress-hackers.1065353.n5.nabble.com/Adding-new-Menu-Modules-to-Wordpress-tp43267p43969.html
Sent from the Wordpress Hackers mailing list archive at Nabble.com.
Loading...