TSRef - TypoScript Reference
1.7.10. HMENU
Generates hierarchical menus.
Property: | Data type: | Description: | Default: |
|---|---|---|---|
(1 / 2 / 3 /...) | menuObj | Required! Defines which menuObj that should render the menu items on the various levels. 1 is the first level, 2 is the second level, 3 is the third level, 4 is ....
Example: temp.sidemenu = HMENU temp.sidemenu.1 = GMENU | (no menu) |
cache_period | int | The number of seconds a menu may remain in cache. If this value is not set, the first available value of the following will be used: 1) cache_timeout of the current page 2) config.cache_period defined globally 3) 86400 (= 1 day) |
|
entryLevel | int /stdWrap | Defines at which level in the rootLine, the menu should start. Default is "0" which gives us a menu of the very first pages on the site. If the value is < 0, entryLevel is chosen from "behind" in the rootLine. Thus "-1" is a menu with items from the outermost level, "-2" is the level before the outermost... | 0 |
special | "directory" / "list" / "updated" / "browse" / "rootline" / "keywords" / "language" | (See separate table below) |
|
special.value | list of page-uid's /stdWrap | See above |
|
minItems | int | The minimum items in the menu. If the number of pages does not reach this level, a dummy-page with the title "..." and uid=[currentpage_id] is inserted.
Notice: Affects all sub menus as well. To set the value for each menu level individually, set the properties in the menu objects (see "Common properties" table). |
|
maxItems | int | The maximum items in the menu. More items will be ignored.
Notice: Affects all sub menus as well. (See "minItems" for notice) |
|
begin | int +calc | The first item in the menu.
Example: This results in a menu, where the first two items are skipped starting with item number 3: begin = 3
Notice: Affects all sub menus as well. (See "minItems" for notice) |
|
excludeUidList | list of int | This is a list of page uid's to exclude when the select statement is done. Comma-separated. You may add "current" to the list to exclude the current page.
Example: The pages with these uid-number will NOT be within the menu!! Additionally the current page is always excluded too. excludeUidList = 34,2,current |
|
excludeDoktypes | list of integers | Enter the list of page document types (doktype) to exclude from menus. By default pages that are "not in menu" (5) are excluded and those marked for backend user access only (6). | 5,6 |
includeNotInMenu | boolean | If set, pages with the checkbox "Not in menu" checked will be included in menus. |
|
alwaysActivePIDlist | list of integers /stdWrap | This is a list of page UID numbers that will always be regarded as active menu items and thereby automatically opened regardless of the rootline. |
|
protectLvar | boolean / keyword | If set, then for each page in the menu it will be checked if an Alternative Page Language record for the language defined in "config.sys_language_uid" (typically defined via &L) exists for the page. If that is not the case and the pages "Localization settings" have the "Hide page if no translation for current language exists" flag set, then the menu item will link to a non accessible page that will yield an error page to the user. Setting this option will prevent that situation by simply adding "&L=0" for such pages, meaning that they will switch to the default language rather than keeping the current language. The check is only carried out if a translation is requested ("config.sys_language_uid" is not zero).
Keyword: "all" When set to "all" the same check is carried out but it will not look if "Hide page if no translation for current language exists" is set - it always reverts to default language if no translation is found.
For these options to make sense, they should only be used when "config.sys_language_mode" is not set to "content_fallback". |
|
addQueryString | string | see typolink.addQueryString
Notice: This works only for special=language. |
|
if | ->if | If "if" returns false, the menu is not generated |
|
wrap | wrap |
|
|
stdWrap | ->stdWrap |
|
|
[tsref:(cObject).HMENU]
Example:
temp.sidemenu = HMENU
temp.sidemenu.entryLevel = 1
temp.sidemenu.1 = TMENU
temp.sidemenu.1 {
target = page
NO.afterImg = media/bullets/dots2.gif |*||*| _
NO.afterImgTagParams = hspace="4"
NO.linkWrap = {$fontTag}
NO.ATagBeforeWrap = 1
ACT < .NO
ACT = 1
ACT.linkWrap = <b>{$fontTag}</b>
}
The .special property
This property makes it possible to create menus that are not strictly reflecting the current page-structure, but rather creating menus with links to pages like "next/previous", "last modified", "pages in a certain page" and so on.
NOTE: Don't set .entryLevel for a HMENU when using this option! Also be aware that this selects pages for the first level in the menu. Submenus by menuPbjects 2+ will be created as usual.
special.directory
A HMENU of type special = directory lets you create a menu listing the subpages of one or more parent pages. The parent pages are defined in the property ".value". It is usually used for sitemaps.
Mount pages are supported.
Property: | Data type: | Description: | Default: |
|---|---|---|---|
value | list of page ids /stdWrap | This will generate a menu of all pages with pid = 35 and pid = 56. 20 = HMENU 20.special = directory 20.special.value = 35, 56 | current page id |
[tsref:(cObject).HMENU.special.directory]
special.list
A HMENU of type special = list lets you create a menu that lists the pages you define in the property ".value".
Mount pages are supported.
Property: | Data type: | Description: | Default: |
|---|---|---|---|
value | list of page ids /stdWrap | This will generate a menu with the two pages (uid=35 and uid=36) listed:
20 = HMENU 20.special = list 20.special.value = 35, 56
If .value is not set, the default uid is the .entryLevel uid. | .entryLevel uid |
[tsref:(cObject).HMENU.special.list]
special.updated
A HMENU with the property special = updated will create a menu of the most recently updated pages.
A note on ordering: The sorting menu is by default done in reverse order (desc) with the field specified by "mode", but setting "alternativeSortingField" for the menu object (eg TMENU or GMENU, see later) will override that.
Mount pages are supported.
Property: | Data type: | Description: | Default: |
|---|---|---|---|
value | list of page ids /stdWrap | This will generate a menu of the most recently updated pages from the branches in the tree starting with the uid's (uid=35 and uid=36) listed. 20 = HMENU 20.special = updated 20.special.value = 35, 56 |
|
mode | string | The field in the database that contains the information about the last update. The following values are possible: - SYS_LASTCHANGED (default) - crdate - tstamp (is set automatically when the record is changed) - lastUpdated (set manually in the page-record) - manual (an alias for lastUpdated) - starttime
Fields with empty values are generally not selected. | SYS_LASTCHANGED |
depth | int | Defines the treedepth. The allowed range is 1-20. A depth of 1 means only the start id, depth of 2 means start-id + first level. Notice: "depth" is relative to "beginAtLevel". | 20 |
beginAtLevel | int | Determines starting level for the pagetrees generated based on .value and .depth.
0 is default and includes the start id. 1 starts with the first row of subpages, 2 starts with the second row of subpages.
Notice: "depth" is relative to this property. | 0 |
maxAge | int (seconds) +calc | Pages with update-dates older than the current time minus this number of seconds will not be shown in the menu no matter what. Default is "not used". You may use +-*/ for calculations. |
|
limit | int | Maximal number of items in the menu. Default is 10, max is 100. | 10 |
excludeNoSearchPages | boolean | If set, pages marked "No search" are not included into special-menus. |
|
[tsref:(cObject).HMENU.special.updated]
Example for special = updated:
The following example will generate a menu of the most recently updated pages from the branches in the tree starting with the uid's (uid=35 and uid=36) listed. Furthermore the field "tstamp" is used (default is SYS_LASTCHANGED) and the treedepth is 2 levels. Also there will be shown a maximum of 8 pages and they must have been updated within the last three days (3600*24*3):
20 = HMENU
20.special = updated
20.special.value = 35, 56
20.special {
mode = tstamp
depth = 2
maxAge = 3600*24*3
limit = 8
}
special.rootline
A HMENU with the property special = rootline creates a rootline menu (also known as "breadcrumb trail") that could look like this:
Page level 1 > Page level 2 > Page level 3 > Current page
(For a description of "rootline" see further up in this document.)
Mount pages are supported.
Property: | Data type: | Description: | Default: |
|---|---|---|---|
range | string /stdWrap | [begin-level] | [end-level] (same way as you reference the .entryLevel for HMENU). The following example will start at level 1 and not show the page the user is currently on: temp.breadcrumbs = HMENU temp.breadcrumbs.special = rootline |
|
reverseOrder | boolean | If set to true, the order of the rootline menu elements will be reversed. | false |
targets.[level number] | string | For framesets. You can set a default target and a target for each level by using the level number as subproperty. In the following example the links to pages on level 3 will have target="page", while all other levels will have target="_top" through the TMENU property .target.
page.2 = HMENU page.2.special = rootline page.2.special.range = 1|-2 page.2.special.targets.3 = page page.2.1 = TMENU page.2.1.target = _top page.2.1.wrap = <HR> | <HR> page.2.1.NO { linkWrap = | > } |
|
[tsref:(cObject).HMENU.special.rootline]
special.browse
Warning: Mount pages are not supported!
This kind of menu is built of items given by a list from the property ".item".
Ordering is by default done in reverse order (desc) with the field specified by "mode" , but setting "alternativeSortingField" for the menu object (eg GMENU, see later) will override that.
Property: | Data type: | Description: | Default: |
|---|---|---|---|
value | int | Default is current page id. Seldomly you might want to override this value with another page-uid which will then act as the basepoint for the menu and the predefined items. | current page id |
items | list of itemnames seperated by "|" | Each element in the list (separated by "|") is either a reserved item name (see list) with a predefined function, or a userdefined name which you can assign a link to any page. Note that the current page cannot be the root-page of a site.
Reserved itemnames: next / prev : links to next page / previous page. Next and previous pages are from the same "pid" as the current page id (or "value") - that is the next item in a menu with the current page. Also referred to as current level. If ".prevnextToSection" is set then next/prev will link to the first page of next section / last page of previous section. nextsection / prevsection : links to next section / previous section. A section is defined as the subpages of a page on the same level as the parent (pid) page of the current page. Will not work if parent page of current page is the root page of the site. nextsection_last | prevsection_last: Where nextsection/prevsection links to the first page in a section, these links to the last pages. If there is only one page in the section that will be both first and last. Will not work if parent page of current page is the root page of the site. first / last : First / Last page on current level. If there is only one page on the current level that page will be both first and last. up : Links to the parent (pid) page of the current page. (up 1 level) Will always be available index : Links to the parent of the parent page of the current page (up 2 levels). May not be available if that page is out of the rootline.
If id=20 is current page then: 21= prev and first, 19 = next, 18 = last, 17 = up, 1=index, 10 = nextsection, 11 = nextsection_last
prevsection and prevsection_last is not present because id=3 has no subpages!
TypoScript (only "browse"-part, needs also TMENU/GMENU): xxx = HMENU xxx.special = browse xxx.special { items = index|up|next|prev items.prevnextToSection = 1 index.target = _blank index.fields.title = INDEX index.uid = 8 } |
|
items.prevnextToSection | boolean | If set, the "prev" and "next" navigation will jump to the next section when it reaches the end of pages in the current section |
|
[itemnames].target | string | Optional/alternative target of the item |
|
[itemnames].uid | int | (uid of page) - optional/alternative page-uid to link to |
|
[itemnames].fields.[fieldname] | string | Override field "fieldname" in pagerecord |
|
[tsref:(cObject).HMENU.special.browse]
special.keywords
Makes a menu of pages with one or more keywords also found on the current page.
Mount pages are supported.
Property: | Data type: | Description: | Default: |
|---|---|---|---|
value | int | Page for which keywords to find similar pages |
|
mode | string | Which field in the pages-table to use for sorting. Possible values are:
SYS_LASTCHANGED (which is updated when a page is generated to the youngest tstamp of the records on the page). manual or lastUpdated will use the field "lastUpdated" (set manually in the page-record). tstamp will use the "tstamp"-field of the pagerecord, which is set automatically when the record is changed. crdate will use "crdate"-field of the pagerecord. starttime will use the starttime field. | SYS_LAST_CHANGED |
entryLevel | int | Where in the rootline the search begins. Standard rootline syntax (-x to x) |
|
depth | int | (same as in section "special.updated") | 20 |
limit | int | (same as in section "special.updated") | 10 |
excludeNoSearchPages | boolean | (same as in section "special.updated") |
|
begin | boolean | (same as in section "special.updated") |
|
setKeywords | string | lets you define the keywords manually by defining them as a commaseparated list. If this property is defined, it overrides the default, which is the keywords of the current page. |
|
keywordsField | string | defines the field in the pages-table in which to search for the keywords. Default is the fieldname "keyword". No check is done to see if the field you enter here exists, so enter an existing field, OK?! | keywords |
keywordsField.sourceField | string | defines the field from the current page from which to take the keywords being matched. The default is "keyword". (Notice that ".keywordsField" is only setting the page-record field to search in !) | keywords |
[tsref:(cObject).HMENU.special.keywords]
special.language
Creates a language selector menu. Typically this is made as a menu with flags for each language a page is translated to and when the user clicks any element the same page id is hit but with a change to the "&L" parameter in the URL.
The "language" type will create menu items based on the current page record but with the language record for each language overlaid if available. The items all link to the current page id and only "&L" is changed.
Note on item states:
When "TSFE->sys_language_uid" matches the sys_language uid for an element the state is set to "ACT", otherwise "NO". However, if a page is not available due to the pages "Localization settings" (which can disable translations) or if no Alternative Page Language record was found (can be disabled with ".normalWhenNoLanguage", see below) the state is set to "USERDEF1" for non-active items and "USERDEF2" for active items. So in total there are four states to create designs for. It is recommended to disable the link on menu items rendered with "USERDEF1" and "USERDEF2" in this case since they are disabled exactly because a page in that language does not exist and might even issue an error if tried accessed (depending on site configuration).
Property: | Data type: | Description: | Default: |
|---|---|---|---|
value | comma list of sys_language uids | The number of elements in this list determines the number of menu items. |
|
normalWhenNoLanguage | boolean | If set to 1 the button for a language will ve rendered as a non-disabled button even if no translation is found for the language. |
|
[tsref:(cObject).HMENU.special.language]
Example
Creates a language menu with flags (notice that some lines break):
lib.langMenu = HMENU
lib.langMenu.special = language
lib.langMenu.special.value = 0,1,2
lib.langMenu.1 = GMENU
lib.langMenu.1.NO {
XY = [5.w]+4, [5.h]+4
backColor = white
5 = IMAGE
5.file = media/flags/flag_uk.gif || media/flags/flag_fr.gif || media/flags/flag_es.gif
5.offset = 2,2
}
lib.langMenu.1.ACT < lib.langMenu.1.NO
lib.langMenu.1.ACT=1
lib.langMenu.1.ACT.backColor = black
lib.langMenu.1.USERDEF1 < lib.langMenu.1.NO
lib.langMenu.1.USERDEF1=1
lib.langMenu.1.USERDEF1.5.file = media/flags/flag_uk_d.gif || media/flags/flag_fr_d.gif || media/flags/flag_es_d.gif
lib.langMenu.1.USERDEF1.noLink = 1
special.userdefined
Lets you write your own little PHP-script that generates the array of menuitems.
Property: | Data type: | Description: | Default: |
|---|---|---|---|
file | resource | Filename of the php-file to include. (Just like cObject PHP_SCRIPT) |
|
[any other key] |
| Your own variables to your script. They are all accessible in the array $conf in your script. |
|
[tsref:(cObject).HMENU.special.userdefined]
Howto:
You must populate an array called $menuItemsArray with page-records of the menuitems you want to be in the menu.
It goes like this:
$menuItemsArray[] = pageRow1;
$menuItemsArray[] = pageRow2;
$menuItemsArray[] = pageRow3;
...
A "pageRow" is a record from the table "pages" with all fields selected (SELECT * FROM...)
If you create fake page rows, make sure to add at least "title" and "uid" field values.
Notice:
If you work with mount-points you can set the MP param which should be set for the page by setting the internal field "_MP_PARAM" in the page-record (xxx-xxx).
Overriding URLs:
You can also use the internal field "_OVERRIDE_HREF" to set a custom href-value (eg. "http://www.typo3.org") which will in any case be used rather than a link to the page that the page otherwise might represent. If you use "_OVERRIDE_HREF" then "_OVERRIDE_TARGET" can be used to override the target value as well (See example below).
Other reserved keys:
"_ADD_GETVARS" can be used to add get parameters to the URL, eg. "&L=xxx".
"_SAFE" can be used to protect the element to make sure it is not filtered out for any reason.
Creating submenus:
You can create submenus for the next level easily by just adding an array of menu items in the internal field "_SUB_MENU" (See example below).
Presetting element state
If you would like to preset an element to be recognized as a SPC, IFSUB, ACT, CUR or USR mode item, you can do so by specifying one of these values in the key "ITEM_STATE" of the page record. This setting will override the natural state-evaluation.
special.userfunction
Calls a user function/method in class which should (as with "userdefined" above) return an array with page records for the menu.
Property: | Data type: | Description: | Default: |
|---|---|---|---|
userFunc | string | Name of the function |
|
[tsref:(cObject).HMENU.special.userfunction]
Example: Creating hierarchical menus of custom links
By default the HMENU object is designed to create menus from pages in TYPO3. Such pages are represented by their page-record contents. Usually the "title" field is used for the title and the "uid" field is used to create a link to that page in the menu.
However the HMENU and sub-menu objects are so powerful that it would be very useful to use these objects for creating menus of links which does not relate to pages in TYPO3 by their ids. This could be a menu reflecting a menu structure of a plugin where each link might link to the same page id in TYPO3 but where the difference would be in some parameter value.
This can be easily done with the special-type "userdefined" (see table above) where you can return an array of menu items customly build in a PHP-script you write.
First, this listing creates a menu in three levels where the first two are graphical items:
0: # ************************
1: # MENU LEFT
2: # ************************
3: lib.leftmenu.20 = HMENU
4: lib.leftmenu.20.special = userfunction
5: lib.leftmenu.20.special.userFunc = user_3dsplm_pi2->makeMenuArray
6: lib.leftmenu.20.1 = GMENU
7: lib.leftmenu.20.1.NO {
8: wrap = <tr><td>|</td></tr><tr><td class="bckgdgrey1" height="1"></td></tr>
9: XY = 163,19
10: backColor = white
11: 10 = TEXT
12: 10.text.field = title
13: 10.text.case = upper
14: 10.fontColor = red
15: 10.fontFile = fileadmin/fonts/ARIALNB.TTF
16: 10.niceText = 1
17: 10.offset = 14,12
18: 10.fontSize = 10
19: }
20: lib.leftmenu.20.2 = GMENU
21: lib.leftmenu.20.2.wrap = | <tr><td class="bckgdwhite" height="4"></td></tr><tr><td class="bckgdgrey1" height="1"></td></tr>
22: lib.leftmenu.20.2.NO {
23: wrap = <tr><td class="bckgdwhite" height="4"></td></tr><tr><td>|</td></tr>
24: XY = 163,16
25: backColor = white
26: 10 = TEXT
27: 10.text.field = title
28: 10.text.case = upper
29: 10.fontColor = #666666
30: 10.fontFile = fileadmin/fonts/ARIALNB.TTF
31: 10.niceText = 1
32: 10.offset = 14,12
33: 10.fontSize = 11
34: }
35: lib.leftmenu.20.2.RO < lib.leftmenu.20.2.NO
36: lib.leftmenu.20.2.RO = 1
37: lib.leftmenu.20.2.RO.backColor = #eeeeee
38: lib.leftmenu.20.2.ACT < lib.leftmenu.20.2.NO
39: lib.leftmenu.20.2.ACT = 1
40: lib.leftmenu.20.2.ACT.10.fontColor = red
41: lib.leftmenu.20.3 = TMENU
42: lib.leftmenu.20.3.NO {
43: allWrap = <tr><td>|</td></tr>
44: linkWrap (
45: <table border="0" cellpadding="0" cellspacing="0" style="margin: 2px; 0px; 2px; 0px;">
46: <tr>
47: <td><img src="clear.gif" width="15" height="1" /></td>
48: <td><img src="fileadmin/arrow_gray.gif" height="9" width="9" hspace="3" /></td>
49: <td>|</td>
50: </tr>
51: </table>
52: )
53: }
The menu looks like this on a webpage:

The TypoScript code above generates this menu, but the items does not link straight to pages as usual. This is because the whole menu is generated from this array, which was returned from the function "menuMenuArray" called in TypoScript line 4+5
1: function makeMenuArray($content,$conf) {
2: return array(
3: array(
4: 'title' => 'Contact',
5: '_OVERRIDE_HREF' => 'index.php?id=10',
6: '_SUB_MENU' => array(
7: array(
8: 'title' => 'Offices',
9: '_OVERRIDE_HREF' => 'index.php?id=11',
10: '_OVERRIDE_TARGET' => '_top',
11: 'ITEM_STATE' => 'ACT',
12: '_SUB_MENU' => array(
13: array(
14: 'title' => 'Copenhagen Office',
15: '_OVERRIDE_HREF' => 'index.php?id=11&officeId=cph',
16: ),
17: array(
18: 'title' => 'Paris Office',
19: '_OVERRIDE_HREF' => 'index.php?id=11&officeId=paris',
20: ),
21: array(
22: 'title' => 'New York Office',
23: '_OVERRIDE_HREF' => 'http://www.newyork-office.com',
24: '_OVERRIDE_TARGET' => '_blank',
25: )
26: )
27: ),
28: array(
29: 'title' => 'Form',
30: '_OVERRIDE_HREF' => 'index.php?id=10&cmd=showform',
31: ),
32: array(
33: 'title' => 'Thank you',
34: '_OVERRIDE_HREF' => 'index.php?id=10&cmd=thankyou',
35: ),
36: ),
37: ),
38: array(
39: 'title' => 'Products',
40: '_OVERRIDE_HREF' => 'index.php?id=14',
41: )
42: );
43: }
Notice how the array contains "fake" page-records which has no uid field, only a "title" and "_OVERRIDE_HREF" as required and some other fields as it fits.
The first level with items "Contact" and "Products" contains "title" and "_OVERRIDE_HREF" fields, but "Contact" extends this by a "_SUB_MENU" array which contains a similar array of items.
The first item on the second level, "Offices", contains a field called "_OVERRIDE_TARGET". Further the item has its state set to "ACT" which means it will render as an "active" item (you will have to calculate such stuff manually when you are not rendering a menu of real pages!). Finally there is even another sub-level of menu items.
