1/* A highly customized version of.... 2* 3 * Accessible Menu 4 * Version: 1.0 5 * Author: Thomas Mester 6 * Repo: https://github.com/hotgeart/accessible-menu 7 */ 8 9(function($){ 10 $.fn.wmMegaMenu = function (options) { 11 this.each(function() { 12 // Default variable 13 var el = "#" + this.id; 14 15 // Defaults settings 16 var defaults = { 17 animation: "none", 18 animationSpeed: 'fast' 19 }; 20 21 var settings = $.extend({}, defaults, options); 22 23 // Handle click 24 $("body").on("click", el + " button", function () { 25 wmMegaMenuToggler($(this)); 26 }); 27 28 // Handle keyboard 29 $(this).keydown(function (e) { 30 e = e || window.event; 31 var focused = $(":focus"); 32 33 if (e.keyCode == "27") { 34 // ESC 35 if (focused.is('button[aria-expanded="true"]')) { 36 wmMegaMenuToggler(focused); 37 } else { 38 var button = focused 39 .parent() 40 .parent() 41 .parent() 42 .children("button"); 43 button.focus(); 44 wmMegaMenuToggler(button); 45 } 46 } else if (e.keyCode == "37" || e.keyCode == "38") { 47 // ARROW LEFT & UP 48 e.preventDefault(); 49 // jump to the heading link 50 if(focused.parent("li").hasClass("first-sub")) { 51 focused 52 .closest("ul") 53 .parent("li") 54 .prev("li") 55 .children("a, button") 56 .focus(); 57 } 58 // jump to the last sub-link 59 else if (focused.parent().hasClass("vims-primary-bar__feature-morelink")) { 60 focused 61 .closest("li") 62 .prev("li") 63 .find('li.last-sub') 64 .children("a, button") 65 .focus(); 66 } 67 else { 68 focused 69 .parent() 70 .prev("li") 71 .children("a, button") 72 .focus(); 73 } 74 } else if (e.keyCode == "39" || e.keyCode == "40") { 75 // ARROW RIGHT & DOWN 76 e.preventDefault(); 77 // from primary button to heading 78 if(focused.is('button[aria-expanded="true"]')){ 79 focused 80 .next("ul") 81 .children('li:first-child') 82 .children("a, button") 83 .focus(); 84 } 85 // jump to first sub 86 else if(focused.parent().hasClass("heading-link")) { 87 focused 88 .parent() 89 .next("li") 90 .find("ul") 91 .children("li:first-child") 92 .children("a, button") 93 .focus(); 94 } 95 // jump to feature link if there is 96 else if(focused.parent().hasClass("last-sub")) { 97 focused 98 .closest("ul") 99 .parent("li") 100 .next("li") 101 .find("a, button") 102 .focus(); 103 } 104 else { 105 focused 106 .parent() 107 .next("li") 108 .children("a, button") 109 .focus(); 110 } 111 } else if (e.keyCode == "36") { 112 // HOME 113 e.preventDefault(); 114 focused 115 .parent() 116 .parent() 117 .children('li:first-child') 118 .children('a, button') 119 .focus(); 120 } else if (e.keyCode == "35") { 121 // END 122 e.preventDefault(); 123 focused 124 .parent() 125 .parent() 126 .children("li:last-child") 127 .children('a, button') 128 .focus(); 129 } else { 130 // Normal behavior 131 } 132 }); 133 134 // Toggler 135 function wmMegaMenuToggler(item) { 136 var depthString = " > ul > li "; 137 138 if (item == false) { 139 $(el + ' button[aria-expanded="true"]').each(function () { 140 $(this).attr("aria-expanded", false); 141 animate($(this), 'close'); 142 }); 143 } else { 144 $(el + depthString.repeat(getCurrentDepth(item)) + ' button[aria-expanded="true"]') 145 .not(item) 146 .each(function () { 147 $(this).attr("aria-expanded", false); 148 animate($(this), 'close'); 149 }); 150 151 var ariaExpanded = item.attr("aria-expanded") == "true" ? false : true; 152 item.attr("aria-expanded", ariaExpanded); 153 if(ariaExpanded) { 154 animate(item, 'open'); 155 } 156 else { 157 animate(item, 'close'); 158 } 159 160 } 161 } 162 163 // To know which level you are in the menu 164 function getCurrentDepth(element) { 165 var depth = 0; 166 167 for (i = 0; i < element.parents().length; i++) { 168 if (element.parents()[i].tagName == "NAV") { 169 /* 170 We devide by 2 because otherwise it count </li> like a level of depth 171 Example: 172 ul > li > ul > li => 4 parents but a depth of 2 173 So depth = parents / 2 174 */ 175 depth = i / 2; 176 break; 177 } 178 } 179 return depth; 180 } 181 182 // Annimate function 183 function animate(element, action) { 184 //console.log(action); 185 if(action == 'close') { 186 element.closest("ul").removeClass("menu-open"); 187 } else if(action == 'open'){ 188 element.closest("ul").addClass("menu-open"); 189 } else { 190 if(element.attr("aria-expanded") == true) { 191 element.closest("ul").removeClass("menu-open"); 192 } 193 else { 194 element.closest("ul").addClass("menu-open"); 195 } 196 } 197 } 198 199 $(el + ", " + el + " ul").focusout(function (e) { 200 if (!$(e.relatedTarget).is(el + ", " + el + " *") && document.hasFocus()) { 201 wmMegaMenuToggler(false); 202 } 203 }); 204 });
205 206 }; 207}(jQuery));
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.