Make wordpress menu
23 Ⅵ 2010
I was not entirely happy with the way wordpress handles menus for this (my own) website. I like the idea of making all the content posts so they're bound to a date and such. Then I'd like to see them in the menu based on the category they're in. There are category menus, and even nice folding ones, but I couldn't find one that displays all the posts per category in a nice way.
So I decided to hack one in myself. It's a very nasty hack... and I just put a bunch of code in the sidebar.php of my template. But that said… it works and I now have a menu that does what I want.
If you'd like to use this... just remember it's a great big bad hack and very inefficient!
Here's the html/php code I added to my template's sidebar.php:
// Get the id of the current post so we can give it a "current" class later.
$postid = $post->ID;
// Arguments for getting all the categories
$args = array(
'show_option_all' => '',
'orderby' => 'name',
'order' => 'ASC',
'show_last_update' => 0,
'style' => 'list',
'show_count' => 0,
'hide_empty' => 1,
'use_desc_for_title' => 0,
'child_of' => 0,
'feed' => '',
'feed_type' => '',
'feed_image' => '',
'exclude' => '',
'exclude_tree' => '',
'include' => '',
'hierarchical' => true,
'title_li' => '',
'number' => NULL,
'echo' => 0,
'depth' => 0,
'current_category' => 1,
'pad_counts' => 0,
'taxonomy' => 'category' );
// Get all categories (in a silly html menu)
$catmenu = wp_list_categories( $args );
// Split the menu to get all categories sepparately
$cats = split('<li class="cat-item cat-item-', $catmenu);
$catmenu = '';
// Loop through the categories.
foreach($cats as $key => $cat){
$current = '';
// Get the code and html sepparately
list($id, $code) = split('"><a', $cat);
// Make sure they're there.
if($id && $code){
// If this is the current category, then remove that text and remember for later
if(strpos($id, ' current-cat') !== False){
$current = ' current-cat';
$id = str_replace(' current-cat', '', $id);
}
// In case we got an id... and this category doesn't have sub categories.
if(is_numeric($id) && strpos($code, "<ul class='children'>") === False){
// Arguments for getting the categorie's posts
$args = array(
'post_type' => 'post',
'post_status' => 'published',
'numberposts' => -1,
'category' => $id
);
// Get the posts
$myposts = get_posts($args);
// If we got any posts returned
if(count($myposts)){
// Start a nice html post list
$postlist = "\n".'<ul class="posts">';
// Check east post to see if it's current and add to the html
foreach($myposts as $post) {
$current_post = '';
if($postid == $post->ID){
$current_post = ' class="current-post"';
$current = ' current-cat';
}
$postlist .= "\n".' <li'.$current_post.'><a href="'.get_permalink($post->ID).'">'.$post->post_title.'</a></li>';
}
$postlist .= "\n".'</ul>';
// Add the post list to the code of the current category
$code = str_replace('</a>', '</a>'.$postlist, $code);
}
}
// Put everything that was split before back together
$cat = '<li class="cat-item cat-item-'.$id.$current.'"><a'.$code;
}
// Add back into the complete category menu
$catmenu .= $cat;
}
// Print out the category menu
echo '<li id="menu"><ul>'.$catmenu.'</ul></li>';
And here is the javascript code I added to my template’s header.php:
// Initialise javascript functions using jquery
jQuery(document).ready(function(){
initMenu();
});
// Start the menu functionality
function initMenu(){
// Hide all the submenus by default
jQuery('#menu ul ul').hide();
// Find the current post and make sure all the categories it's in are also "current", then show their kids.
jQuery('#menu .current-post').parents('li[id!=menu]').addClass('current-cat').children('ul').show();
// Replace the click event of all category menu items except for "news"
// In stead make them fold down and up the sub menu
jQuery('#menu a').click(function(event){
thisItem = jQuery(this);
childList = thisItem.siblings('ul');
if(childList.length){
if(!(thisItem.html() == 'News' && childList.is(':hidden'))){
event.preventDefault();
if(childList.is(':hidden')){
thisItem.addClass('clicked');
childList.slideDown('fast');
jQuery('#menu ul:visible').each(function(){
if(!(jQuery('.clicked', this).length || jQuery(this).siblings('.clicked').length)){
jQuery(this).slideUp('fast');
}
});
thisItem.removeClass('clicked');
}else{
childList.slideUp('fast');
}
}
}
});
}