1/** 2 * UMBC Nav State â role-personalized utility strip 3 * 4 * Reads the `umbc_roles` cookie set by myUMBC (30-day, refreshed on login). 5 * Format: comma-separated, priority-ordered, e.g. "faculty,staff" 6 * 7 * Replaces the server-rendered anonymous utility strip with a role-specific 8 * one client-side. PHP always renders the anonymous state; this upgrades it 9 * when a known role is detected. No WP login required. 10 * 11 * Role priority (first match wins, people can have multiple): 12 * 1. faculty 13 * 2. staff 14 * 3. graduate-student | undergraduate-student 15 * 4. cookie present, no recognised role â generic logged-in nav 16 * 5. no cookie â anonymous nav (PHP default, no JS change) 17 * 18 * To add this to another UMBC-family site, change COOKIE_NAME if needed. 19 * Everything else is self-contained. 20 */ 21 22(function () { 23 "use strict"; 24 25 var COOKIE_NAME = "umbc_roles"; 26 27 /* ------------------------------------------------------------------ 28 * Link definitions per role 29 * Each entry: [label, url, mobile-only-cta?] 30 * Shared by both desktop (.uh-utility-strip) and mobile (.mobile-utility-strip) 31 * so links only need updating in one place. 32 * ------------------------------------------------------------------ */ 33 var LINKS = { 34 "undergraduate-student": [ 35 { label: "myUMBC", url: "https://my.umbc.edu", cta: true }, 36 { label: "Directory", url: "/directory/" }, 37 { 38 label: "Undergrad Programs", 39 url: "/programs/?degree_level=undergraduate", 40 }, 41 ], 42 "graduate-student": [ 43 { label: "myUMBC", url: "https://my.umbc.edu", cta: true }, 44 { label: "Directory", url: "/directory/" }, 45 { label: "Graduate Programs", url: "/programs/?degree_level=graduate" }, 46 ], 47 faculty: [ 48 { label: "myUMBC", url: "https://my.umbc.edu", cta: true }, 49 { label: "Directory", url: "/directory/" }, 50 { label: "Make a Gift", url: "https://give.umbc.edu/campaigns/41278/donations/new?a=7548658&utm_source=umbc.edu&utm_medium=utility-nav&utm_campaign=make-a-gift" }, 51 { 52 label: "Faculty Research", 53 url: "https://umbc.discovery.academicanalytics.com", 54 }, 55 ], 56 staff: [ 57 { label: "myUMBC", url: "https://my.umbc.edu", cta: true }, 58 { label: "Directory", url: "/directory/" }, 59 { label: "Make a Gift", url: "https://give.umbc.edu/campaigns/41278/donations/new?a=7548658&utm_source=umbc.edu&utm_medium=utility-nav&utm_campaign=make-a-gift" }, 60 ], 61 member: [ 62 { label: "myUMBC", url: "https://my.umbc.edu", cta: true }, 63 { label: "Directory", url: "/directory/" }, 64 { label: "Make a Gift", url: "https://give.umbc.edu/campaigns/41278/donations/new?a=7548658&utm_source=umbc.edu&utm_medium=utility-nav&utm_campaign=make-a-gift" }, 65 ], 66 }; 67 68 /* Build HTML for the desktop strip (.uh-utility-strip). 69 Non-CTA links render as plain utility links; the CTA entry 70 becomes the gold button at the end of the strip. */ 71 function buildDesktop(links) { 72 var plain = links.filter(function (l) { 73 return !l.cta; 74 }); 75 var cta = links.filter(function (l) { 76 return l.cta; 77 })[0]; 78 var html = plain 79 .map(function (l) { 80 return ( 81 '<a href="' + l.url + '" class="uh-utility-link">' + l.label + "</a>" 82 ); 83 }) 84 .join("\n"); 85 if (cta) { 86 html += 87 '\n<a href="' + 88 cta.url + 89 '" class="uh-utility-cta">' + 90 cta.label + 91 "</a>"; 92 } 93 return html; 94 } 95 96 /* Build HTML for the mobile strip (.mobile-utility-strip) */ 97 function buildMobile(links) { 98 return links 99 .map(function (l) { 100 var cls = l.cta 101 ? "mobile-utility-link mobile-utility-link--cta" 102 : "mobile-utility-link"; 103 return ( 104 '<a href="' + l.url + '" class="' + cls + '">' + l.label + "</a>" 105 ); 106 }) 107 .join("\n"); 108 } 109 110 /* ------------------------------------------------------------------ 111 * Helpers 112 * ------------------------------------------------------------------ */ 113 function getCookie(name) { 114 var match = document.cookie.match( 115 new RegExp( 116 "(?:^|;)\\s*" + 117 name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + 118 "=([^;]*)", 119 ), 120 ); 121 return match ? decodeURIComponent(match[1]) : null; 122 } 123 124 function resolveRole(cookieValue) { 125 // Priority order â first match wins (cookie is already ordered by myUMBC) 126 var roles = cookieValue.split(",").map(function (r) { 127 return r.trim(); 128 }); 129 if (roles.indexOf("faculty") !== -1) return "faculty"; 130 if (roles.indexOf("staff") !== -1) return "staff"; 131 if (roles.indexOf("graduate-student") !== -1) return "graduate-student"; 132 if (roles.indexOf("undergraduate-student") !== -1) 133 return "undergraduate-student"; 134 return "member"; // authenticated but unrecognised role 135 } 136 137 function applyNav(role) { 138 var links = LINKS[role]; 139 if (!links) return; 140 141 var desktop = document.querySelector(".uh-utility-strip"); 142 if (desktop) { 143 // The dark-mode toggle lives inside the strip â detach it before 144 // replacing the links, then re-append the SAME node so its click 145 // listener (bound in header.php) survives the rebuild. 146 var toggle = desktop.querySelector(".dark-mode-toggle"); 147 desktop.innerHTML = buildDesktop(links); 148 if (toggle) desktop.appendChild(toggle); 149 } 150 151 var mobile = document.querySelector(".mobile-utility-strip"); 152 if (mobile) mobile.innerHTML = buildMobile(links); 153 } 154 155 /* ------------------------------------------------------------------ 156 * Boot 157 * ------------------------------------------------------------------ */ 158 function boot() { 159 var cookieValue = getCookie(COOKIE_NAME); 160 if (!cookieValue) return; // no cookie â anonymous/prospective; leave PHP nav as-is + affiliation unset 161 162 var role = resolveRole(cookieValue); 163 164 // Expose affiliation to analytics as a user-scoped dimension (read by GTM 165 // as the `user_affiliation` Data Layer Variable). Pushed client-side from 166 // the umbc_roles cookie â NOT server-rendered â so it is never baked into 167 // Pantheon's page cache. Anonymous visitors get no push (correct: they 168 // read as "prospective" / unset in GA4). See plan §11.4. 169 window.dataLayer = window.dataLayer || []; 170 window.dataLayer.push({ user_affiliation: role }); 171 172 applyNav(role); 173 } 174 175 // Runs in footer so DOM is already ready â but guard anyway 176 if (document.readyState === "loading") { 177 document.addEventListener("DOMContentLoaded", boot); 178 } else {
179 boot(); 180 } 181})();
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.