Code

A Smarter Menu for WordPress

I’ve always thought it would be nice to combine pages and categories all inside one menu, and recently I was looking for a nice way to add subtitles as well. So I thought it would be cool to write my own menu function, to suit my needs.

First off I want to give credit to a couple of posts, on how to add subtitles via custom fields, sadly, each had their separate issue.

In the first post I found by Shantanu you would have to hack classes.php, a WordPress core file (not my cup of tea). The second one by Theme Shaper was lacking one very essential thing, dynamic active classes! (A non-dynamic menu is a non-happy menu).

The second post by Theme Shaper was almost doing what I was looking for so I decided to hack on it. The code was wrapped in a function which I could easily add to any of my themes, and it uses custom fields for the job, easy-peasy:)

I’ve spent a great deal of time figuring out how to do this and finally I came up with a solution that worked, next phase was to add categories and home link, ontop of that, I’ve added some more snacks, for instance you can chose if you want the home link and categories to show up, (with active classes of course) and you can sort the listing. Subtitles for home and categories are fetched from their respective description container. Enjoy!

Currently missing the active class on single blog posts, will fix soon. Also, I’ve included the same behaviour on child-pages but I haven’t tested this. If you need it, please test it and report back;)

Add this code to functions.php in your theme folder and call it with

<?php wp_smart_menu(); ?>
// Smart Menu with Subtitles by Jon Kristian Nilsen - http://jonkristian.no
function wp_smart_menu() {

	$show_home		= "true"; // Show home link true/false.
	$home_first		= "false"; // In a horizontal list, show home first or last depending on the float, true/false.

	$show_cat		= "true"; // Show Categories true/false.
	$cat_first		= "true"; // In a horizontal list, show categories first or last depending on the float, true/false.

	$cat_id			= "1, 9"; // Filter categories by ID, leave blank for all.

	$metakey		= "Description"; // The meta key for your subtitle text.
	$description	= "under"; // Where you want the subtitle over/under link.
	$order			= "desc"; // Set the link order asc/desc.

	global $wpdb;
	$sql = "SELECT p.ID, p.post_title, p.guid, pm.meta_value FROM " . $wpdb->posts . " AS p LEFT JOIN ";
	$sql .= "(SELECT post_id, meta_value FROM " . $wpdb->postmeta . " AS ipm WHERE meta_key = '$metakey') ";
	$sql .= "AS pm ON p.ID = pm.post_id ";
	$sql .= "WHERE p.post_type = 'page' AND p.post_parent = 0 AND p.post_status = 'publish' ";
	$sql .= "ORDER BY p.menu_order $order ";
	$sql .= "LIMIT 0, 10";
	$rows = $wpdb->get_results($sql,OBJECT);

	if($rows) {

		foreach($rows as $row) {

		global $post;
		$home_url = get_bloginfo('home');
		$home_desc = get_bloginfo('description');
		$current_page = $post;
		$page_id = $row->ID;
		$page_url = get_permalink($row->ID);

		echo "\n	<li>\n";

		if ( $show_home == "true" && $home_first == "true" ) {
				if (is_front_page()) {
					echo "		<ul class=\"active\">\n";
				} else {
					echo "		<ul class=\"page_item\">\n";
				}
					echo "			<li class=\"title\"><a href=\"$home_url\">Home</a></li>\n";
					echo "			<li class=\"description\"><p>$home_desc</p></li>";
					echo "\n		</ul>\n";
		}

		if ( $show_cat == "true" && $cat_first == "true" ) {
		$categories = get_categories("include=$cat_id");
			foreach ($categories as $cat) {
			$cat_url = get_category_link( $cat->term_id );

				if ( is_category($cat->cat_name) || is_single() && in_category($cat->cat_name) ) {
					echo "		<ul class=\"active\">\n";
				} else {
					echo "\n		<ul class=\"page_item\">\n";
				}
					echo "				<li class=\"title\"><a href=\"$cat_url\">$cat->cat_name</a></li>\n";
					echo "				<li class=\"description\"><p>$cat->description</p></li>";
					echo "\n		</ul>\n";
			}
		}

		if ( !empty($current_page) ) {
			$_current_page = get_page( $current_page );
		if ( in_array($page_id, (array) $_current_page->ancestors) )
			echo "		<ul class=\"ancestor\">\n";
		if ( $page_id == $current_page )
			echo "		<ul class=\"active\">\n";
		elseif ( $_current_page && $page_id == $_current_page->post_parent )
			echo "		<ul class=\"parent\">\n";
		else
			echo "		<ul class=\"page_item\">\n";
		}

		if ( $description == "over" ) {
			echo "			<li class=\"description\"><p>$row->meta_value</p></li>\n";
			echo "			<li class=\"title\"><a href=\"$page_url\">$row->post_title</a></li>";

		} elseif ( $description == "under" ) {
			echo "			<li class=\"title\"><a href=\"$page_url\">$row->post_title</a></li>\n";
			echo "			<li class=\"description\"><p>$row->meta_value</p></li>";
		}
			echo "\n		</ul>\n";
		}

		if ( $show_cat == "true" && $cat_first == "false" ) {
		$categories = get_categories("include=$cat_id");
			foreach ($categories as $cat) {
		$cat_url = get_category_link( $cat->term_id );
			if ( is_category($cat->cat_name) ) {
				echo "		<ul class=\"active\">\n";
			} else {
				echo "\n		<ul class=\"page_item\">\n";
			}
				echo "				<li class=\"title\"><a href=\"$cat_url\">$cat->cat_name</a></li>\n";
				echo "				<li class=\"description\"><p>$cat->description</p></li>";
				echo "\n		</ul>";
			}
		}

		if ( $show_home == "true" && $home_first == "false" ) {
				if (is_front_page()) {
					echo "		<ul class=\"active\">\n";
				} else {
					echo "		<ul class=\"page_item\">\n";
				}
					echo "			<li class=\"title\"><a href=\"$home_url\">Home</a></li>\n";
					echo "			<li class=\"description\"><p>$home_desc</p></li>";
					echo "\n		</ul>\n";
		}		

		echo "\n	</li>\n";

	}
}
  • Print
  • email
  • Add to favorites
  • RSS
  • Digg
  • Twitter
  • Facebook
  • del.icio.us

17 Responses

Leave a Reply