WordPress’ new menu system is both wondrous and infinitely frustrating, depending on what you are trying to do and what day of the week it happens to be. 🙂 It’s a great idea but far from mature so while it’s a feature I applaud I’ll be happier when v3.3 or v3.4 of WordPress rolls out and we get a lot more use-cases directly supported by the menu system’s API.
That said, not sure if there is an existing plugin to do what you are looking for, but how about the code you need to write you own plugin? Or you could just include it in your theme’s functions.php
file; whatever your preference.
What I’m providing is a fully self-contained example that you can save as test.php
in your website’s root directory in order to test it. If your domain were example.com
you’d load to test at:
http://example.com/test.php
Here’s what it look’s like in action:
(source: mikeschinkel.com)
(source: mikeschinkel.com)
From the code below it should be easy to incorporate the get_page_selector()
function into your theme and to call it whenever you need this functionality:
<?php
include "wp-load.php";
echo 'Jump to:';
echo get_page_selector('My Select Menu');
function get_page_selector($menu) {
$page_menu_items = wp_get_nav_menu_items($menu,array(
'meta_key'=>'_menu_item_object',
'meta_value'=>'page',
));
$selector = array();
if (is_array($page_menu_items) && count($page_menu_items)>0) {
$selector[] =<<<HTML
<select id="page-selector" name="page-selector"
onchange="location.href = document.getElementById('page-selector').value;">
HTML;
$selector[] = '<option value="">Select a Page</option>';
foreach($page_menu_items as $page_menu_item) {
$link = get_page_link($page_menu_item->object_id);
$selector[] =<<<HTML
<option value="{$link}">{$page_menu_item->title}</option>
HTML;
}
$selector[] = '</select>';
}
return implode("\n",$selector);
}
So you might wonder how it works?
The wp_get_nav_menu_items()
function
WordPress 3.0 stores it’s menus in the wp_posts
table as post_type
type of nav_menu_item
. The wp_get_nav_menu_items()
indirectly just calls the get_posts()
function. The first parameter to wp_get_nav_menu_items()
is either 1.) a menu name (which is what I used: “My Select Menu”), 2.) a menu item ID (i.e. the menu item’s post ID
the database) or 3.) a menu slug (the slug from the menu’s taxonomy term; yes menus are implemented using taxonomy terms with a taxonomy of 'nav_menu'
.)
(source: mikeschinkel.com)
Beyond the first parameter it forwards on to get_posts()
most (if not all?) of the $args
you pass to wp_get_nav_menu_items()
thus you can treat it like a custom post type (even though longer term when they improve the menu API that probably won’t be such a great idea. But today? Make hay while the sun shines!)
Filtering Menu Items with meta_key
and meta_value
WordPress’ underlying use of posts for menu items is why we can query for meta_key
and meta_value
; WordPress uses a series of meta_keys
prefixed with _menu_item
for the additional information it needs for each menu item. _menu_item_object
will contain page
for every menu item that corresponds to a WordPress “Page” post type. (If you want to include items besides Pages you you’ll need to do a bit more research than I did here but at least I gave you the tools you need to do the research yourself.)
Here’s a screenshot using Navicat for MySQL of a query showing the meta records for several nav_menu_items
:
(source: mikeschinkel.com)
Grabbing the Page’s URL with get_post_link()
Next I’ll point out that get the page’s URL from the get_post_link()
function and that I’m setting the HTML <option>
‘s value
to be the URL…
<?php
$link = get_page_link($page_menu_item->object_id);
$selector[] =<<<HTML
<option value="{$link}">{$page_menu_item->title}</option>
HTML;
Using Javascript’s onchange
to Navigate to our Selected Page
…So that I can grab it from the value
property of the 'page-selector'
<select>
element and assign it to location.href
. Assigning location.href
causes the browser to immediately navigate to the new URL, and that, in a nutshell, is how it’s all done:
<?php
$selector[] =<<<HTML
<select id="page-selector" name="page-selector"
onchange="location.href = document.getElementById('page-selector').value;">
HTML;
An Empty value=""
as the Default Option
You might note that the “Select a Page” default option has an empty value; that’s not a mistake but instead by design. When it is selected and the "onchange"
is triggered1 setting location.href
to an empty string will have no effect, which is exactly what we want and it doesn’t require us to write an exception code. Viola!
<?php
$selector[] = '<option value="">Select a Page</option>';
- Having selection of “Select a Page” trigger
"onchange"
can only happen on a browser back navigation to a page that doesn’t trigger a page reload where another option had previously been selected, but it can still happen so we should address it.