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> ';
Display clean php code for copying
// 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('
- ';
// 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".'
- '.$post->post_title.' '; } $postlist .= "\n".'
- '.$catmenu.'
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'); } } } }); }
Display clean javascript code for copying
// 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');
}
}
}
});
}