PageSourceSearch

https://www.mclaren.org/Uploads/JS/bootstrap/theme/block/branch-nav.js

js mclaren.org collected 2026-09-24 09:30:53 UTC 4,692 bytes, 159 lines download raw bytes

1(function () {
2  // Audience prefixes that Centralpoint may prepend to hrefs
3  var AUDIENCE_PREFIX_RE = /^\/(?:main|development|staging|stage|test|qa|preview|prod)\b/i;
4
5  function stripAudience(pathname) {
6    if (!pathname) return "";
7    // remove /main or /development etc
8    var p = pathname.replace(AUDIENCE_PREFIX_RE, "");
9    // ensure leading slash
10    if (p && p.charAt(0) !== "/") p = "/" + p;
11    return p;
12  }
13
14  function normPath(p) {
15    try {
16      var u = new URL(p, location.origin);
17      var clean = stripAudience(u.pathname);
18      return clean.replace(/\/+$/, "");
19    } catch (e) {
20      var raw = (p || "").split("#")[0].split("?")[0];
21      raw = stripAudience(raw);
22      return raw.replace(/\/+$/, "");
23    }
24  }
25
26  var out = document.getElementById("branch-nav");
27  var tree = document.getElementById("branch-nav-source");
28  if (!out || !tree) return;
29
30  var currentPath = normPath(location.pathname);
31
32  var navWrap = out.closest("nav");
33  var branchRootAttr = navWrap ? navWrap.getAttribute("data-branch-root") : null;
34  var branchPath = branchRootAttr ? normPath(branchRootAttr) : null;
35
36  var links = tree.querySelectorAll("a[href]");
37
38  function buildFromSiblingUl(a) {
39    var li = a && a.closest("li");
40    var ul = li && li.parentElement;
41    if (!ul) return null;
42    return ul.cloneNode(true);
43  }
44
45  function findLinkByPath(path) {
46    if (!path) return null;
47    for (var i = 0; i < links.length; i++) {
48      var p = normPath(links[i].getAttribute("href"));
49      if (!p) continue;
50      if (p === path) return links[i];
51    }
52    return null;
53  }
54
55  function findCurrentLink() {
56    for (var i = 0; i < links.length; i++) {
57      if (normPath(links[i].getAttribute("href")) === currentPath) return links[i];
58    }
59    return null;
60  }
61
62  // If no branch root provided, choose the deepest ancestor of currentPath in the nav tree
63  function autoDetectBranchRoot() {
64    var best = null;
65    var bestLen = -1;
66
67    for (var i = 0; i < links.length; i++) {
68      var p = normPath(links[i].getAttribute("href"));
69      if (!p) continue;
70
71      if (currentPath === p || currentPath.indexOf(p + "/") === 0) {
72        if (p.length > bestLen) {
73          best = links[i];
74          bestLen = p.length;
75        }
76      }
77    }
78
79    // If best is current page, prefer its parent
80    if (best && normPath(best.getAttribute("href")) === currentPath) {
81      var li = best.closest("li");
82      var parentLi = li && li.parentElement && li.parentElement.closest("li");
83      var parentA = parentLi ? parentLi.querySelector(":scope > a[href]") : null;
84      if (parentA) best = parentA;
85    }
86
87    return best ? normPath(best.getAttribute("href")) : null;
88  }
89
90  if (!branchPath) branchPath = autoDetectBranchRoot();
91
92  var branchLink = findLinkByPath(branchPath);
93
94  var built = null;
95
96  // Prefer immediate children of the branch root
97  if (branchLink) {
98    var li = branchLink.closest("li");
99    if (li) {
100      var childUl = li.querySelector(":scope > ul");
101      if (!childUl && li.nextElementSibling && li.nextElementSibling.tagName === "UL") {
102        childUl = li.nextElementSibling;
103      }
104      if (childUl) {
105        built = childUl.cloneNode(true);
106      } else {
107        built = buildFromSiblingUl(branchLink);
108      }
109    }
110  }
111
112  // Fallback to current page siblings
113  if (!built) {
114    var currentA = findCurrentLink();
115    if (currentA) built = buildFromSiblingUl(currentA);
116  }
117
118  out.innerHTML = "";
119
120  if (built) {
121    if (built.tagName === "UL") {
122      while (built.firstChild) out.appendChild(built.firstChild);
123    } else {
124      out.appendChild(built);
125    }
126
127    // Mark "current" — exact match if possible, otherwise mark the closest ancestor in this list
128    var outLinks = out.querySelectorAll("a[href]");
129    var exact = null;
130    for (var k = 0; k < outLinks.length; k++) {
131      if (normPath(outLinks[k].getAttribute("href")) === currentPath) {
132        exact = outLinks[k];
133        break;
134      }
135    }
136
137    if (exact) {
138      exact.setAttribute("aria-current", "page");
139    } else {
140      // pick the deepest link whose path is a prefix of currentPath
141      var bestLink = null;
142      var bestLen2 = -1;
143      for (var j = 0; j < outLinks.length; j++) {
144        var p2 = normPath(outLinks[j].getAttribute("href"));
145        if (!p2) continue;
146
147        if (currentPath === p2 || currentPath.indexOf(p2 + "/") === 0) {
148          if (p2.length > bestLen2) {
149            bestLink = outLinks[j];
150            bestLen2 = p2.length;
151          }
152        }
153      }
154      if (bestLink) bestLink.setAttribute("aria-current", "page");
155    }
156  } else {
157    out.innerHTML = '<li class="small text-muted">
157No section links found.</li>';
158  }
159})();

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.