THE DIGITAL BLOG

Advanced Techniques: The Joomla Parent Menu ItemID

Using Joomla's getMenu() function to apply top-level cascading styling for parent menus.

Posted on March 3, 2010 18 comments

More Articles...

Joomla's ItemID system offers a great way of customizing sites by giving the opportunity to style major parts of a template or page based on the menu links ItemID.

Every menu link in a Joomla website has one; and they are unique to each and every link on your site.

But what if you need to style entire sections of a site based on a handful of top-level (parent) menu items?

This article explores the methodology of styling sub-level pages respective of their common parent menu links.

menusystem

Method 1: Modifying the mod_breadcrumb Module Code

The mod_breadcrumb module is native to Joomla, and by it's core function maintains a trail of menu link hierarchy leading to the current page. This code can be utilized in order to obtain the top-level menu's textual name (rather than an itemID number). This method expands the code further to reformat this text into a usable, readable format which can be used to style a page in an understandable way. It's more code-heavy than method 2, but provides an easier-to-understand output that works in exactly the same way.

Let's first examine the original code:

defined('_JEXEC') or die('Restricted access');

class modBreadCrumbsHelper
{
	function getList(&$params)
	{
		global $mainframe;

		// Get the PathWay object from the application
		$pathway =& $mainframe->getPathway();
		$items   = $pathway->getPathWay();

		$count = count($items);
		for ($i = 0; $i < $count; $i ++)
		{
			$items[$i]->name = stripslashes(htmlspecialchars($items[$i]->name));
			$items[$i]->link = JRoute::_($items[$i]->link);
		}

		if ($params->get('showHome', 1))
		{
			$item = new stdClass();
			$item->name = $params->get('homeText', JText::_('Home'));
			$item->link = JURI::base();
			array_unshift($items, $item);
		}

		return $items;
	}

	function setSeparator($custom = null)
	{
		global $mainframe;

		$lang =& JFactory::getLanguage();

		if ($custom == null) {
			if($lang->isRTL()){
				$_separator = JHTML::_('image.site', 'arrow_rtl.png');
			}
			else{
				$_separator = JHTML::_('image.site', 'arrow.png');
			}
		} else {
			$_separator = $custom;
		}
		return $_separator;
	}
}

We can immediately remove the second part of the code that sets the separator, since we don't need that. Also, since we only need to return the parent item's text, we don't need the loop in place. We shall also use the Application Object since
$global mainframe will be removed in Joomla 1.6, so:

$global mainframe;

Becomes:

$app = &JFactory::getApplication();

Which gives us the completed code below:

class getParentMenuTitle {
	function getList() {
		$getParent = &JFactory::getApplication();
		// Get the PathWay object
		$pathway =& $getParent->getPathway();
		$items = $pathway->getPathWay();
	return $items;
	}
}
$list = getParentMenuTitle::getList();
$count = count($list);
if ($count !== 0) :
	$parentmenu = $list[0]->name;
	$parentmenu = ereg_replace(" ", "-", $parentmenu); // replace spaces with a dash
	$parentmenu = ereg_replace("[^+A-Za-z0-9-]", "", $parentmenu); // strip special characters
	$parentmenu = strtolower($parentmenu); //set name to lowercase
else :
	$parentmenu = "home"; // Set parentmenu to "home" if there are no items
endif;

How To Use The Code

This block of code can be inserted directly into your active template's index.php file before the HTML is started. Remember to enclose the code block in PHP tags. Alternatively you can include it from an external file.

Once working in the template, you can apply the variable $parentmenu to a top-level container to initiate a CSS hook. Where you add this will depend on what you need to influence in the design, but the further up the hierarchy the more things you will be able to affect in the design – for example:

<body id="<?php echo $parentmenu; ?>">

…will allow you to influence the design across the whole template, such as:

body#menu-link-name a {color:red;}

…which will change all links on the page to red for that particular top-level menu link.

Method 2: Using the Jsite Object

This method is by far the simplist of the two methods, and unless you need a more human-readable format for the menu class/ids then it's by far the recommended method of the two. It uses the Jsite object to obtain the parent menu's ItemID and stores it in a variable which can then be applied to any class/id in the template:

$parentmenu = JSite::getMenu()->getActive()->tree[0];

You can obtain the ItemID of any menu links in the pathway by altering the value of tree[0].

How To Use The Code

Again, this code needs to be inserted into the template. The ItemID is stored in the $parentmenu variable, just as it was before, so you can use a similar method to above – but prefix the class/id with something or else you may have problems, for example:

<body id="menuID-<?php echo $parentmenu; ?>">

Why Would You Need To Use Method 1?

The first method could be useful in instances where you (as the developer) might want to pass more control onto someone who is less technically-minded – the class/id names which are generated using this method are very easy to predict, whereas method 2 requires the administrator to lookup the itemID for each menu item that requires styling.

Something to Share?

Have an alternative technique, or have you used this (or something similar) on a site before? Please do share it in the comments.

Many thanks to Gergő Erdősi and Amy Stephen for the code presented in method 2 above.

There are 18 awesome comments...

  1. Tambra Goldhirsh - April 3, 2010 at 1:54 am

    Thanks dude, that is really helpful information, thanks.

  2. Webster - April 6, 2010 at 12:28 am

    Thank You

  3. Josh - April 13, 2010 at 9:34 am

    Could you expand on how to use this technique with children menu items as well?

  4. Dan Luton - April 13, 2010 at 9:45 am

    Hi Josh,

    Depends what you mean.

    If you want to get the current Menu Itemid, you can use:

    $item_id = JRequest::getVar(‘Itemid’);

    Alternatively, you can use the above technique to obtain the parent menu Itemid for a different level:

    $parentmenu = JSite::getMenu()->getActive()->tree[1];

    …which should work. All depends really what it is you’re trying to achieve – this article really focuses on the absolute top-level ID.

    Hope that helps.

  5. Josh - April 13, 2010 at 3:56 pm

    That was exactly what I have been trying to do all morning. Thanks!

  6. TaeV - August 27, 2010 at 5:06 pm

    Thank so much.

  7. Bira - October 2, 2010 at 4:23 pm

    Before the line #15 I have inserted a function I found here http://www.php.net/manual/en/function.strtr.php#90925 to normalize the accented characteres, instead of deleting them. It is nice for those, like me, whose language have accented characteres like á and ó etc. Is there any other way to get the titles already without accents, like an “alias”? And of course thanks!

  8. Dan Luton - October 4, 2010 at 9:39 am

    Hi Bira,

    I have replaced individual special characters before with PHP, so would imagine the same could apply here.

    I think you’d have to define each one individually though, which could be lengthy…I’m not sure of a better way to do it.

    Something like:

    ereg_replace(“á”, “a”, $parentmenu)
    ereg_replace(“ó”, “o”, $parentmenu)

    …should be sufficient.

    Thanks for pointing it out, it’s easy to forget other languages and exceptions such as special characters!

  9. Sam - March 22, 2011 at 11:31 pm

    EXACTLY what I needed. Many thanks!

  10. Philippe - May 11, 2011 at 9:24 pm

    Thanks !
    Really helpfull trick as I was wondering how to find the parent menu itemid.
    Solution 2 works fine and easy to use.
    Exactly what I was searching for 🙂

  11. Dan Luton - May 11, 2011 at 9:43 pm

    Glad it helped! Thanks for posting guys.

  12. ahmad balavipour - October 26, 2011 at 12:24 pm

    thanks alot, very good tutorial

  13. Dolmat - January 16, 2012 at 8:34 am
  14. Ilja - December 17, 2012 at 10:39 pm

    so simple! works great – thanks a lot!

  15. Sanjeev - January 23, 2013 at 11:59 am

    Code replace spaces with “-” what if i want to print “About Us” not as “about-us”

  16. Dan Luton - January 25, 2013 at 9:22 am

    You can just fine-tune the ereg_replace codes in the script to customise the output – however, remember this is for CSS class names, so I’m not sure why keeping the output as “About Us” would be desirable – that would give two separate class names (.About and .Us) applied to the menu links which would quickly become confusing!

  17. rita - October 1, 2013 at 12:29 pm

    Like this, Thanks for posting

  18. Doug Evans - November 19, 2015 at 3:58 pm

    Great information here! I was wondering how I would get the actual title variable from the following:

    $parentmenu = JSite::getMenu()->getActive()->tree[0];

    I get the ID# but how do I convert that to the name/title of the menu item?

    Thanks!!
    Doug

Leave a comment:

I consent to Toolbox Digital collecting and storing my data from this form, as detailed in the Privacy Notice.

Previous:

Next up: