Änderungen von Dokument Menu Macro
Zuletzt geändert von xwikiadmin am 2025/01/07 11:25
Von Version 1.1
bearbeitet von xwikiadmin
am 2021/11/10 09:01
am 2021/11/10 09:01
Änderungskommentar:
Install extension [org.xwiki.platform:xwiki-platform-menu-ui/13.9]
Auf Version 5.1
bearbeitet von xwikiadmin
am 2023/10/26 09:31
am 2023/10/26 09:31
Änderungskommentar:
Install extension [org.xwiki.platform:xwiki-platform-menu-ui/15.8]
Zusammenfassung
-
Seiteneigenschaften (1 geändert, 0 hinzugefügt, 0 gelöscht)
-
Objekte (3 geändert, 1 hinzugefügt, 0 gelöscht)
Details
- Seiteneigenschaften
-
- Inhalt
-
... ... @@ -3,9 +3,11 @@ 3 3 = Horizontal Menu = 4 4 5 5 {{velocity}} 6 +#set ($menuTemplateDoc = $xwiki.getDocument('MenuTemplate')) 6 6 {{code language="none"}} 7 7 {{menu type="horizontal fixedWidth"}} 8 -$xwiki.getDocument('MenuTemplate').content 9 +## No way to escape content in the code macro, so just remove {, see https://jira.xwiki.org/browse/XRENDERING-13. 10 +$menuTemplateDoc.content.replace('{', '') 9 9 {{/menu}} 10 10 {{/code}} 11 11 {{/velocity}}
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,26 +1,85 @@ 1 -require(['jquery'], function($) { 1 +define('menu-ui-translation-keys', { 2 + prefix: 'menu.ui.', 3 + keys: [ 4 + "openSubMenu", 5 + "closeSubMenu" 6 + ] 7 +}); 8 +require(['jquery','xwiki-l10n!menu-ui-translation-keys'], function($, l10n) { 2 2 // It's not possible to write a CSS selector that targets list items containing lists so we rely on JavaScript. 3 3 // The 'dropdown' CSS class is used only to display the down/left arrow. 4 - $('.menu-horizontal li ul').parent().addClass('xDropdown'); 5 - 11 + // All nodes on the tree. 12 + $('.menu-horizontal ul , .menu-vertical ul') 13 + .attr('role', 'menu'); 14 + // All leaves on the tree. 15 + $('.menu-horizontal li, .menu-vertical li') 16 + .attr('role', 'menuitem'); 17 + $('.menu-horizontal li ul, .menu-vertical li ul') 18 + .parent() 19 + .addClass('xDropdown'); 6 6 // Make sure the menu separators are really empty. 7 - $('.menu-horizontal, .menu-vertical').find('li > br:first-child').remove(); 21 + var menus = $('.menu-horizontal, .menu-vertical'); 22 + menus.find('li > br:first-child').remove(); 8 8 9 - // Collapsible menu bahavior. 10 - $('.menu-vertical.collapsible').each(function(){ 24 + // Add aria attributes to the menu separators. 25 + menus.find('li') 26 + .filter(function() {return this.textContent.trim() === ""; }) 27 + .attr('role', 'separator') 28 + .attr('aria-hidden', 'true'); 29 + 30 + // Vertical menus are initially expanded 31 + $('.menu-vertical.collapsible').each(function() { 11 11 var open = $(this).hasClass('open'); 12 12 $(this).find('li ul').each(function() { 13 13 $(this).addClass('xDropdown-menu').parent().addClass('xDropdown' + (open ? ' open' : '')); 14 - // Wrap everything (including text nodes) before the sub-menu in a DIV that will toggle its state. 15 - var toggle = this.ownerDocument.createElement('div'); 16 - $(this).parent().prepend(toggle); 17 - for(var next = toggle.nextSibling; next != this; next = toggle.nextSibling) { 18 - toggle.appendChild(next); 35 + }); 36 + }); 37 + 38 + function setDropdownButtonTitle(dropDownButton) { 39 + var xDropdown = $(dropDownButton).parent().parent(); 40 + if($(xDropdown).hasClass('open')) { 41 + $(dropDownButton).attr('title', l10n['closeSubMenu']); 42 + $(xDropdown).attr('aria-expanded', "true"); 43 + } else { 44 + $(dropDownButton).attr('title', l10n['openSubMenu']); 45 + $(xDropdown).attr('aria-expanded', "false"); 46 + } 47 + } 48 + 49 + $('.xDropdown').each(function() { 50 + var dropDownHeader = this.ownerDocument.createElement("div"); 51 + $(dropDownHeader).addClass("xDropdown-header"); 52 + var dropDownButton = this.ownerDocument.createElement("button"); 53 + $(dropDownButton).addClass("xDropdown-header-toggle"); 54 + setDropdownButtonTitle(dropDownButton); 55 + dropDownButton.addEventListener('click',function() { 56 + //Swaps the state of the submenu. 57 + var xDropdown = $(this).parent().parent(); 58 + xDropdown.toggleClass('open'); 59 + setDropdownButtonTitle(dropDownButton); 60 + }); 61 + let dropDownContent = $(this).contents(); 62 + // We put all the content of the entry in the header, 63 + // except for the last one which is the content of the dropdown. This dropdown stays where it is. 64 + for (let index = 0; index < dropDownContent.length - 1 ; index++) { 65 + let item = dropDownContent[index]; 66 + dropDownHeader.append(item); 19 19 } 20 - $(toggle).addClass('xDropdown-toggle').on('click', function() { 21 - $(this).parent().toggleClass('open'); 22 - }); 68 + dropDownHeader.append(dropDownButton); 69 + $(this).prepend(dropDownHeader); 70 + $(dropDownHeader).next().addClass('xDropdown-menu'); 71 + }); 72 + 73 + $('.menu-horizontal .xDropdown').each(function() { 74 + // In case of horizontal menus, make it so that a class is added on hover, instead of using the :hover pseudo-class 75 + this.addEventListener("mouseover", function() { 76 + $(this).addClass('open'); 77 + setDropdownButtonTitle(this.firstChild.lastChild); 23 23 }); 79 + this.addEventListener("mouseout", function() { 80 + $(this).removeClass('open'); 81 + setDropdownButtonTitle(this.firstChild.lastChild); 82 + }); 24 24 }); 25 25 26 26 // In case of horizontal responsive menus, make sub-submenus in the navbar work on mobile devices
- XWiki.StyleSheetExtension[1]
-
- Code
-
... ... @@ -4,6 +4,32 @@ 4 4 } 5 5 } 6 6 .menu { 7 + /* Rotate the carets when the menu is opened. */ 8 + .xDropdown{ 9 + > .xDropdown-header > .xDropdown-header-toggle:before { 10 + transform: rotate(90deg); 11 + } 12 + &.open > .xDropdown-header > .xDropdown-header-toggle:before { 13 + transform: rotate(0); 14 + } 15 + } 16 + .xDropdown-header-toggle { 17 + background: transparent; 18 + border:none; 19 + border-radius: @border-radius-base; 20 + margin: 0 .3em; 21 + line-height: (@line-height-computed / 2); 22 + min-width: 24px; 23 + min-height: 24px; 24 + &:hover, &:focus-within { 25 + background-color: @dropdown-bg; 26 + } 27 + &:before { 28 + .caret; 29 + margin-left: 0; 30 + content: ''; 31 + } 32 + } 7 7 &.menu-vertical { 8 8 ul { 9 9 list-style-type: none; ... ... @@ -25,32 +25,8 @@ 25 25 .xDropdown-menu { 26 26 display: none; 27 27 } 28 - .xDropdown-toggle { 29 - cursor: pointer; 30 - position: relative; 31 - &:hover { 32 - background-color: @nav-link-hover-bg; 33 - } 34 - &:after { 35 - .caret; 36 - content: ''; 37 - /* Positioning */ 38 - position: absolute; 39 - margin-top: @line-height-computed / 3; 40 - right: 1em; 41 - /* Collapsed arrow style */ 42 - border-bottom: 4px solid transparent; 43 - border-right: 4px solid; 44 - border-top: 4px solid transparent; 45 - } 46 - } 47 47 .xDropdown.open { 48 - > .xDropdown-toggle:after { 49 - /* Expanded arrow style */ 50 - .caret; 51 - margin-top: @line-height-computed / 2; 52 - } 53 - > .xDropdown-menu { 55 + > ul { 54 54 display: block; 55 55 } 56 56 } ... ... @@ -64,22 +64,35 @@ 64 64 .box-shadow(0 2px 8px rgba(0,0,0,0.4) inset); 65 65 min-height: @navbar-height; 66 66 padding-left: 25px; 69 + .xDropdown.open { 70 + > .xDropdown-header > .xDropdown-header-toggle:before { 71 + transform: rotate(0); 72 + } 73 + > ul { 74 + display: block; 75 + } 76 + } 67 67 & > ul { 68 68 padding-left: 0; 69 69 list-style-type: none; 70 70 margin: 0; 81 + min-height: 50px; 82 + display: flex; 83 + align-items: stretch; 71 71 & > li { 72 72 position: relative; 73 - display: block; 86 + min-height: 50px; 87 + display: flex; 88 + align-items: center; 74 74 padding: @nav-link-padding; 75 - padding-top: @navbar-padding-vertical;76 - padding-bottom: @navbar-padding-vertical;90 + padding-top: 0; 91 + padding-bottom: 0; 77 77 @media (min-width: @grid-float-breakpoint) { 78 78 float: left; 79 79 } 80 80 line-height: @line-height-computed; 81 81 color: @navbar-default-link-color; 82 - &:hover { 97 + &:hover, &:focus-within { 83 83 color: @navbar-default-link-hover-color; 84 84 background-color: @navbar-default-link-hover-bg; 85 85 background-color: @navbar-default-link-active-bg; ... ... @@ -93,7 +93,7 @@ 93 93 /* Links inside menu */ 94 94 a { 95 95 color: @navbar-default-link-color; 96 - &:hover { 111 + &:hover, &:focus-within { 97 97 text-decoration: none; 98 98 } 99 99 } ... ... @@ -102,7 +102,18 @@ 102 102 /* Limit the height to the nav height minus the padding and minus border */ 103 103 max-height: @navbar-height - (2 * @navbar-padding-vertical) - 2px; 104 104 overflow: hidden; 120 + &.xDropdown-header{ 121 + /* No border on the dropdown header */ 122 + max-height: unset; 123 + } 105 105 } 125 + /* Horizontal menu top-level headers. */ 126 + & > .xDropdown-header > .xDropdown-header-toggle { 127 + &:hover, &:focus-within { 128 + /* Change background color of the caret when hovering on the navbar. */ 129 + background-color: @navbar-default-bg; 130 + } 131 + } 106 106 /* Separator vertical inside menu */ 107 107 &:empty { 108 108 height: @navbar-height; ... ... @@ -126,7 +126,6 @@ 126 126 font-size: @font-size-base; 127 127 text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) 128 128 background-color: @dropdown-bg; 129 - border: 1px solid @dropdown-fallback-border; // IE8 fallback 130 130 border: 1px solid @dropdown-border; 131 131 border-radius: @border-radius-base; 132 132 .box-shadow(0 6px 12px rgba(0,0,0,.175)); ... ... @@ -147,7 +147,7 @@ 147 147 color: @dropdown-link-color; 148 148 overflow: hidden; 149 149 text-overflow: ellipsis; // Displaying ... if the text is too long 150 - &:hover { 175 + &:hover, &:focus-within { 151 151 /* &:extend(.dropdown-menu>li>a:hover); */ 152 152 text-decoration: none; 153 153 color: @dropdown-link-hover-color; ... ... @@ -165,7 +165,7 @@ 165 165 color: @dropdown-link-color; 166 166 /* Empty dropdowns should have height in order to display the arrow */ 167 167 min-height: 2 * @font-size-base; 168 - &:hover { 193 + &:hover, &:focus-within { 169 169 text-decoration: none; 170 170 color: @dropdown-link-hover-color; 171 171 background-color: @dropdown-link-hover-bg; ... ... @@ -179,12 +179,6 @@ 179 179 padding: 0; 180 180 display: inherit; 181 181 } 182 - /* Place the arrow on the right */ 183 - &:after { 184 - position: absolute; 185 - margin-top: @line-height-computed / 2; 186 - right: 8px; 187 - } 188 188 } 189 189 /* Separator horizontal inside menu */ 190 190 &:empty { ... ... @@ -197,17 +197,9 @@ 197 197 /* Stylization: Generic */ 198 198 li { 199 199 /* Display submenus on hover */ 200 - & :hover> ul {219 + &.open > ul { 201 201 display: block; 202 202 } 203 - /* Display an arrow for expandable items */ 204 - &.xDropdown { 205 - &:after { 206 - .caret; 207 - content: ''; 208 - margin-left: .5em; 209 - } 210 - } 211 211 } 212 212 /* The only way to have a menu with more than 2 levels without JavaScript is to use a fixed width. */ 213 213 &.fixedWidth { ... ... @@ -229,7 +229,7 @@ 229 229 } 230 230 /* Resetting rules for mobile view */ 231 231 @media (max-width: @screen-xs-max) { 232 - > ul { 243 + > ul { 233 233 margin: 0 0 0 -25px; /* Remove padding added in normal view */ 234 234 > li { 235 235 &:empty { ... ... @@ -251,19 +251,16 @@ 251 251 /* Links inside menu */ 252 252 a { 253 253 color: @navbar-default-link-color; 254 - &:hover { 255 - /* Preserve the styling from dropdown */ 256 - } 257 257 } 258 258 /* Submenus inside menu */ 259 259 &.xDropdown { 260 260 color: @navbar-default-link-color; 261 - & :hover{269 + &.open { 262 262 background-color: transparent; 263 263 color: inherit; 264 264 } 265 265 /* When in dropdown we also have a link */ 266 - > span > a { 274 + > span > a { 267 267 color: @navbar-default-link-color; 268 268 } 269 269 }
- XWiki.WikiMacroClass[0]
-
- Makro-Code
-
... ... @@ -1,6 +1,7 @@ 1 1 {{velocity}} 2 2 #set ($id = $xcontext.macro.params.id) 3 3 #set ($type = $xcontext.macro.params.type) 4 +#set ($label = $xcontext.macro.params.label) 4 4 #set ($colorTheme = $xwiki.getUserPreference('colorTheme')) 5 5 #if ("$!colorTheme" != '') 6 6 ## Make sure we use an absolute reference (see XWIKI-9672) ... ... @@ -8,12 +8,24 @@ 8 8 #end 9 9 #set ($discard = $xwiki.ssx.use("$xcontext.macro.doc.prefixedFullName", {'colorTheme': $colorTheme})) 10 10 #set ($discard = $xwiki.jsx.use("$xcontext.macro.doc.prefixedFullName")) 12 +## Make sure the label is non-empty as otherwise the aria-label doesn't work. 13 +#if ("$!label" != '') 14 + #set ($label = $wikimacro.context.getXDOM().getIdGenerator().generateUniqueId('Menu','')) 15 +#end 11 11 #if($type.contains('horizontal')) 12 - (% role="navigation" class="menu-horizontal-toggle" %)((( 17 + ## Make sure the id is non-empty for horizontal menus as otherwise the toggle doesn't work. 18 + #if ("$!id" == '') 19 + #set ($id = $wikimacro.context.getXDOM().getIdGenerator().generateUniqueId("M", "GeneratedMenuId")) 20 + #end 21 + (% role='navigation' class='menu-horizontal-toggle' 22 + aria-label="${services.rendering.escape($label, 'xwiki/2.1')}" %)((( 13 13 (% class="navbar-header" %)((( 14 14 {{html}} 15 - <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#$!{id}" aria-expanded="false"> 16 - <span class="sr-only"></span> 25 + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#$!{escapetool.xml($id)}" 26 + aria-expanded="false" aria-controls="$!{escapetool.xml($id)}"> 27 + <span class="sr-only"> 28 + $escapetool.xml($services.localization.render('menu.ui.horizontal.toggler.description')) 29 + </span> 17 17 <span class="icon-bar"></span> 18 18 <span class="icon-bar"></span> 19 19 <span class="icon-bar"></span> ... ... @@ -20,13 +20,14 @@ 20 20 </button> 21 21 {{/html}} 22 22 ))) 23 - (% id="${id}" class="menu menu-$!type collapse navbar-collapse" %)((( 24 - $xcontext.macro.content36 + (% id="$!{services.rendering.escape($id, 'xwiki/2.1')}" class="menu menu-${services.rendering.escape($!type, 'xwiki/2.1')} collapse navbar-collapse" role="navigation" %)((( 37 + {{wikimacrocontent/}} 25 25 ))) 26 26 ))) 27 27 #else 28 - (% #if ("$!id" != '') id="$id"#end class="menu menu-$!type" %)((( 29 - $xcontext.macro.content 41 + (% role="navigation" #if ("$!id" != '') id="${services.rendering.escape($id, 'xwiki/2.1')}"#end class="menu menu-${services.rendering.escape($!type, 'xwiki/2.1')}" 42 + aria-label="${services.rendering.escape($label, 'xwiki/2.1')}" %)((( 43 + {{wikimacrocontent/}} 30 30 ))) 31 31 #end 32 32 {{/velocity}} - Makroinhaltstyp
-
... ... @@ -1,0 +1,1 @@ 1 +Wiki - Default categories
-
... ... @@ -1,0 +1,1 @@ 1 +Navigation - Standardkategorie
-
... ... @@ -1,1 +1,0 @@ 1 -Navigation
- XWiki.WikiMacroParameterClass[3]
-
- Parameter-Beschreibung
-
... ... @@ -1,0 +1,1 @@ 1 +Optional menu label used to describe the content of the menu. - Parameter verpflichtend
-
... ... @@ -1,0 +1,1 @@ 1 +Nein - Parameter-Name
-
... ... @@ -1,0 +1,1 @@ 1 +label