1class HeaderExtendedMenuClass { 2 mobileNavIsOpen = false; 3 mobileNavFocusedItem = undefined; 4 /** 5 * @param mobileNavMenuId string nav-element 6 * @param mobileNavMenuButtonID string button im nav-element 7 * @param mobileNavMenuListWrapper 8 * @param mobileNavMenuList string liste im nav-element 9 * @param mobileNavMenuListElements string listen-elemente in der liste 10 * @param mobileNavMenuListElementLinks string links in den listen-elementen 11 */ 12 constructor( 13 mobileNavMenuId, 14 mobileNavMenuButtonID, 15 mobileNavMenuListWrapper, 16 mobileNavMenuList, 17 mobileNavMenuListElements, 18 mobileNavMenuListElementLinks, 19 ) { 20 this.mobileNavMenuId = mobileNavMenuId; 21 this.mobileNavMenuButtonID = mobileNavMenuButtonID; 22 this.mobileNavMenuListWrapper = mobileNavMenuListWrapper; 23 this.mobileNavMenuList = mobileNavMenuList; 24 this.mobileNavMenuListElements = mobileNavMenuListElements; 25 this.mobileNavMenuListElementLinks = mobileNavMenuListElementLinks; 26 this.firstMenuItemChars = []; 27 this.currentSelectedMenuItemIndex = 0; 28 this.fillFirstMenuItemChars(); 29 this.startListener(); 30 this.setLastMobileNavFocusedItem( 31 $(this.mobileNavMenuListElements + ":first-child a"), 32 ); 33 } 34 /** 35 * @name startListener 36 * @description Startet alle Listener 37 */ 38 startListener() { 39 let that = this; 40 $(that.mobileNavMenuButtonID).on("click", function (e) { 41 that.toggleMobileNavMenu(); 42 }); 43 44 $(that.mobileNavMenuButtonID).on("keydown", function (e) { 45 if (e.keyCode === 13 || e.keyCode === 32) { 46 e.preventDefault(); 47 e.stopPropagation(); 48 that.toggleMobileNavMenu(); 49 } 50 }); 51 52 $(document).on("click", function () { 53 if (that.menuIsVisible() && !that.isFocusInMenu()) { 54 that.closeMobileNavMenu(); 55 } 56 }); 57 58 $(document).on("keydown", function (e) { 59 if (that.menuIsVisible() && that.isFocusInMenu()) { 60 let currentItem = ""; 61 let nextItem = ""; 62 let prevItem = ""; 63 switch (e.keyCode) { 64 case 13: //Enter 65 case 32: //Space 66 // Ãffnet den aktuellen Menüpunkt 67 e.preventDefault(); 68 $(that.mobileNavMenuListElementLinks + "[tabindex=0]")[0].click(); 69 break; 70 case 38: //ArrowUp 71 // Fokussiert den vorherigen Menüpunkt 72 e.preventDefault(); 73 currentItem = $( 74 that.mobileNavMenuListElementLinks + "[tabindex=0]", 75 ); 76 prevItem = currentItem.parent().prev().find("a"); 77 if (prevItem.length === 1) { 78 that.setMenuItemFocus(prevItem); 79 } else { 80 // Fokussiert den letzten Menüpunkt wenn der Anfang der Liste erreicht ist 81 that.setMenuItemFocus( 82 $(that.mobileNavMenuListElements + ":last-child a"), 83 ); 84 } 85 break; 86 case 40: //ArrowDown 87 // Fokussiert den nächsten Menüpunkt 88 e.preventDefault(); 89 currentItem = $( 90 that.mobileNavMenuListElementLinks + "[tabindex=0]", 91 ); 92 nextItem = currentItem.parent().next().find("a"); 93 if (nextItem.length === 1) { 94 that.setMenuItemFocus(nextItem); 95 } else { 96 // Fokussiert den letzten Menüpunkt wenn das ende der Liste erreicht ist 97 that.setMenuItemFocus( 98 $(that.mobileNavMenuListElements + ":first-child a"), 99 ); 100 } 101 break; 102 case 36: //Home 103 // Fokussiert den ersten Menüpunkt 104 e.preventDefault(); 105 that.setMenuItemFocus( 106 $(that.mobileNavMenuListElements + ":first-child a"), 107 ); 108 break; 109 case 35: //END 110 // Fokussiert den letzten Menüpunkt 111 e.preventDefault(); 112 that.setMenuItemFocus( 113 $(that.mobileNavMenuListElements + ":last-child a"), 114 ); 115 break; 116 case 27: //ESC 117 //SchlieÃt das Menü 118 e.preventDefault(); 119 that.closeMobileNavMenu(); 120 break; 121 default: 122 //Prüft ob die gedrücke Taste mit einem Anfangsbuchstaben der Menüpunkte übereinstimmt 123 that.setFocusByChar(e.key); 124 break; 125 } 126 } 127 }); 128 } 129 130 setLastMobileNavFocusedItem(item) { 131 this.mobileNavFocusedItem = item; 132 } 133 134 /** 135 * @name fillFirstMenuItemChars 136 * @description Setzt alle Anfangsbuchstaben der Menüpunkte in ein Array. 137 */ 138 fillFirstMenuItemChars() { 139 let that = this; 140 $(this.mobileNavMenuListElementLinks).each(function (index, value) { 141 let char = ""; 142 if ($(value).text().trim() !== "") { 143 char = $(value).text().trim().substr(0, 1).toLowerCase(); 144 } else { 145 char = $(value).attr("title").trim().substr(0, 1).toLowerCase(); 146 } 147 that.firstMenuItemChars.push(char); 148 }); 149 } 150 151 /** 152 * @name isFocusInMenu 153 * @description Prüft ob der aktuelle Fokus in Menü liegt. 154 * @returns {boolean} 155 */ 156 isFocusInMenu() { 157 return $(this.mobileNavMenuList).find($(":focus")).length === 1; 158 } 159 160 /** 161 * @name menuIsVisible 162 * @description Prüft ob das Menü offen ist. 163 * @returns {boolean} 164 */ 165 menuIsVisible() { 166 return ( 167 $(this.mobileNavMenuButtonID).attr("aria-expanded") === true || 168 $(this.mobileNavMenuButtonID).attr("aria-expanded") === "true" 169 ); 170 } 171 172 /** 173 * @name toggleMobileNavMenu 174 * @description "Steuert" das öffnen und schlieÃen des Menüs. 175 */ 176 toggleMobileNavMenu() { 177 if (this.menuIsVisible()) { 178 this.closeMobileNavMenu(); 179 } else if (!this.menuIsVisible()) { 180 this.openMobileNavMenu(); 181 } 182 } 183 184 /** 185 * @name setMenuItemFocus 186 * @description Setzt den Fokus und setzt die Attribute an den Menüpunkten. 187 * @param element 188 */ 189 setMenuItemFocus(element) { 190 this.currentSelectedMenuItemIndex = $( 191 this.mobileNavMenuListElementLinks, 192 ).index($(element)); 193 $(this.mobileNavMenuList + " li a").attr("tabindex", -1); 194 $(element).attr("tabindex", 0); 195 $(element).focus(); 196 this.setLastMobileNavFocusedItem($(element)); 197 } 198 199 /** 200 * @name openMobileNavMenu 201 * @description Ãffnet das Menü und setzt die Attribute am Button. 202 */
203 openMobileNavMenu() { 204 $(this.mobileNavMenuList).removeClass("mobileClosed"); 205 this.autoHeightAnimate($(this.mobileNavMenuListWrapper), 500); 206 this.mobileNavIsOpen = true; 207 $(this.mobileNavMenuButtonID).attr("aria-expanded", true); 208 $(this.mobileNavMenuId).data("menu-open", true); 209 $(this.mobileNavFocusedItem).attr("tabindex", 0); 210 $(this.mobileNavMenuButtonID).attr("aria-label", "Menü schlieÃen"); 211 this.setMenuItemFocus( 212 $(this.mobileNavMenuListElementLinks + "[tabindex=0]"), 213 ); 214 } 215 216 /** 217 * @name closeMobileNavMenu 218 * @description SchlieÃt das Menü und setzt die Attribute am Button. 219 */ 220 closeMobileNavMenu() { 221 let that = this; 222 $(that.mobileNavMenuListWrapper) 223 .stop() 224 .animate({ height: "0" }, 500, function () { 225 $(that.mobileNavMenuList).addClass("mobileClosed"); 226 $(that.mobileNavMenuButtonID).attr("aria-expanded", false); 227 $(this.mobileNavMenuId).data("menu-open", false); 228 that.mobileNavIsOpen = false; 229 $(that.mobileNavMenuList + " li a").attr("tabindex", -1); 230 $(that.mobileNavMenuButtonID).focus(); 231 $(this.mobileNavMenuButtonID).attr("aria-label", "Menü öffnen"); 232 }); 233 } 234 235 /** 236 * @name setFocusByChar 237 * @description Setzt den Fokus an den nächsten Menüpunkt der mit dem gegebenen Buchstaben beginnt. 238 * @param char 239 */ 240 setFocusByChar(char) { 241 if ( 242 this.firstMenuItemChars.indexOf(char) !== -1 && 243 this.firstMenuItemChars !== [] 244 ) { 245 let length = $(this.mobileNavMenuListElementLinks).length; 246 let rest = length - this.currentSelectedMenuItemIndex; 247 for (let i = this.currentSelectedMenuItemIndex + 1; i < length; i++) { 248 if ( 249 $(this.mobileNavMenuListElementLinks) 250 [i].text.trim() 251 .substr(0, 1) 252 .toLowerCase() === char || 253 $(this.mobileNavMenuListElementLinks) 254 [i].title.trim() 255 .substr(0, 1) 256 .toLowerCase() === char 257 ) { 258 this.setMenuItemFocus($(this.mobileNavMenuListElementLinks)[i]); 259 return; 260 } 261 } 262 for (let i = 0; i < length - rest + 1; i++) { 263 if ( 264 $(this.mobileNavMenuListElementLinks) 265 [i].text.trim() 266 .substr(0, 1) 267 .toLowerCase() === char || 268 $(this.mobileNavMenuListElementLinks) 269 [i].title.trim() 270 .substr(0, 1) 271 .toLowerCase() === char 272 ) { 273 this.setMenuItemFocus($(this.mobileNavMenuListElementLinks)[i]); 274 return; 275 } 276 } 277 } 278 } 279 280 autoHeightAnimate(element, time) { 281 let currentHeight = element.height(); 282 let autoHeight = element.css("height", "auto").height(); 283 284 element.height(currentHeight); 285 element.stop().animate({ height: autoHeight }, time); 286 } 287}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.