PageSourceSearch

https://visitwanderland.com.au/profiles/custom/district-cms-profil…/js/main-menu.js?v=202401240946

js visitwanderland.com.au collected 2026-10-02 13:26:00 UTC 6,380 bytes, 209 lines download raw bytes

1(function ($, Drupal) {
2
3  Drupal.behaviors.districtMenuMainMenu = {
4
5    /**
6     * Navigation help text. Used for screen reader announcements and dialog.
7     */
8    helpText: function () {
9      var text = 'Use the keyboard arrow keys to easily traverse the main navigation.';
10      text += ' Press the escape key at any time to jump to the top level parent link.';
11      return text;
12    },
13
14    /**
15     * Attach all functionality here.
16     */
17    attach: function (context, settings) {
18      var behavior = this;
19      
20      $(once('district-menu-main-menu', '.js-menu-extras-main', context)).each(function () {
21        behavior.initNavigationHelp(this);
22        behavior.initNavigationKeys(this)
23      });
24    },
25
26    /**
27     * Map key press to navigation behaviors.
28     */
29    initNavigationKeys: function (context) {
30      var behavior = this;
31      $('.menu-level-0 > .menu-item', context).keydown(function (e) {
32        var $current = $(this);
33        var $target = $(e.target);
34
35        switch (e.keyCode) {
36          case 37: // left
37            e.preventDefault();
38            behavior.navigateLeft($current, $target);
39            break;
40
41          case 38: // up
42            e.preventDefault();
43            behavior.navigateUp($current, $target);
44            break;
45
46          case 39: // right
47            e.preventDefault();
48            behavior.navigateRight($current, $target);
49            break;
50
51          case 40: // down
52            e.preventDefault();
53            behavior.navigateDown($current, $target);
54            break;
55
56          case 27: // escape
57            e.preventDefault();
58            behavior.navigateEscape($current, $target);
59            break;
60        }
61      });
62    },
63
64    /**
65     * Generate navigation help elements and functionality.
66     */
67    initNavigationHelp: function (context) {
68      var behavior = this;
69      // Create hidden dialog elements.
70      var $hidden = $('<div class="hidden"></div>').appendTo('body');
71      var $helpDialogEl = $('<div id="nav-help-dialog"</div>')
72        .text(this.helpText()).appendTo($hidden);
73      // Create help menu item. Only accessible via keyboard.
74      var $help = $('<li class="menu-item menu-item--nav-help"><a href="#" role="button" tabindex="0" aria-label="Keyboard navigation help" class="nav-help sr-only">?</a></li>');
75      $help.prependTo($('.menu-level-0', context));
76      $help = $('.menu-level-0', context).find('.nav-help');
77      // Show help link when focused.
78      $help.focus(function () {
79        $(this).removeClass('sr-only');
80      });
81      // Hide help link when not focused.
82      $help.blur(function () {
83        $(this).addClass('sr-only');
84      });
85      // Create dialog object.
86      var helpDialog = Drupal.dialog($helpDialogEl, {
87        title: 'Main navigation help',
88        modal: true,
89        close: function ( event, ui ) {
90          $help.focus()
91        }
92      })
93      // Trigger dialog when link is clicked/keyboard enter button.
94      $help.click(function () {
95        if (!helpDialog.open) {
96          Drupal.announce(behavior.helpText())
97          helpDialog.showModal();
98        }
99        else {
100          helpDialog.close();
101        }
102      })
103      // Hide dialog when navigating away from help link.
104      $help.keydown('keydown', function (e) {
105        if (e.keyCode == 13) {
106          return;
107        }
108       if (helpDialog.open) {
109          helpDialog.close();
110        }
111      });
112    },
113
114    /**
115     * Check if target link is a top level menu item.
116     */
117    isTopLevelLink: function ($current, $target) {
118      return $target.is($current.find('> a'));
119    },
120
121    /**
122     * Check if target link is a second level menu item.
123     */
124    isSecondLevelLink: function ($current, $target) {
125      return $target.is($current.find('.menu-level-1 > .menu-item > a'));
126    },
127
128    /**
129     * Check if target link is a third level menu item.
130     */
131    isThirdLevelLink: function ($current, $target) {
132      return $target.is($current.find('.menu-level-2 > .menu-item > a'));
133    },
134
135    /**
136     * Keyboard arrow left behavior.
137     */
138    navigateLeft: function ($current, $target) {
139      if (this.isTopLevelLink($current, $target)) {
140        $current.prev('.menu-item').find(' > a').focus();
141      }
142      else if (this.isSecondLevelLink($current, $target)) {
143        $target.parent('.menu-item').prev('.menu-item').find(' > a').focus();
144      }
145      else if (this.isThirdLevelLink($current, $target)) {
146        $target.parents('.menu-level-1 > .menu-item')
147          .prev('.menu-item').find(' > a').focus();
148      }
149    },
150
151    /**
152     * Keyboard arrow right behavior.
153     */
154    navigateRight: function ($current, $target) {
155      if (this.isTopLevelLink($current, $target)) {
156        // If last top level menu item. try to find the next focusable element.
157        if ($current.is(':last-of-type')) {
158          $current.parents('.menu--main').next().find('a, button, input').first().focus()
159        }
160        else {
161          $current.next('.menu-item').find(' > a').focus();
162        }
163      }
164      else if (this.isSecondLevelLink($current, $target)) {
165        $target.parent('.menu-item').next('.menu-item').find(' > a').focus();
166      }
167      else if (this.isThirdLevelLink($current, $target)) {
168        $target.parents('.menu-level-1 > .menu-item')
169          .next('.menu-item').find(' > a').focus();
170      }
171    },
172
173    /**
174     * Keyboard arrow up behavior.
175     */
176    navigateUp: function ($current, $target) {
177      if (this.isSecondLevelLink($current, $target)) {
178        $current.find('> a').focus();
179      }
180      else if (this.isThirdLevelLink($current, $target)) {
181        $target.parents('.menu-level-1 > .menu-item')
182          .find(' > a').focus();
183      }
184    },
185
186    /**
187     * Keyboard arrow down behavior.
188     */
189    navigateDown: function ($current, $target) {
190      if (this.isTopLevelLink($current, $target)) {
191        $current.find('.menu-level-1 a').first().focus();
192      }
193      else if (this.isSecondLevelLink($current, $target)) {
194        $target.next().find('.menu-level-2 a').first().focus();
195      }
196      else {
197        $target.parent('.menu-item').next('.menu-item').find(' > a').focus();
198      }
199    },
200
201    /**
202     * Keyboard escape key behavior.
203     */
204    navigateEscape: function ($current, $target) {
205      $current.find('> a').focus();
206    }
207  };
208
209}(jQuery, Drupal));

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.