PageSourceSearch

https://www.writecream.com/js/header-nav.js

js writecream.com collected 2026-10-01 10:28:37 UTC 2,573 bytes, 68 lines download raw bytes

1/**
2 * Header navigation — mobile hamburger toggle + submenu dropdowns + click-outside close.
3 *
4 * Extracted from main.js so any page that includes the {{> header}} partial can wire
5 * the nav without pulling in all of main.js (avoids conflicts with page-specific JS).
6 * Self-contained IIFE, guarded against double-init; every block guards on element
7 * presence, so it's a no-op on pages without the header.
8 */
9(function () {
10  'use strict';
11  if (window.__wcHeaderNavInit) return;
12  window.__wcHeaderNavInit = true;
13
14  function init() {
15    var menuToggle = document.querySelector('.mobile-menu-toggle');
16    var mainNav = document.querySelector('.main-nav');
17    var submenuItems = document.querySelectorAll('.main-nav .has-dropdown, .main-nav .has-mega-menu');
18
19    var closeMobileMenu = function () {
20      if (!menuToggle || !mainNav) return;
21      menuToggle.setAttribute('aria-expanded', 'false');
22      mainNav.classList.remove('active');
23      submenuItems.forEach(function (item) { item.classList.remove('is-open'); });
24    };
25
26    if (menuToggle && mainNav) {
27      menuToggle.addEventListener('click', function () {
28        var expanded = this.getAttribute('aria-expanded') === 'true';
29        this.setAttribute('aria-expanded', !expanded);
30        mainNav.classList.toggle('active');
31        if (expanded) {
32          submenuItems.forEach(function (item) { item.classList.remove('is-open'); });
33        }
34      });
35    }
36
37    if (submenuItems.length) {
38      submenuItems.forEach(function (item) {
39        var trigger = item.querySelector('.main-nav__link');
40        if (!trigger) return;
41        trigger.addEventListener('click', function (e) {
42          var isMobileNav = window.innerWidth <= 992;
43          if (!isMobileNav) return;
44          e.preventDefault();
45          var isOpen = item.classList.contains('is-open');
46          submenuItems.forEach(function (otherItem) { otherItem.classList.remove('is-open'); });
47          if (!isOpen) { item.classList.add('is-open'); }
48        });
49      });
50    }
51
52    document.addEventListener('click', function (e) {
53      var isMobileNav = window.innerWidth <= 992;
54      if (!isMobileNav || !mainNav || !menuToggle) return;
55      var clickInsideMenu = mainNav.contains(e.target);
56      var clickOnToggle = menuToggle.contains(e.target);
57      if (!clickInsideMenu && !clickOnToggle && mainNav.classList.contains('active')) {
58        closeMobileMenu();
59      }
60    });
61  }
62
63  if (document.readyState === 'loading') {
64    document.addEventListener('DOMContentLoaded', init);
65  } else {
66    init();
67  }
68})();

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.