summaryrefslogtreecommitdiffstatshomepage
path: root/core/themes/olivero/js/navigation-utils.js
blob: fb22bee3eafa81ed58d81f3c5c05e1919f4005c6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/2815083
* @preserve
**/

(Drupal => {
  Drupal.olivero = {};

  function isDesktopNav() {
    const navButtons = document.querySelector('[data-drupal-selector="mobile-buttons"]');
    return navButtons ? window.getComputedStyle(navButtons).getPropertyValue('display') === 'none' : false;
  }

  Drupal.olivero.isDesktopNav = isDesktopNav;
  const stickyHeaderToggleButton = document.querySelector('[data-drupal-selector="sticky-header-toggle"]');
  const siteHeaderFixable = document.querySelector('[data-drupal-selector="site-header-fixable"]');

  function stickyHeaderIsEnabled() {
    return stickyHeaderToggleButton.getAttribute('aria-checked') === 'true';
  }

  function setStickyHeaderStorage(expandedState) {
    const now = new Date();
    const item = {
      value: expandedState,
      expiry: now.getTime() + 20160000
    };
    localStorage.setItem('Drupal.olivero.stickyHeaderState', JSON.stringify(item));
  }

  function toggleStickyHeaderState(pinnedState) {
    if (isDesktopNav()) {
      if (pinnedState === true) {
        siteHeaderFixable.classList.add('is-expanded');
      } else {
        siteHeaderFixable.classList.remove('is-expanded');
      }

      stickyHeaderToggleButton.setAttribute('aria-checked', pinnedState);
      setStickyHeaderStorage(pinnedState);
    }
  }

  function getStickyHeaderStorage() {
    const stickyHeaderState = localStorage.getItem('Drupal.olivero.stickyHeaderState');
    if (!stickyHeaderState) return false;
    const item = JSON.parse(stickyHeaderState);
    const now = new Date();

    if (now.getTime() > item.expiry) {
      localStorage.removeItem('Drupal.olivero.stickyHeaderState');
      return false;
    }

    return item.value;
  }

  if ('IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype) {
    const fixableElements = document.querySelectorAll('[data-drupal-selector="site-header-fixable"], [data-drupal-selector="social-bar-inner"]');

    function toggleDesktopNavVisibility(entries) {
      if (!isDesktopNav()) return;
      entries.forEach(entry => {
        if (entry.intersectionRatio < 1) {
          fixableElements.forEach(el => el.classList.add('is-fixed'));
        } else {
          fixableElements.forEach(el => el.classList.remove('is-fixed'));
        }
      });
    }

    function getRootMargin() {
      let rootMarginTop = 72;
      const {
        body
      } = document;

      if (body.classList.contains('toolbar-fixed')) {
        rootMarginTop -= 39;
      }

      if (body.classList.contains('toolbar-horizontal') && body.classList.contains('toolbar-tray-open')) {
        rootMarginTop -= 40;
      }

      return `${rootMarginTop}px 0px 0px 0px`;
    }

    function monitorNavPosition() {
      const primaryNav = document.querySelector('[data-drupal-selector="site-header"]');
      const options = {
        rootMargin: getRootMargin(),
        threshold: [0.999, 1]
      };
      const observer = new IntersectionObserver(toggleDesktopNavVisibility, options);

      if (primaryNav) {
        observer.observe(primaryNav);
      }
    }

    if (stickyHeaderToggleButton) {
      stickyHeaderToggleButton.addEventListener('click', () => {
        toggleStickyHeaderState(!stickyHeaderIsEnabled());
      });
    }

    const siteHeaderInner = document.querySelector('[data-drupal-selector="site-header-inner"]');

    if (siteHeaderInner) {
      siteHeaderInner.addEventListener('focusin', () => {
        if (isDesktopNav() && !stickyHeaderIsEnabled()) {
          const header = document.querySelector('[data-drupal-selector="site-header"]');
          const headerNav = header.querySelector('[data-drupal-selector="header-nav"]');
          const headerMargin = header.clientHeight - headerNav.clientHeight;

          if (window.scrollY > headerMargin) {
            window.scrollTo(0, headerMargin);
          }
        }
      });
    }

    monitorNavPosition();
    setStickyHeaderStorage(getStickyHeaderStorage());
    toggleStickyHeaderState(getStickyHeaderStorage());
  }
})(Drupal);