PageSourceSearch

https://www.vims.edu/js/wm-mega-menu.js

js vims.edu collected 2026-10-09 22:41:33 UTC 6,071 bytes, 207 lines download raw bytes

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.