PageSourceSearch

https://pacificdataintegrators.com/assets/pdi-common/pdi-header.js?v=9

js pacificdataintegrators.com collected 2026-10-03 20:56:41 UTC 9,263 bytes, 257 lines download raw bytes

1(function () {
2  'use strict';
3
4  function toArray(list) {
5    return Array.prototype.slice.call(list || []);
6  }
7
8  function cleanPath(value) {
9    var path = value || '/';
10    try {
11      path = new URL(path, window.location.href).pathname;
12    } catch (_) {}
13    path = path.replace(/\/(?:index)?\.(?:html?|php)$/i, '/').replace(/\.(?:html?|php)$/i, '');
14    path = path.length > 1 ? path.replace(/\/$/, '') : path;
15    return decodeURIComponent(path || '/');
16  }
17
18  function initHeader(root) {
19    if (!root || root.dataset.pdiHeaderReady === 'true') return;
20    root.dataset.pdiHeaderReady = 'true';
21
22    var mobileToggle = root.querySelector('.pdi-nav__mobile-toggle');
23    var nav = root.querySelector('#pdi-primary-navigation');
24    var dropdownItems = toArray(root.querySelectorAll('.pdi-nav__item--dropdown'));
25    var toggles = toArray(root.querySelectorAll('.pdi-nav__toggle, .pdi-nav__branch-toggle'));
26    var media = window.matchMedia('(max-width: 1080px)');
27    var submenuSequence = 0;
28
29    function isMobile() {
30      return media.matches;
31    }
32
33    function directSubmenu(item) {
34      if (!item) return null;
35      return item.querySelector(':scope > .pdi-nav__submenu');
36    }
37
38    function directToggle(item) {
39      if (!item) return null;
40      return item.querySelector(':scope > .pdi-nav__toggle, :scope > .pdi-nav__branch-toggle, :scope > .pdi-nav__link-row > .pdi-nav__branch-toggle');
41    }
42
43    dropdownItems.forEach(function (item) {
44      var toggle = directToggle(item);
45      var submenu = directSubmenu(item);
46      if (!toggle || !submenu) return;
47      if (!submenu.id) {
48        submenuSequence += 1;
49        submenu.id = 'pdi-submenu-' + submenuSequence;
50      }
51      toggle.setAttribute('aria-controls', submenu.id);
52      toggle.setAttribute('aria-haspopup', 'true');
53      submenu.setAttribute('aria-hidden', 'true');
54    });
55
56    function setItemOpen(item, open, options) {
57      if (!item) return;
58      var toggle = directToggle(item);
59      var submenu = directSubmenu(item);
60      item.classList.toggle('is-open', open);
61      if (toggle) toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
62      if (submenu) submenu.setAttribute('aria-hidden', open ? 'false' : 'true');
63
64      if (!open) {
65        toArray(item.querySelectorAll('.pdi-nav__item--dropdown.is-open')).forEach(function (child) {
66          if (child !== item) setItemOpen(child, false);
67        });
68      }
69
70      if (open && options && options.focus) {
71        var focusable = toArray(submenu && submenu.querySelectorAll('a[href], button:not([disabled])'));
72        var target = options.focus === 'last' ? focusable[focusable.length - 1] : focusable[0];
73        if (target) target.focus();
74      }
75    }
76
77    function closeAll(except) {
78      dropdownItems.forEach(function (item) {
79        if (item !== except && (!except || !item.contains(except))) setItemOpen(item, false);
80      });
81    }
82
83    function setMobileOpen(open, returnFocus) {
84      root.classList.toggle('is-mobile-open', open);
85      document.body.classList.toggle('pdi-nav-open', open && isMobile());
86      if (mobileToggle) {
87        mobileToggle.setAttribute('aria-expanded', open ? 'true' : 'false');
88        mobileToggle.setAttribute('aria-label', open ? 'Close navigation menu' : 'Open navigation menu');
89      }
90      if (!open) {
91        closeAll();
92        if (returnFocus && mobileToggle) mobileToggle.focus();
93      } else if (nav) {
94        var first = nav.querySelector('a[href], button:not([disabled])');
95        if (first) window.setTimeout(function () { first.focus(); }, 0);
96      }
97    }
98
99    /* Desktop flyouts open on hover/focus and close after a short grace period.
100       The delay prevents the menu from collapsing while the pointer moves from
101       the top-level trigger into its submenu. Click behavior remains available
102       for touch devices and keyboard users. */
103    var hoverCloseDelay = 220;
104
105    function clearHoverTimer(item) {
106      if (!item || !item._pdiHoverTimer) return;
107      window.clearTimeout(item._pdiHoverTimer);
108      item._pdiHoverTimer = null;
109    }
110
111    function closeSiblingDropdowns(item) {
112      var siblings = item && item.parentElement ? item.parentElement.children : [];
113      toArray(siblings).forEach(function (sibling) {
114        if (sibling !== item && sibling.classList && sibling.classList.contains('pdi-nav__item--dropdown')) {
115          clearHoverTimer(sibling);
116          setItemOpen(sibling, false);
117        }
118      });
119    }
120
121    dropdownItems.forEach(function (item) {
122      item.addEventListener('mouseenter', function () {
123        if (isMobile()) return;
124        clearHoverTimer(item);
125        closeSiblingDropdowns(item);
126        setItemOpen(item, true);
127      });
128
129      item.addEventListener('mouseleave', function () {
130        if (isMobile()) return;
131        clearHoverTimer(item);
132        item._pdiHoverTimer = window.setTimeout(function () {
133          var active = document.activeElement;
134          if (!item.matches(':hover') && !(active && item.contains(active))) {
135            setItemOpen(item, false);
136          }
137        }, hoverCloseDelay);
138      });
139
140      item.addEventListener('focusin', function () {
141        if (isMobile()) return;
142        clearHoverTimer(item);
143        closeSiblingDropdowns(item);
144        setItemOpen(item, true);
145      });
146
147      item.addEventListener('focusout', function () {
148        if (isMobile()) return;
149        clearHoverTimer(item);
150        item._pdiHoverTimer = window.setTimeout(function () {
151          if (!item.contains(document.activeElement) && !item.matches(':hover')) {
152            setItemOpen(item, false);
153          }
154        }, hoverCloseDelay);
155      });
156    });
157
158    toggles.forEach(function (toggle) {
159      toggle.addEventListener('click', function (event) {
160        event.preventDefault();
161        event.stopPropagation();
162        var item = toggle.closest('.pdi-nav__item--dropdown');
163        if (!item) return;
164        var shouldOpen = !item.classList.contains('is-open');
165        var siblings = item.parentElement ? item.parentElement.children : [];
166        toArray(siblings).forEach(function (sibling) {
167          if (sibling !== item && sibling.classList && sibling.classList.contains('pdi-nav__item--dropdown')) {
168            setItemOpen(sibling, false);
169          }
170        });
171        setItemOpen(item, shouldOpen);
172      });
173
174      toggle.addEventListener('keydown', function (event) {
175        var item = toggle.closest('.pdi-nav__item--dropdown');
176        if (!item) return;
177        if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
178          event.preventDefault();
179          setItemOpen(item, true, {focus: event.key === 'ArrowUp' ? 'last' : 'first'});
180        }
181      });
182    });
183
184    if (mobileToggle) {
185      mobileToggle.addEventListener('click', function () {
186        setMobileOpen(!root.classList.contains('is-mobile-open'), false);
187      });
188    }
189
190    root.addEventListener('keydown', function (event) {
191      var target = event.target;
192      var item = target && target.closest ? target.closest('.pdi-nav__item--dropdown') : null;
193
194      if (event.key === 'Escape') {
195        event.preventDefault();
196        if (item && item.classList.contains('is-open')) {
197          var toggle = directToggle(item);
198          if (toggle) toggle.focus();
199          // Focusin opens desktop menus; move focus before closing so Escape
200          // does not immediately reopen the branch.
201          setItemOpen(item, false);
202          return;
203        }
204        closeAll();
205        if (root.classList.contains('is-mobile-open')) setMobileOpen(false, true);
206        return;
207      }
208
209      if (event.key === 'ArrowLeft' && item && !isMobile()) {
210        var parentItem = item.parentElement && item.parentElement.closest('.pdi-nav__item--dropdown');
211        if (parentItem) {
212          event.preventDefault();
213          var branchToggle = directToggle(item);
214          if (branchToggle) branchToggle.focus();
215          setItemOpen(item, false);
216        }
217      }
218    });
219
220    toArray(root.querySelectorAll('a[href]')).forEach(function (link) {
221      var linkPath;
222      try {
223        var url = new URL(link.href, window.location.href);
224        if (url.origin !== window.location.origin) return;
225        linkPath = cleanPath(url.pathname);
226      } catch (_) {
227        return;
228      }
229      if (linkPath === cleanPath(window.location.pathname)) {
230        link.setAttribute('aria-current', 'page');
231      }
232      link.addEventListener('click', function () {
233        if (isMobile()) setMobileOpen(false, false);
234      });
235    });
236
237    document.addEventListener('click', function (event) {
238      if (!root.contains(event.target)) {
239        closeAll();
240        if (isMobile()) setMobileOpen(false, false);
241      }
242    });
243
244    function handleMediaChange() {
245      if (!isMobile()) setMobileOpen(false, false);
246    }
247    if (typeof media.addEventListener === 'function') media.addEventListener('change', handleMediaChange);
248    else if (typeof media.addListener === 'function') media.addListener(handleMediaChange);
249  }
250
251  function boot() {
252    initHeader(document.getElementById('pdi-common-header'));
253  }
254
255  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot, {once: true});
256  else boot();
257})();

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.