PageSourceSearch

https://stamen.com/wp-content/themes/stamen/assets/js/navigation.js?ver=20210128

js stamen.com collected 2026-09-24 08:24:03 UTC 4,242 bytes, 149 lines download raw bytes

1/**
2 * File navigation.js.
3 *
4 * Handles toggling the navigation menu for small screens and enables TAB key
5 * navigation support for dropdown menus.
6 */
7(function () {
8  var body, parent, container, button, menu, links, i, len, mobileOverlay;
9
10  container = document.getElementById('site-navigation');
11  if (!container) {
12    return;
13  }
14
15  parent = document.getElementById('nav-container');
16  if (!parent) {
17    return;
18  }
19
20  body = document.querySelector('body');
21
22  button = container.getElementsByTagName('button')[0];
23  if ('undefined' === typeof button) {
24    return;
25  }
26
27  menu = container.getElementsByTagName('ul')[0];
28
29  mobileOverlay = document.getElementById('mobile-overlay');
30
31  // Hide menu toggle button if menu is empty and return early.
32  if ('undefined' === typeof menu) {
33    button.style.display = 'none';
34    return;
35  }
36
37  menu.setAttribute('aria-expanded', 'false');
38  if (-1 === menu.className.indexOf('nav-menu')) {
39    menu.className += ' nav-menu';
40  }
41
42  const doToggleOff = function () {
43    container.className = container.className.replace(' toggled', '');
44    parent.className = parent.className.replace(' toggled', '');
45    body.classList.remove('toggled');
46    button.setAttribute('aria-expanded', 'false');
47    menu.setAttribute('aria-expanded', 'false');
48    mobileOverlay.classList.remove('visible');
49  };
50
51  const doToggleOn = function () {
52    container.className += ' toggled';
53    parent.className += ' toggled';
54    body.classList.add('toggled');
55    button.setAttribute('aria-expanded', 'true');
56    menu.setAttribute('aria-expanded', 'true');
57    mobileOverlay.classList.add('visible');
58  };
59
60  button.onclick = function () {
61    if (-1 !== container.className.indexOf('toggled')) {
62      doToggleOff();
63    } else {
64      doToggleOn();
65    }
66  };
67
68  mobileOverlay.addEventListener('click', function () {
69    doToggleOff();
70  });
71
72  // Get all the link elements within the menu.
73  links = menu.getElementsByTagName('a');
74
75  // Each time a menu link is focused or blurred, toggle focus.
76  for (i = 0, len = links.length; i < len; i++) {
77    links[i].addEventListener('focus', toggleFocus, true);
78    links[i].addEventListener('blur', toggleFocus, true);
79  }
80
81  /**
82   * Sets or removes .focus class on an element.
83   */
84  function toggleFocus() {
85    var self = this;
86
87    // Move up through the ancestors of the current link until we hit .nav-menu.
88    while (-1 === self.className.indexOf('nav-menu')) {
89      // On li elements toggle the class .focus.
90      if ('li' === self.tagName.toLowerCase()) {
91        if (-1 !== self.className.indexOf('focus')) {
92          self.className = self.className.replace(' focus', '');
93        } else {
94          self.className += ' focus';
95        }
96      }
97
98      self = self.parentElement;
99    }
100  }
101
102  /**
103   * Toggles `focus` class to allow submenu access on tablets.
104   */
105  (function (container) {
106    var touchStartFn,
107      i,
108      parentLink = container.querySelectorAll(
109        '.menu-item-has-children > a, .page_item_has_children > a'
110      );
111
112    if ('ontouchstart' in window) {
113      touchStartFn = function (e) {
114        var menuItem = this.parentNode,
115          i;
116
117        if (!menuItem.classList.contains('focus')) {
118          e.preventDefault();
119          for (i = 0; i < menuItem.parentNode.children.length; ++i) {
120            if (menuItem === menuItem.parentNode.children[i]) {
121              continue;
122            }
123            menuItem.parentNode.children[i].classList.remove('focus');
124          }
125          menuItem.classList.add('focus');
126        } else {
127          menuItem.classList.remove('focus');
128        }
129      };
130
131      for (i = 0; i < parentLink.length; ++i) {
132        parentLink[i].addEventListener('touchstart', touchStartFn, false);
133      }
134    }
135  })(container);
136
137  // watch resize for closing sidebar
138  window.addEventListener('resize', function () {
139    if (
140      this.innerWidth > 808 &&
141      -1 !== container.className.indexOf('toggled')
142    ) {
143      container.className = container.className.replace(' toggled', '');
144      parent.className = container.className.replace(' toggled', '');
145      button.setAttribute('aria-expanded', 'false');
146      menu.setAttribute('aria-expanded', 'false');
147    }
148  });
149})();

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.