Last active
August 4, 2020 12:51
-
-
Save julrich/d91c1ac1968418e6ae8290f2a2e90afb to your computer and use it in GitHub Desktop.
Revisions
-
julrich revised this gist
Jun 6, 2018 . No changes.There are no files selected for viewing
-
julrich created this gist
Jun 6, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,151 @@ # # Main navigation in Sidebar # # General idea: Don't render & cache 'active' and 'current' states in 'expAll' menu, so it becomes cacheable # over all pages. To regain 'active' and 'current' states, the result of the cached menu is parsed by # 'stdWrap.replacement', utilizing specific information about the resulting menu item markup to insert them. # Use COA to decouple the stdWrap ('lib.navSidebar.stdWrap.replacement') needed for RegExp replacement from # the cached menu ('lib.navSidebar.10'). This way the complete menu can be generically cached without current # and active states, but the stdWrap is still run, re-adding those lib.navSidebar = COA # Definition of the general menu object lib.navSidebar.10 = HMENU lib.navSidebar.10 { cache { # Use unique key for combination of '$page.uid.root' (current instance, multi-site specific) # and the chosen language ('TSFE:sys_language_uid') key = navSidebar-{$page.uid.root}-{TSFE:sys_language_uid} key.insertData = 1 # 'lifetime = default' in this case refers to config.cache_period = 43200 (12 hours) lifetime = default } # Start at the root of the page entryLevel = 0 # Actual menu, crucially we render 'page_{field:uid}', e.g. 'page_123', into each relevant # item. This gives us the option to later replace those uniquely identifiable strings to include # additional classes like 'active' or 'current' 1 = TMENU 1 { # 'expAll = 1' to expand all nodes recursively expAll = 1 # Markup for items that have no submenu-items NO = 1 NO { wrapItemAndSub = <li class="page_{field:uid} nav-sidebar__list__item">|</li> wrapItemAndSub.insertData = 1 ATagTitle.field = title // subtitle ATagParams = tabindex="0" } # Markup for items that have submenu-items IFSUB = 1 IFSUB { wrapItemAndSub = <li class="page_{field:uid} nav-sidebar__list__item nav-sidebar__list__item--has-submenu">|</li> wrapItemAndSub.insertData = 1 before = <span id="nav-sidebar_{field:uid}" role="button" aria-haspopup="true" aria-owns="nav-sidebar__submenu_{field:uid}" aria-controls="nav-sidebar__submenu_{field:uid}" aria-expanded="false"> before.insertData = 1 after = <svg class="nav-sidebar__icon"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-arrow-down"></use></svg></span> after.insertData = 1 doNotLinkIt = 1 } } # Additionally add a class denoting the level for subsequent menu levels (5 supported overall right now) # Submenu Level 2 2 < .1 2 = TMENU 2 { stdWrap.dataWrap = <ul class="nav-sidebar__submenu nav-sidebar__submenu--level-2">|</ul> } # Submenu Level 3 3 < .1 3 = TMENU 3 { stdWrap.dataWrap = <ul class="nav-sidebar__submenu nav-sidebar__submenu--level-3">|</ul> } # Submenu Level 4 4 < .1 4 = TMENU 4 { stdWrap.dataWrap = <ul class="nav-sidebar__submenu nav-sidebar__submenu--level-4">|</ul> } # Submenu Level 5 5 < .1 5 = TMENU 5 { stdWrap.dataWrap = <ul class="nav-sidebar__submenu nav-sidebar__submenu--level-5">|</ul> } } # Add replacement stdWrap, to augment the uniquely identifable strings ('page_{field:uid} nav', e.g. 'page_123 nav'), # embedded with the classes=".." of each menuitem, with additional classes for 'active' and 'current' states. # the classes # Don't add replacement function for pages where the resulting regular expression would be empty, triggering an error # Those currently are the root page itself, and all publicly visible pages, that are not children of the root page. [globalVar = TSFE:id={$page.uid.root}] || [globalVar = TSFE:id={$page.uid.404}] || [globalVar = TSFE:id={$page.uid.noTranslation}] || [globalVar = TSFE:id={$page.uid.search}] # Do nothing here, we just need the negation [else] # Also see 'replacement' TypoScript reference: # https://docs.typo3.org/typo3cms/TyposcriptReference/8.7/Functions/Replacement/ lib.navSidebar.stdWrap.replacement.10 { # Construct search string of the form '#a (Cat|Dog|Tiger)#i', Cat/Dog/Tiger in this case being all the values # we want to replace. All the menu items, to be precise their unique string (e.g. 'page_123 nav'), # that are in the rootline need replacement here. search.cObject = COA search.cObject.10 = HMENU search.cObject.10 { # Construct a rootline menu, including all pages from the current page to the root page ('1|-1') special = rootline special.range = 1|-1 # Wrap the whole menu with the structure we need for the 'replacement.10.search' RegExp ('#(...)#i') wrap = #(|)#i # For all menuitems of this rootline, discard the actual output ('<li><a>...</a></li>') # by setting 'doNotLinkIt = 1' and 'doNotShowLink = 1'. Generate inner part of RegExp, # e.g. 'page_123 nav|page_1231 nav|page_2123 nav', using 'before' 1 = TMENU 1 { NO { # Use option split, because we don't want a '|' after the last item before = page_{field:uid} nav| |*| page_{field:uid} nav| |*| page_{field:uid} nav before.insertData = 1 doNotLinkIt = 1 doNotShowLink = 1 } } } # Rootline looks something like this: 'root (uid: 1) > page1 (uid: 10) > page10 (uid:100) > page100 (uid:1000)' # Only the last item in the rootline is the current item, all the items before it are active items. # Thus we option split again, for us 'nav-sidebar__list__item--submenu-is-open' equals 'active', # 'nav-sidebar__list__item--current' equal 'current'. replace = nav-sidebar__list__item--submenu-is-open ${1} |*| nav-sidebar__list__item--submenu-is-open ${1} |*| nav-sidebar__list__item--current ${1} # Enable option split for replace and RegExp for search useRegExp = 1 useOptionSplitReplace = 1 } [global] # If there is a user logged in to the specific (current) instance, use a different cache key, which in addition to # '$page.uid.root' and 'TSFE:sys_language_uid' also encodes the user uid of the logged in user, because every user # might have his own set of visible pages, resulting in menu cache entry unique per user + instance + language. [usergroup = {$page.uid.frontendUserGroupUid}] lib.navSidebar.10 { cache { key = navSidebarLoggedIn-{$page.uid.root}-{TSFE:sys_language_uid}-{TSFE:fe_user|user|uid} key.insertData = 1 } } [global]