Introducing Hierarchical Menu in TYPO3

Exclusive offer: get 50% off this eBook here
TYPO3 Templates

TYPO3 Templates — Save 50%

Create and modify templates with TypoScript and TemplaVoila

$26.99    $13.50
by Jeremy Greenawalt | November 2010 | Open Source

In this article, by Jeremy Greenawalt, author of TYPO3 Templates, we will:

  • Learn about the base hierarchical menu object in TYPO3: HMENU
  • Get introduced to the text-based menu object
  • Rebuild the main menu and submenu from scratch with fancy text-based menu options

 

TYPO3 Templates

TYPO3 Templates

Create and modify templates with TypoScript and TemplaVoila

  • Build dynamic and powerful TYPO3 templates using TypoScript, TemplaVoila, and other core technologies.
  • Customize dynamic menus, logos, and headers using tricks you won’t find in the official documentation.
  • Build content elements and template extensions to overhaul and improve TYPO3’s default back-end editing experience.
  • Follow along with the step-by-step instructions to build a site from scratch using all the lessons in the book in a practical example.
        Read more about this book      

(For more resources on this subject, see here.)

Page tree concepts

We are about to dive into all of the little details, but there are a few basic concepts that we need to review first. So, we're going to make sure we have a more complete definition that avoids any confusion:

  • Page tree: Our TYPO3 page tree is all of the pages and folders that we work with. This includes the home page, about us, subpages, and even non-public items such as the storage folder in our example site. If we have a very simple website it could look like this:
    • Home
    • About Us
    • Staff
  • Level: Our page tree will almost always have pages, subpages, and pages under those. In TYPO3, these are considered levels, and they increase as you go deeper into the page tree. For example, in our extremely simple website from the example above both Home and About Us are at the base (or root) of our page tree, so they are on level 0. The staff page is underneath the About Us page in the hierarchy, so it is on level 1. If we added a page for a photo gallery of our last staff lunch as a subpage to the staff page, then it would be at level 2:
    • Home (Level 0)
    • About Us (Level 0)
    • Staff (Level 1)
    • Staff Lunch Gallery (Level 2)
  • Rootline: TYPO3 documentation actually has a few different uses for the term "rootline", but for the menu objects it is the list of pages from your current page or level moving up to the root page. In our example above, the current rootline from the Staff Lunch Gallery is Staff Lunch Gallery | Staff| About Us

Introduction

Before we look at all the different kinds of menus in TYPO3 and all their little differences, we need to explore the base TypoScript object for all of them: HMENU. HMENU generates hierarchical menus, and everything related to menus in TYPO3 is controlled by it. As the base object, HMENU is the one thing that every type of menu is guaranteed to have in common. If we understand how HMENU is creating its hierarchical menu, then everything else is just styling.

We can already see an example of HMENU being used in our own TypoScript template setup by looking at the menus that the TemplaVoila Wizard generated for us:

## Main Menu [Begin]
lib.mainMenu = HMENU
lib.mainMenu.entryLevel = 0
lib.mainMenu.wrap = <ul id="menu-area">|</ul>
lib.mainMenu.1 = TMENU
lib.mainMenu.1.NO {
allWrap = <li class="menu-item">|</li>
}
## Main Menu [End]

## Submenu [Begin]
lib.subMenu = HMENU
lib.subMenu.entryLevel = 1
lib.subMenu.wrap = <ul id="submenu-area">|</ul>
lib.subMenu.1 = TMENU
lib.subMenu.1.NO {
allWrap = <li class="submenu-item">|</li>
}
## Submenu [End]

We can see that the wizard created two new HMENU objects, lib.mainMenu and lib.subMenu, and assigned properties for the entry level and HTML tags associated with each menu. We're about to learn what those specific properties mean, but we can already use the code from the wizard as an example of how HMENU is created and how properties are defined for it.

Types of menu objects

The HMENU class does not output anything directly. To generate our menus, we must define a menu object and assign properties to it. In our current menus, the TemplaVoila Wizard generated a menu object for each HMENU in the following highlighted lines:


## Main Menu [Begin]
lib.mainMenu = HMENU
lib.mainMenu.entryLevel = 0
lib.mainMenu.wrap = <ul id="menu-area">|</ul>
lib.mainMenu.1 = TMENU
lib.mainMenu.1.NO {
allWrap = <li class="menu-item">|</li>
}
## Main Menu [End]

## Submenu [Begin]
lib.subMenu = HMENU
lib.subMenu.entryLevel = 1
lib.subMenu.wrap = <ul id="submenu-area">|</ul>
lib.subMenu.1 = TMENU
lib.subMenu.1.NO {
allWrap = <li class="submenu-item">|</li>
}
## Submenu [End]

There are a handful of classes for menu objects that can be used by HMENU to generate menus in TYPO3, but we are going to be concentrating on the two most powerful and flexible options: TMENU and GMENU.

The TemplaVoila Wizard used TMENU in our current menu, and it is used to generate text-based menus. Menus built with TMENU output the title of each page in the menu as a text link, and then we can use HTML and CSS to add styling and layout options.

Menus created with the GMENU class are considered graphic menus. We can use GMENU to dynamically generate images from our page titles so that we can use fancy fonts and effects like drop-shadow and emboss that are not supported in CSS by all browsers equally.

Menu item states

The menu system in TYPO3 allows us to define states for different menu options. For example, using the state definitions, we can customize the behavior of menu items when they are active or rolled over. The normal state (NO) is available and set by default, but all of the menu item states must be enabled in TYPO3 by adding code to our template like this: lib.mainMenu.1.ACT = 1. All menu objects share a common set of menu item states from the table below:

HMENU properties

Because HMENU is the root of all of our other menu objects, any of the properties that we learn for HMENU will be applicable to all of our menu options that we might use on future websites. I've included a list of the TypoScript properties that we are most likely to use in the TypoScript template setup, but you can see the complete list in the TSref (http://typo3.org/documentation/document-library/references/doc_core_tsref/current).

If you haven't used TypoScript much, and this is too much information all at once, don't worry. It will make more sense in a few pages when we start experimenting on our own site. Then, this will serve as a great reference.

As we've already witnessed in the main menu, TYPO3 sorts our menu by the order in the page tree by default. We can use this property to list fields for TYPO3 to use in the database query. For example, if we wanted to list the main menu items in reverse alphabetical order, we could call the alternativeSortingField in our template:
lib.mainMenu.1 = TMENU
lib.mainMenu.1.alternativeSortingField = title desc

TYPO3 Templates Create and modify templates with TypoScript and TemplaVoila
Published: November 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on this subject, see here.)

Common menu item properties

We've looked at the menu as a whole, but a lot of our TypoScript configuration revolves around the menu items themselves. Editing all of the menu items in TypoScript is not hard, but it's not completely straightforward. When we are adding TypoScript configuration like HTML tags to all of our menu items, we will always start by assigning them to the normal (NO) state. For example, we haven't talked about the specific properties available yet, but the following TypoScript code will assign a class to all of the menu links:

lib.mainMenu.1 = TMENU
lib.mainMenu.1.NO.ATagParams = class="menu-links"

Here are some of the most common menu item properties that we might use in our TypoScript templates:

Introducing text-based menus

The simplest type of menu is the text-based menu, TMENU, which displays the page titles of menu items as text links. It's the fastest, drop-in solution for any menu, and it's what TemplaVoila created by default. The big advantages for TMENU are speed and flexibility. It's the fastest to implement, but it's also the fastest menu object to render because it's not downloading any special graphics or complex layouts during the loading of our page.

It also means that your design is not tied to the TypoScript template, so you can do all your customization through CSS or even JavaScript libraries. If you're designing for CSS3-compatible browsers and you really know what you're doing, then you can build a very fast menu with custom fonts and effects that degrade gracefully across unsupported browsers without TypoScript. We are going to look at ways to integrate non-web fonts and complex graphic effects using TypoScript because, for those who aren't CSS or JavaScript geniuses already, TypoScript is easier and more flexible. Almost anything is possible, with TMENU, CSS, and JavaScript.

What are the disadvantages? Obviously, the main disadvantage can be appearance. If your designer has handed you a folder of mockups with fancy graphical menus, then they are not going to be impressed with our text-based navigation. If you want fancy buttons, but you're still designing for legacy browsers and graceful degradation (displaying functional but less advanced designs to older browsers) is not an option, you'll need to use GMENU with GIFBUILDER.

If you build enough websites, you will end up using various menus at different times, but TMENU is both a great starting point for new projects and a nice alternative when we need the basic functionality of our navigation.

TMENU Properties

As a child of HMENU, TMENU shares some common properties with the other menu objects, but there are some specific TMENUITEM properties that can be modified for the items in a text-based menu:

Adding separators to menu items

Okay, now that we've seen the properties we can use, we can start using them and improving the basic menu we currently have. We remember that our boss complained early on that our multiple word menu titles sometimes looked like separate items and wondered if we could put separators in-between the items. Of course, we could try to just add a | after every menu item by saying lib.mainMenu.1.NO.after =  |, but then the menu will still have one annoying | at the end. Luckily for us, we can use the optionSplit function in TypoScript. With the optionSplit function, we can define different wrappings for the first, middle, and last elements. The optionSplit function can be used with many different menu properties including our different wrapping properties, and the basic syntax looks like this:

wrap = [First element] |*| [All middle elements] |*| [Last element]

As we're already using the allWrap property, we don't really want to retype the li three times. We can go ahead and use the before and after properties. We only actually need the vertical separators after our menu items, so we can quickly skip the before property and just add a special after to our main menu using splitOption like this:

## Main Menu [Begin]
lib.mainMenu = HMENU
lib.mainMenu.entryLevel = 0
lib.mainMenu.wrap = <ul id="menu-area">|</ul>
lib.mainMenu.1 = TMENU
lib.mainMenu.1.NO {
allWrap = <li class="menu-item">|</li>
after = &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | |*|
&nbsp;&nbsp;&nbsp;&nbsp; | |*| &nbsp;
}
## Main Menu [End]

Now, our main menu with CSS spacing and vertical separators can look like this:

TYPO3 Templates Create and modify templates with TypoScript and TemplaVoila
Published: November 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on this subject, see here.)

Redesigning the text-based menus

Okay, so we've made some tasteful changes to update our navigation and make our boss happier, but we need to see the full power of the basic text menu in TYPO3 before we move on to graphical menus. We can't just go back to our bosses and show them that we added little lines to the menu; it's not that impressive. We need to really experiment with this, and that means we have to make more than small tasteful changes. We need to break stuff.

  1. There is a limited amount of space in our submenu area, so we'll set a maximum limit of items:

    lib.subMenu.1.maxItems = 8

  2. We can skip over the first page in the main page tree (Products) for now, so we'll just start on the second item:

    lib.mainMenu.1.begin = 2

  3. The spacing between the text items and the separators seems a little imprecise. We can replace the   spaces with spacer images:

    lib.mainMenu.1.NO.after = <img src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="clear.gif" width="15"> | |*|
    <img src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="clear.gif" width="15"> | |*| &nbsp;

  4. If we add a class to the &lta> tags, it will make it even easier to style in CSS:

    lib.mainMenu.1.NO.ATagParams = class="menu-links"

  5. Right now, we don't have a title field in the &lta> tags, but a title helps usability for everyone and especially those using screen readers or other assistive devices. We're all about web standards right now. We can add the description or page title from the page properties to the link's title field to clarify the contents of the page to which we are linking. To insure that we don't have blank titles, we are going to use the // operator in TypoScript so that TYPO3 will look for the description field first and use the title field if the description is empty:

    lib.mainMenu.1.NO.ATagTitle.field = description // title

  6. It might end up looking tacky, but we just want to see what it looks like to place an image in front of our text titles in the menu. Just to be consistent, we want to make sure that the image links to the same page as the text:

    lib.mainMenu.1 {
    NO {
    beforeImg = fileadmin/templates/bullet.png
    beforeImgLink = 1
    }
    }

  7. While we're at it, let's just add a rollover image. Remember we have to enable the rollover state at the end for it to work:

    lib.mainMenu.1.NO {
    RO = 1
    beforeROImg = fileadmin/templates/bullet_rollover.png
    }

  8. Finally, we decide that we want to show the pages in the current rootline (with the ACT state) differently to set them apart. Our first though might be to just worry about the current page state (CUR), but it might be nice if the main menu item displayed differently even if we're on a subpage. We can use the < operator TypoScript (see TSref for more information) to copy the properties of the normal state over as a starting point. To copy all of the properties, we will write ACT < .NO (not ACT < NO). We'll change the class on the active links and remove the image in front of them. Once again, we will have to enable the ACT state to use it:

    lib.mainMenu.1 {
    ACT < .NO
    ACT = 1
    ACT {
    ATagParams = class="active-link"
    beforeImg >
    }
    }

  9. Finally, we need to add a class to the stylesheet to differentiate the active links according to TYPO3. We've just told the template to change the class to active-link, so we can add the following code to the bottom of our CSS file to change the color of the link to a light grey:

    li.menu-item a.active-link {
    color: #ddd;
    }

After all of our changes, our menu may not be as simple and clean as it once was, but it definitely shows what we can do with some lines of TypoScript. Here is a screenshot with from the Content Elements page. With the mouse hovering over the Visions menu item we can see the rollover image and the link title text that is being pulled from the description field of the page properties:

Final code

If you stepped through all of those changes with us, you probably noticed that we added a lot of redundant lines because we wanted all of our modifications to stand on their own. Of course, in a production environment, those changes should look cleaned up:

## Main Menu [Begin]
lib.mainMenu = HMENU
lib.mainMenu.entryLevel = 0
lib.mainMenu.wrap = <ul id="menu-area">|</ul>
lib.mainMenu.1 = TMENU
lib.mainMenu.1 {
begin = 2
NO {
allWrap = <li class="menu-item">|</li>
after = <img src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="clear.gif" width="15"> | |*| <img src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="clear.
gif" width="15"> | |*| &nbsp;
ATagParams = class="menu-links"
ATagTitle.field = description // title
beforeImg = fileadmin/templates/bullet.png
beforeImgLink = 1
RO = 1
beforeROImg = fileadmin/templates/bullet_rollover.png
}
ACT < .NO
ACT = 1
ACT {
ATagParams = class="active-link"
beforeImg >
}
}
## Main Menu [End]

## Submenu [Begin]
lib.subMenu = HMENU
lib.subMenu.entryLevel = 1
lib.subMenu.wrap = <ul id="submenu-area">|</ul>
lib.subMenu.1 = TMENU
lib.subMenu.1.maxItems = 8
lib.subMenu.1.NO {
allWrap = <li class="submenu-item">|</li>
}
## Submenu [End]

Summary

In the above article we have learnt about HMENUS.

We have covered:

  • Learn about the base hierarchical menu object in TYPO3: HMENU
  • Get introduced to the text-based menu object
  • Rebuild the main menu and submenu from scratch with fancy text-based menu options

Further resources on this subject:


About the Author :


Jeremy Greenawalt

Jeremy Greenawalt is a full-time developer and part-time writer with close to ten years professional experience in website and application creation. His first love was writing, but programming quickly followed.He is a co-founder of Vintage 56 where he helps develop websites, online shopping carts, web apps, iPhone/iOS apps, and anything else his friends can think up. Jeremy is also the web director of a large ministry, Generals International. Jeremy lives near Dallas, Texas with his wife, Rebekah, and their ever-youthful puppy, Aingeal. He loves spending time at home reading, playing around on the piano, or just relaxing on the couch with his family. You can read more from Jeremy at pocketrevolutionary.com, and you can follow him on Twitter at @jgreenawalt.

Books From Packt


TYPO3 4.2 E-Commerce
TYPO3 4.2 E-Commerce

TYPO3 4.3 Multimedia Cookbook
TYPO3 4.3 Multimedia Cookbook

Apache OfBiz Cookbook
Apache OfBiz Cookbook

CMS Design Using PHP and jQuery
CMS Design Using PHP and jQuery

Mastering phpMyAdmin 3.3.x for Effective MySQL Management
Mastering phpMyAdmin 3.3.x for Effective MySQL Management

Joomla! 1.5 Top Extensions Cookbook
Joomla! 1.5 Top Extensions Cookbook

Drupal 7
Drupal 7

TYPO3: Enterprise Content Management
TYPO3: Enterprise Content Management


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software