1 2<!DOCTYPE html> 3<html lang="en" xml:lang="en"> 4<head>
4<script src="/bsolude-is-wellow-The-life-in-make-good-man-a-ha" async></script>
4 5
5<script> 6 window.dataLayer = window.dataLayer || []; 7 function gtag() {{ dataLayer.push(arguments); }} 8 </script>
8 9 10 <meta charset="UTF-8"> 11 <title>Your cart | CU Presents</title> 12 <meta name="description" content=""> 13 <meta name="keywords" content=""> 14 <meta name="author" content=""> 15 16 17 18 <link href="https://production.tnew-assets.com/tnew/public/tnew.edd191fca8c449f937a7.css" rel="stylesheet"/> 19 20 21 <link href="https://production.tnew-assets.com/tnew/public/tnew-cart.25fb2ad4462092e058fa.css" rel="stylesheet" type="text/css" /> 22 23 24 25 <!-- BEGIN INJECTED HEAD --> 26 27 <style id="hide-content-style"> 28 /* Hide content until the page is fully loaded */ 29 body, 30 #content { 31 opacity: 0 !important; 32 } 33 </style> 34 35 <style> 36 /* Hot Fixes */ 37 aside.tn-admin-preview-banner.alert.alert-warning { 38 display: none; 39 } 40 41 /* 42 @media (max-width: 781px) { 43 .tn-utility-nav-cart-controls-section div.tn-utility-nav-cart-timer { 44 top: 55px !important; 45 } 46 } */ 47 48 /* Only the Search Modal related styles are here - the rest of the styles are in the style.css file */ 49 #content { 50 position: relative; 51 /* Needed for absolute positioning of the search modal */ 52 } 53 54 .search-modal { 55 position: absolute; 56 left: 50%; 57 top: 2px; 58 /* Aligns the left edge of the modal to the horizontal center of the viewport */ 59 right: calc(max(0px, (100vw - min(1280px, 100vw))) / 2); 60 /* Aligns the right edge of the contents */ 61 background: white; 62 /* border-bottom: 2px solid #ceb87c; */ 63 /* box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); */ 64 z-index: 999; 65 max-height: 0; 66 overflow: hidden; 67 transition: 68 max-height 0.3s ease, 69 opacity 0.3s ease; 70 opacity: 0; 71 display: none; 72 margin-left: auto; 73 } 74 75 @media (max-width: 781px) { 76 .search-modal { 77 left: 0; 78 } 79 } 80 81 @media (min-width: 1280px) { 82 .search-modal { 83 position: absolute; 84 left: 50%; 85 right: 0; 86 } 87 } 88 89 body.search-open .search-modal { 90 max-height: 100px; 91 opacity: 1; 92 display: block; 93 } 94 95 .search-modal__container { 96 padding-right: 20px; 97 width: 100%; 98 } 99 100 @media (max-width: 768px) { 101 .search-modal__container { 102 padding: 0 10px; 103 } 104 105 .search-input-group { 106 margin-left: -6px; 107 } 108 } 109 110 .search-modal__content { 111 display: flex; 112 align-items: center; 113 gap: 5px; 114 } 115 116 .search-form { 117 display: flex; 118 align-items: center; 119 position: relative; 120 flex-grow: 1; 121 width: 100%; 122 } 123 124 .search-input-group { 125 position: relative; 126 display: flex; 127 align-items: center; 128 width: 100%; 129 padding: 4px 4px 4px 0; 130 } 131 132 .search-submit { 133 padding: 0 !important; 134 margin: 0 !important; 135 height: 39px; 136 width: 40px; 137 } 138 139 .search-submit:focus { 140 position: absolute !important; 141 } 142 143 .search-input { 144 width: 100%; 145 border: 2px solid #ceb87c; 146 /* border-radius: 6px; */ 147 border-radius: 0; 148 font-size: 16px; 149 padding: 6px; 150 margin: 6px; 151 } 152 153 .search-input:focus { 154 border-color: #b8a56b; 155 /* box-shadow: 0 0 0 3px rgba(206, 184, 124, 0.2); */ 156 outline: 2px solid var(--tn-link-color-hover); 157 outline-offset: 2px; 158 } 159 160 .search-input::placeholder { 161 color: #888; 162 } 163 164 .search-submit { 165 position: absolute; 166 right: 10px; 167 top: 10px; 168 background: none; 169 border: none; 170 cursor: pointer; 171 padding: 8px; 172 color: #ceb87c; 173 } 174 175 .search-close { 176 background: none; 177 border: none; 178 font-size: 24px; 179 cursor: pointer; 180 color: #000; 181 padding: 8px; 182 height: 39px; 183 line-height: 25px; 184 } 185 </style> 186 187 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 188 189 190 <link id="favicon" rel="shortcut icon" type="image/x-icon" href=""> 191 192 <!--
192<script type="text/javascript" src="//translate.google.com"></script>
192 --> 193 194 <!-- This allows Clarity to send data back to Microsoft servers - it s now loaded via Google Tag Manager 195 <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' https://www.clarity.ms; connect-src 'self' https://*.clarity.ms https://c.bing.com;"> 196 --> 197 198 <!-- Google Translate --> 199
199<script> 200 // Robust global init for Google Translate. The external translate script 201 // invokes `googleTranslateElementInit` when it loads (cb parameter). 202 // This function ensures the container exists and only initializes the 203 // widget when the API is available. It is safe to call multiple times. 204 window.googleTranslateElementInit = function () { 205 try { 206 // Only initialize when the widget API is available and theme matches 207 if (window.theme && window.theme !== 'cupresents') return; 208 209 if (window.google && google.translate && typeof google.translate.TranslateElement === 'function') { 210 try { 211 // Make the container visible so Translate can render into it. 212 var el = document.getElementById('google_translate_element'); 213 new google.translate.TranslateElement({ 214 pageLanguage: 'en', 215 includedLanguages: 'en,es,zh-CN,fr,de,ru,it,ko,vi,lo,ne,ja,bo,tl,ar', 216 autoDisplay: false 217 }, 'google_translate_element'); 218 // Mark that the widget has initialized and expose the select 219 try { 220 // Mark that the widget has initialized. We avoid probing the 221 // injected select directly (it's unreliable across browsers 222 // and may be inside an iframe). Instead we listen for 223 // postMessage events from Google's iframe which indicate 224 // when the language actually changes. 225 window._translateReady = true; 226 // If any language requests were queued before init, keep 227 // them in the queue for other parts of the code to act on. 228 // (We do NOT attempt to set the internal select here.) 229 } catch (e) { window._translateReady = false; } 230 231 // If any language requests were queued before init, apply them now 232 try { 233 if (window._translateQueue && window._translateQueue.length && window._translateSelect) { 234 // Apply the last queued request (user's latest choice) 235 const req = window._translateQueue.pop(); 236 try { window._translateSelect.value = req.langCode; } catch (e) {} 237 try { window._translateSelect.dispatchEvent(new Event('change', { bubbles: true })); } catch (e) {} 238 // Update anchor to match queued language name (best-effort) 239 try { 240 var _anchor2 = document.getElementById('langAnchor'); 241 if (_anchor2) _anchor2.textContent = req.langName || req.langCode; 242 } catch (e) { } 243 // Clear the queue 244 window._translateQueue = []; 245 } 246 } catch (e) { } 247 // Observe the injected container for changes so we can detect 248 // when Google applies the user's last-chosen language (often via iframe communication). 249 try { 250 // Expose a global language map so other parts of the 251 // page can read friendly names without probing Google's 252 // injected controls. Keys match the codes in 253 // `includedLanguages` passed to the widget. 254 window._languageMap = { 255 'en': 'English', 'es': 'Spanish', 'zh-CN': 'Chinese', 'fr': 'French', 'de': 'German', 256 'ru': 'Russian', 'it': 'Italian', 'ko': 'Korean', 'vi': 'Vietnamese', 'lo': 'Laos', 257 'ne': 'Nepali', 'ja': 'Japanese', 'bo': 'Tibetan', 'tl': 'Tagalog', 'ar': 'Arabic' 258 }; 259 var knownCodes = Object.keys(window._languageMap); 260 } catch (e) { } 261 } catch (e) { 262 console && console.warn && console.warn('googleTranslateElementInit: failed to instantiate widget', e); 263 } 264 } else { 265 // API not present yet â the external script should call us again after it loads. 266 } 267 } catch (e) { 268 console && console.warn && console.warn('googleTranslateElementInit failed', e); 269 } 270 }; 271 </script>
271 272
272<script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit" defer=""></script>
272 273 <link type="text/css" rel="stylesheet" charset="UTF-8" href="https://www.gstatic.com/_/translate_http/_/ss/k=translate_http.tr.2f3WBw8L4SI.L.W.O/am=AAQD/d=0/rs=AN8SPfrXXtxuFpMMBoYgp93jo68L3iC3ZQ/m=el_main_css"> 274
274<script type="text/javascript" charset="UTF-8" src="https://translate.googleapis.com/_/translate_http/_/js/k=translate_http.tr.en_US.V5VW1UIy3kI.O/am=AAAQ/d=1/exm=el_conf/ed=1/rs=AN8SPfqkzTqvP8OCEEDeVdyetOdLmZ90wQ/m=el_main"></script>
274 275 276
276<script> 277 // Set URL & path constants 278 window.url = window.location.href; 279 window.urlPath = window.location.pathname; 280 window.prodTnewURL = "https://tickets.cupresents.org/"; 281 window.testTnewURL = "https://bold-tnew-test.tnhs.cloud/"; 282 window.prodFrontURL = "https://cupresents.org/"; 283 window.testFrontURL = "https://cupresents-dev.org/"; // or https://cupresents-dev.org/ 284 window.prodTnewServer = "https://cupresents-test.org/"; 285 window.testTnewServer = "https://cupresents-dev.org/"; // or https://cupresents-dev.org/ 286 window.prodTnewFolder = "cup-tnew-templates/" 287 window.testTnewFolder = "cup-tnew-templates/" 288 window.serverUrl = getServerUrl(); 289 window.classList = ""; 290 291 // Set URLs based on the environment 292 // TO DO: IMPORTANT: Change back to test once testing is completed. 293 if ( 294 window.serverUrl == "https://cupresents-dev.org/" || 295 window.serverUrl == "https://bold-tnew-test.tnhs.cloud/" 296 ) { 297 window.frontURL = window.testFrontURL; 298 window.tnewURL = window.testFrontURL; 299 // Tessitura API not working due to CORS issues, so we are using the CUPresents Tessitura API Proxy API 300 // which has CORS enabled and points to the same database 301 // window.apiURL = "https://ucobouusco0webtest.tnhs.cloud/tessitura/api/"; 302 window.apiURL = "https://api.cupresents-dev.org/"; 303 window.tnewServer = window.testTnewServer; 304 window.tnewFolder = window.testTnewFolder; 305 } 306 if ( 307 window.serverUrl == "https://cupresents.org/" || 308 window.serverUrl == "https://cupresents-test.org/" || 309 window.serverUrl == "https://tickets.cupresents.org/" 310 ) { 311 window.frontURL = window.prodFrontURL; 312 window.tnewURL = window.prodFrontURL; 313 // Tessitura API not working due to CORS issues, so we are using the CUPresents Tessitura API Proxy API 314 // which has CORS enabled and points to the same database 315 // window.apiURL = "https://ucobouusco0webprod.tnhs.cloud/tessitura/api/"; 316 window.apiURL = "https://api.cupresents.org/"; 317 window.tnewServer = window.prodTnewServer; 318 window.tnewFolder = window.prodTnewFolder; 319 } 320 321 // Set favicon dynamically 322 const favicon = document.getElementById("favicon"); 323 //if (favicon) favicon.href = window.tnewURL + window.tnewFolder + "images/cupresents.avif"; 324 if (favicon) favicon.href = window.tnewServer + window.tnewFolder + "images/cupresents.avif"; 325 326 //const cssFile = window.tnewURL + window.tnewFolder + "css/styles.css?v=1790203397"; 327 const cssFile = window.tnewServer + window.tnewFolder + "css/styles.css?v=1790203397"; 328 if (!document.querySelector('link[rel="stylesheet"][href="' + cssFile + '"]')) { 329 const l = document.createElement("link"); 330 l.rel = "stylesheet"; 331 l.type = "text/css"; 332 l.href = cssFile; 333 document.head.appendChild(l); 334 } 335 336 // Check theme URL parameter and tnew-theme cookie 337 var theme = getQueryParam("theme"); // Default to the theme that cooresponds to the host website 338 if (theme == "null") { 339 theme = "cupresents"; 340 // redirect to the same url except change the theme parameter 341 const url = new URL(window.location.href); 342 url.searchParams.set("theme", theme); 343 history.replaceState(null, '', url.toString()); 344 } 345 346 if (theme == null) { 347 var referrer = document.referrer; 348 if ((referrer.includes("cupresents")) && (!referrer.includes("tickets.cupresents"))) { // includes both cupresents.org and cupresents-test.org - but not tickets.cupresents.org 349 theme = "cupresents"; 350 } else if (referrer.includes("macky.colorado.edu")) { 351 theme = "macky"; 352 } 353 if (theme == null) { 354 theme = getCookie("tnew-theme"); 355 } 356 if ((urlPath) && (!urlPath.includes("account/login")) && (!urlPath.includes("account/tokenlogin"))) { 357 const url = new URL(window.location.href); 358 url.searchParams.set("theme", theme); 359 history.replaceState(null, '', url.toString()); 360 } 361 } 362 363 // ** Set theme to cupresents if on /packages/renewals page 364 if (window.urlPath.startsWith("/packages/renewals")) { 365 theme = "cupresents"; 366 } else { 367 const returnUrl = getQueryParam("ReturnUrl"); 368 if ((returnUrl) && (returnUrl == "/packages/renewals")) { 369 theme = "cupresents"; 370 } 371 } 372 373 window.classList = setClassList(window.urlPath); 374 375 // ** Set theme to cupresents if on cupresents performance page 376 if (window.classList.includes("performance") && theme == "macky") { 377 // We need to override the macky theme on cupresents performance pages in case the perfromance is in bookmarks or shared links 378 const prodPerformanceSeasonIds = [ 379 3229, 3230, 3231, 3232, 3248, 3249, 3250, 3251, 3259, 3267, 3268, 3269, 380 3271, 3272, 3273, 3284, 3285, 3286, 3304, 3305, 3306, 3342, 3344, 3345, 381 3346, 3372, 3374, 3377, 3378, 3379, 3380, 3443, 382 ]; 383 // if the first segment of the url path is found in prodPerformanceSeasonIds, set theme to cupresents 384 const pathSegments = window.urlPath 385 .split("/") 386 .filter((segment) => segment.length > 0); 387 if (pathSegments.length > 0) { 388 const firstSegment = parseInt(pathSegments[0], 10); 389 if (prodPerformanceSeasonIds.includes(firstSegment)) { 390 theme = "cupresents"; 391 } 392 } 393 } 394 395 if (theme == null) { 396 theme = "cupresents"; // Default theme if none is found 397 }
398 setCookie("tnew-theme", theme, 7); // Cookie expires in 7 days 399 400 // Load Google Tag Manager only for the cupresents theme 401 try { 402 if (theme === 'cupresents') {
vendor: 472 bytes, lines 402-407
402 403 (function (w, d, s, l, i) { 404 w[l] = w[l] || []; w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' }); 405 var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; 406 j.async = true; j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f); 407 })(window, document, 'script', 'dataLayer', '
407GTM-MW48BWK
vendor: 23 bytes, lines 407-409
407'); 408 409
409// This is the trigger function for the custom menu 410 function translateLanguage(langCode, langName) { 411 // Update your menu label to show the selected language 412 const anchor = document.getElementById('langAnchor'); 413 if (anchor) anchor.innerText = langName; 414 415 // (No persistence written here â persistence handled elsewhere) 416 417 // Assume the translate select is present and dispatch events once. 418 try { 419 // If the internal cached select is available, use it 420 var sel = window._translateSelect || document.querySelector('#google_translate_element select') || document.querySelector('.goog-te-combo'); 421 if (!sel) { 422 // Queue the request for the widget to handle after init 423 window._translateQueue = window._translateQueue || []; 424 window._translateQueue.push({ langCode: langCode, langName: langName }); 425 console && console.debug && console.debug('[translateLanguage] queued language request', langCode); 426 return true; 427 } 428 429 sel.value = langCode; 430 const eventTypes = ['input', 'change']; 431 eventTypes.forEach((type) => { 432 try { 433 let ev; 434 if (typeof Event === 'function') ev = new Event(type, { bubbles: true }); 435 else { ev = document.createEvent('HTMLEvents'); ev.initEvent(type, true, false); } 436 sel.dispatchEvent(ev); 437 } catch (e) { } 438 }); 439 440 if (sel.value != "") document.body.classList.add('googtrans'); 441 442 try { 443 const opt = Array.from(sel.options || []).find(o => o.value === langCode || (o.value && o.value.indexOf && o.value.indexOf(langCode) !== -1)); 444 if (opt && opt.click) opt.click(); 445 } catch (e) { } 446 447 return true; 448 } catch (err) { 449 console && console.warn && console.warn('translateLanguage failed', err); 450 return false; 451 } 452 } 453 454 // Remove Google Translate voting infrastructure to prevent WAVE false positives 455 document.addEventListener('DOMContentLoaded', function () { 456 const gtPane = document.getElementById('goog-gt-votingHiddenPane'); 457 if (gtPane) { 458 gtPane.remove(); 459 } 460 }); 461 } 462 } catch (e) { 463 console && console.warn && console.warn('GTM loader failed', e); 464 } 465 466 document.addEventListener("DOMContentLoaded", async () => { 467 468 if (window.classList.length > 0) { 469 const tokens = window.classList.split(/\s+/); 470 for (let i = 0; i < tokens.length; i++) { 471 const token = tokens[i]; 472 if (token) { 473 document.body.classList.add(token); 474 } 475 } 476 } 477 478 // Add the theme as a class to the body element 479 document.body.classList.add("theme-" + theme); 480 481 //await injectContent(window.tnewURL + window.tnewFolder); 482 await injectContent(window.tnewServer + window.tnewFolder); 483 484 // Load JavaScript as external file 485 (function () { 486 const s = document.createElement('script'); 487 s.defer = true; 488 s.src = window.tnewServer + window.tnewFolder + "scripts/index.min.js?v=1790203397"; 489 document.head.appendChild(s); 490 })(); 491 492 const contentDiv = document.getElementById("content"); 493 if (contentDiv) { 494 contentDiv.classList.add("loaded"); 495 // Remove the style block that hides #content 496 const hideStyle = document.getElementById("hide-content-style"); 497 if (hideStyle) hideStyle.parentNode.removeChild(hideStyle); 498 } 499 500 // Ensure the global init function is invoked for this theme. The 501 // real initialization happens inside `window.googleTranslateElementInit`. 502 try { 503 if (typeof window.googleTranslateElementInit === 'function') { 504 // If the API is already loaded, this will instantiate immediately. 505 // Otherwise the external translate script will call the global 506 // callback again when it finishes loading. 507 window.googleTranslateElementInit(); 508 } 509 } catch (e) { 510 console && console.warn && console.warn('invoke googleTranslateElementInit failed', e); 511 } 512 513 // Read `googtrans` cookie (if present) and pre-apply the saved 514 // language to the UI to avoid the English->translated flicker. 515 try { 516 (function applySavedTranslateFromCookie(){ 517 var g = getCookie('googtrans'); 518 if (!g) return; 519 // Add body class to mark that a translation is in effect 520 try { document.body.classList.add('googtrans'); } catch (e) { }
521 var segs = g.split('/').filter(Boolean); 522 var target = segs.length ? segs[segs.length - 1] : null; 523 if (!target) return; 524 var lang = target; 525 var name = (window._languageMap && window._languageMap[lang]) ? window._languageMap[lang] : lang; 526 var anchor = document.getElementById('langAnchor'); 527 if (anchor) anchor.innerText = name; 528 if (typeof translateLanguage === 'function') { 529 try { translateLanguage(lang, name); } catch (e) { } 530 } else { 531 window._translateQueue = window._translateQueue || []; 532 window._translateQueue.push({ langCode: lang, langName: name }); 533 } 534 })(); 535 } catch (e) { } 536 }); 537 538 // ** Function to get the protocol and host from the current URL - needed for setting global variables ** 539 function getServerUrl() { 540 const url = window.location.href; 541 // Extract the server URL from the full URL 542 const serverUrl = url.split("/").slice(0, 3).join("/"); // Get the protocol and host 543 return serverUrl + "/"; 544 } 545 546 // ** Function to get a query parameter from the full URL or nested query strings ** 547 function getQueryParam(param) { 548 const urlParams = new URLSearchParams(window.location.search); 549 // First check if the parameter exists directly in the main query string 550 if (urlParams.has(param)) { 551 return urlParams.get(param); 552 } 553 // If not found, check for nested query strings, such as within "ReturnUrl" 554 const returnUrl = urlParams.get("ReturnUrl"); 555 if (returnUrl) { 556 // Extract the query string part of returnUrl 557 const queryString = returnUrl.split("?")[1]; // Get everything after the "?" 558 if (queryString) { 559 const nestedParams = new URLSearchParams(queryString); 560 return nestedParams.get(param); 561 } 562 } 563 // Return null if the parameter is not found 564 return null; 565 } 566 567 // ** Function to get a cookie by name ** 568 function getCookie(name) { 569 var nameEQ = name + "="; 570 var ca = document.cookie.split(";"); 571 for (var i = 0; i < ca.length; i++) { 572 var c = ca[i]; 573 while (c.charAt(0) === " ") c = c.substring(1, c.length); 574 if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); 575 } 576 return null; 577 } 578 579 // ** Function to set a cookie ** 580 function setCookie(name, value, days, hours = 0, minutes = 0) { 581 var expires = ""; 582 if (days || hours || minutes) { 583 var date = new Date(); 584 date.setTime( 585 date.getTime() + 586 days * 24 * 60 * 60 * 1000 + 587 hours * 60 * 60 * 1000 + 588 minutes * 60 * 1000 589 ); 590 expires = "; expires=" + date.toUTCString(); 591 } 592 document.cookie = name + "=" + (value || "") + expires + "; path=/"; 593 } 594 595 // ** Function to set body class based on URL path ** 596 function setClassList(urlPath) { 597 var classList = ""; 598 if (urlPath) { 599 // Change the urlPath, replacing '/' with '-' and removing the leading and trailing slashes 600 classList = urlPath.replace(/\//g, "-").replace(/^-|-$/g, ""); 601 if (urlPath === "/") { 602 classList = "events"; 603 } 604 // Split the path to check for three segments (e.g., ['', 'cart', 'receipt', '12345']) 605 const pathSegments = urlPath.split("/").filter(Boolean); // removes empty strings 606 607 //If the first segment is "cart", let's add the class 'cart' to the body now 608 if (pathSegments[0] === "cart") { 609 classList = classList + " cart"; 610 if (pathSegments[1] === "receipt") { 611 classList = classList + " cart-receipt"; 612 } 613 } else if (pathSegments[0] === "account") { 614 classList = classList + " account"; 615 } 616 617 // Cart Receipt Page: Only remove the last numeric segment if there are at least 3 segments and the last is numeric 618 if ( 619 pathSegments.length >= 3 && 620 /^\d+$/.test(pathSegments[pathSegments.length - 1]) 621 ) { 622 classList = classList.replace(/-\d+$/, ""); 623 } 624 625 // Performance Page: For pages with only 1 segment, which is numeric, assign "performance" to classList 626 if (pathSegments.length === 1 && /^\d+$/.test(pathSegments[0])) { 627 classList = "performance"; 628 } 629 // Performance Page: For pages with only 2 segments, each being numeric, assign "performance" to classList 630 if ( 631 pathSegments.length === 2 && 632 /^\d+$/.test(pathSegments[0]) && 633 /^\d+$/.test(pathSegments[1]) 634 ) { 635 classList = "performance"; 636 } 637 // Performance Page: For paths like /events/detail/3290 (3 segments: events, detail, numeric) 638 if ( 639 pathSegments.length === 3 && 640 pathSegments[0] === "events" && 641 pathSegments[1] === "detail" && 642 /^\d+$/.test(pathSegments[2]) 643 ) { 644 classList = "performance"; 645 } 646 // Performance Page: For paths like /events/detail/3290/3291 (4 segments: events, detail, numeric, numeric) 647 if ( 648 pathSegments.length === 4 && 649 pathSegments[0] === "events" && 650 pathSegments[1] === "detail" && 651 /^\d+$/.test(pathSegments[2]) && 652 /^\d+$/.test(pathSegments[3]) 653 ) { 654 classList = "performance"; 655 } 656 } 657 return (classList); 658 } 659 660 // ** Function to dynamically inject content into specific placeholders ** 661 async function injectContent(themeURL) { 662 window.TNEW_BUILD = "1790203397"; // Be sure to use double quotes here. Updated automatically on each deploy. 663 664 const injectHeadFragment = (html) => { 665 const parser = new DOMParser(); 666 const doc = parser.parseFromString(html, "text/html"); 667 const nodes = doc.head ? Array.from(doc.head.childNodes) : []; 668 if (!nodes.length) return 0; 669 670 let injectedCount = 0; 671
672 nodes.forEach((node) => { 673 document.head.appendChild(node.cloneNode(true)); 674 injectedCount++; 675 }); 676 677 return injectedCount; 678 }; 679 680 /* replace fetchWithCache with this improved variant */ 681 const fetchWithCache = async (url, opts = {}) => { 682 const key = `tnew:${window.TNEW_BUILD}:${url}`; // versioned key prevents stale caches 683 try { 684 const cached = sessionStorage.getItem(key); 685 if (cached) return cached; 686 } catch (e) { 687 // sessionStorage unavailable or quota exceeded â continue to network fetch 688 } 689 690 const res = await fetch(url, { cache: "no-cache", ...opts }); 691 if (!res.ok) throw new Error(`Failed to fetch ${url}: ${res.status}`); 692 const txt = await res.text(); 693 694 try { 695 // avoid storing very large strings (safety check) 696 if (txt.length < 200000) sessionStorage.setItem(key, txt); 697 } catch (e) { 698 // ignore quota/other errors â don't break rendering 699 } 700 return txt; 701 }; 702 703 try { 704 const headInject = document.getElementById("head-inject"); 705 if (headInject) { 706 const url = `${themeURL}${theme}-theme-header.html?v=${window.TNEW_BUILD}`; 707 const headerHtml = await fetchWithCache(url); 708 injectHeadFragment(headerHtml); 709 headInject.innerHTML = ""; 710 } 711 712 const bodyTopInject = document.getElementById("body-top-inject"); 713 if (bodyTopInject) { 714 const url = `${themeURL}${theme}-theme-body-top.html?v=${window.TNEW_BUILD}`; 715 bodyTopInject.innerHTML = await fetchWithCache(url); 716 } 717 718 const footerInject = document.getElementById("footer-inject"); 719 if (footerInject) { 720 const url = `${themeURL}${theme}-theme-footer.html?v=${window.TNEW_BUILD}`; 721 footerInject.innerHTML = await fetchWithCache(url); 722 } 723 } catch (error) { 724 console.error("Error injecting content:", error); 725 } finally { 726 // Remove loading indicator class when injection completes 727 try { 728 document.documentElement.classList.remove("js-loading"); 729 } catch (e) { } 730 } 731 } 732 733 // ===== Menu caret / submenu toggle module ===== 734 // Ensures clicking a caret (or its pseudo-element) toggles only the associated submenu 735 ;(function () { 736 function closeSiblingSubmenus(li) { 737 if (!li || !li.parentElement) return 738 const siblings = Array.from(li.parentElement.children).filter( 739 (child) => child !== li && child.classList.contains('menu-item') 740 ) 741 siblings.forEach((sib) => { 742 const sibSub = sib.querySelector('.sub-menu-container') 743 if (sibSub && sibSub.style.display !== 'none') { 744 sibSub.style.display = 'none' 745 sibSub.classList.remove('submenu-open') 746 const sibAnchor = sib.querySelector('.menu-link') 747 if (sibAnchor) sibAnchor.setAttribute('aria-expanded', 'false') 748 } 749 }) 750 } 751 752 function toggleSubmenuForCaret(caret) { 753 const li = caret.closest('li') 754 if (!li) return 755 const submenu = li.querySelector('.sub-menu-container') 756 const anchor = li.querySelector('.menu-link') 757 758 // If there's no submenu, do nothing 759 if (!submenu) return 760 761 // Close sibling submenus first to avoid triggering previous submenu 762 //closeSiblingSubmenus(li) 763 764 const isOpen = window.getComputedStyle(submenu).display !== 'none' 765 if (isOpen) { 766 submenu.style.display = 'none' 767 submenu.classList.remove('submenu-open') 768 // remove open class on caret to revert pseudo-element transform 769 try { caret.classList.remove('menarrow-open') } catch (e) {} 770 if (anchor) anchor.setAttribute('aria-expanded', 'false') 771 } else { 772 submenu.style.display = 'block' 773 submenu.classList.add('submenu-open') 774 // add open class on caret to apply pseudo-element transform 775 try { caret.classList.add('menarrow-open') } catch (e) {} 776 if (anchor) anchor.setAttribute('aria-expanded', 'true') 777 } 778 } 779 780 document.addEventListener('click', function (e) { 781 const caret = e.target.closest && e.target.closest('.adx-caret-down.menarrow') 782 if (!caret) return 783 e.preventDefault() 784 e.stopPropagation() 785 toggleSubmenuForCaret(caret) 786 }) 787 788 // Keyboard support for accessibility 789 document.addEventListener('keydown', function (e) { 790 if (e.key !== 'Enter' && e.key !== ' ') return 791 const active = document.activeElement 792 if (!active) return 793 if (active.classList && active.classList.contains('adx-caret-down') && active.classList.contains('menarrow')) { 794 e.preventDefault() 795 toggleSubmenuForCaret(active) 796 } 797 }) 798 })() 799 800 // ** Function to Handle mobile menu toggle ** 801 function toggleMobileMenu(event = null) { 802 if (event) { 803 event.preventDefault(); // Prevent link navigation 804 } 805 806 //Find the element .adx-hamburger 807 const hamburger = document.querySelector('.adx-hamburger'); 808 if (!hamburger) return; 809 810 //check if expanded 811 const isExpanded = hamburger.classList.contains('mobile-menu-open'); 812 813 // Toggle the mobile menu open/close state 814 hamburger.classList.toggle('mobile-menu-open'); 815 816 navmenu = document.querySelector('nav.navmenu'); 817 if (navmenu) navmenu.classList.toggle('mobile-menu-open'); 818 819 if (isExpanded) { 820 // Get the primary menu and set its position to static 821 const primaryMenu = document.querySelector(".primary-menu");
822 if (primaryMenu) primaryMenu.style.position = "static"; 823 } else { 824 // Get the primary menu and set its position to fixed 825 const primaryMenu = document.querySelector(".primary-menu"); 826 if (primaryMenu) primaryMenu.style.position = "fixed"; 827 } 828 } 829 830 </script>
830 831 832 <!-- END INJECTED HEAD -->
vendor: 77 bytes, lines 832-834
832 833 834 <script async src="https://www.googletagmanager.com/gtag/js?id=
834G-H465QVKWXL
vendor: 12 bytes, line 834
834"></script>
835</head> 836<body> 837 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8PvrOawJPbFBm853VeoUrRXroWBD4wIX1upiVEfG-F2YpBDPEgl4aziJQCYGMl34xXQAk_fasgd5FwdFHfhi-pLwxRUEfahfM02Jy4O-FEJ3I8Hv7Oq7XgrqqFiORjVm4jTIKClXhUYXNRT5kxq2vttH-Dc-AUX4db3WRXkNyB7OaeHKQSAAzUBcK8qjzKJj5A" /> 838<div style="display: none;" data-tn-component-property="32a0f2f8-6d0e-4f70-bb20-c03b3e9d24ad_FormSubmissionErrorMessage">Please correct the following error(s):</div><div style="display: none;" data-tn-component-property="aa1924f3-4985-41ce-aab1-77e385f42ecc_Heading">Are you sure you want to remove this item?</div><div style="display: none;" data-tn-component-property="aa1924f3-4985-41ce-aab1-77e385f42ecc_Body">If you are removing seats, you may not be able to reserve the same seats again.</div><div style="display: none;" data-tn-component-property="aa1924f3-4985-41ce-aab1-77e385f42ecc_DeleteItemButtonText">Remove Item</div><div style="display: none;" data-tn-component-property="aa1924f3-4985-41ce-aab1-77e385f42ecc_CancelButtonText">Cancel</div><div style="display: none;" data-tn-component-property="aa1924f3-4985-41ce-aab1-77e385f42ecc_RemoveNonInventoryItemSectionText">The item will be removed from your cart.</div> 839 840 <!-- BEGIN INJECTED HEADER --> 841 842 <!-- Placeholder for header --> 843 <div id="head-inject">Loading header...</div> <!-- removed class="fade-in" --> 844 845 <!-- Placeholder for body top --> 846 <div id="body-top-inject">Loading body top content...</div> <!-- removed class="fade-in" --> 847 848 <!-- Main content --> 849 <div class="article-page-wrap"> 850 <div id="content" class="article-page-content"> <!-- removed class="fade-in" --> 851 <div class="site-message" style="opacity: 0; display: none;"> 852 <p>Site messages go here.</p> 853 <button class="btn site-message__close-btn" data-close="" aria-label="Close the alert message"> Ã 854 </button> 855 </div> 856 <div id="search-modal" class="search-modal" aria-hidden="true"> 857 <div class="search-modal__container"> 858 <div class="search-modal__content"> 859 <form class="search-form" role="search" method="get" action="https://cupresents.org/search/"> 860 <div class="search-input-group"> 861 <input type="text" name="search" placeholder="Search events, artists, series..." 862 class="search-input" aria-label="Search" /> 863 <button alt="Search" type="submit" class="search-submit"> 864 <svg tabindex="-1" width="40" height="40" viewBox="0 0 40 40" 865 xmlns="http://www.w3.org/2000/svg" style="height: 25px; width: 25px;"> 866 <circle cx="17.143" cy="18.571" r="8.571" fill="none" stroke="#000" 867 stroke-width="2"></circle> 868 <line x1="23.5" y1="24.9" x2="30.5" y2="31.9" stroke="#000" stroke-width="2" 869 stroke-linecap="round"></line> 870 </svg> 871 <span class="sr-only">Search</span> 872 </button> 873 </div> 874 </form> 875 <button alt="Close search" class="search-close" aria-label="Close search"> 876 Ã 877 </button> 878 </div> 879 </div> 880 </div> 881 <div class="ast-container tnew-content" style="display: block !important;"> 882 883 <!-- END INJECTED HEADER --> 884 885 886 887 888 889 890 891 892<div class="tn-utility-nav"> 893 894 <div class="tn-utility-nav-account-section__container"> 895 <nav class="tn-utility-nav-account-section tn-utility-nav-account-section--logged-out" aria-labelledby="tn-utility-nav-account-heading"> 896 <h2 id="tn-utility-nav-account-heading" class="sr-only">Account</h2> 897 898 <a class="tn-utility-nav-account-login-link btn btn-primary btn-sm" href="/account/login?returnurl=%2Fcart%2Fdetail
898s%3Fqueueittoken%3De_safetynet%7Ets_1790241980%7Ece_true%7Ert_safetynet%7Eh_8ad0494a4944a555e2f8eaeb02b468b9fa5e7117ac7a4181d7092b64e500d38a"> 899 <svg aria-hidden="true" class="tn-icon tn-icon--person-fill tn-utility-nav-account-login-link__user-icon"><use xlink:href="/_images/sprites.svg#person-fill" /></svg> 900 Log In 901 </a> 902 </nav> 903 </div> 904 905 906 <section class="tn-utility-nav-cart-controls-section" aria-labelledby="tn-utility-nav-cart-controls-heading"> 907 <h2 id="tn-utility-nav-cart-controls-heading" class="sr-only">Cart</h2> 908 <div class="tn-utility-nav-cart-timer" role="timer" > 909 <svg aria-hidden="true" class="tn-icon tn-icon--clock tn-utility-nav-cart-timer__icon"><use xlink:href="/_images/sprites.svg#clock" /></svg> 910 <span class="tn-utility-nav-cart-timer__label"> 911 Time Remaining 912 </span> 913 <span class="tn-utility-nav-cart-timer__time" 914 id="tn-count-down-timer" 915 style="visibility: hidden;" 916 data-tn-milliseconds-remaining="0"> 917 00:00 918 </span> 919 </div> 920 921 <div class="tn-utility-nav-promo-code-section"> 922 <h3 class="sr-only">Enter Promo Code</h3> 923 <form class="tn-utility-nav-inline-promo-code-form"> 924 <label class="tn-utility-nav-inline-promo-code-form__label" for="tn-utility-nav-inline-promo-code-form-input">Promo Code</label> 925 926 <div class="tn-utility-nav-inline-promo-code-form__input-container"> 927 <input id="tn-utility-nav-inline-promo-code-form-input" class="tn-utility-nav-inline-promo-code-form__input form-control input-sm" required> 928 <button type="submit" class="tn-utility-nav-inline-promo-code-form__btn-submit btn btn-primary btn-sm"> 929 <span class="tn-utility-nav-inline-promo-code-form__btn-submit-label">Submit</span> 930 </button> 931 932 <div class="tn-utility-nav-inline-promo-code-form__help-block-container"> 933 <div id="tn-utility-nav-inline-promo-code-form-help-block" class="tn-utility-nav-inline-promo-code-form__help-block"> 934 <svg aria-hidden="true" class="tn-icon tn-icon--x-circle-fill tn-utility-nav-inline-promo-code-form__help-block-icon"><use xlink:href="/_images/sprites.svg#x-circle-fill" /></svg> 935 <span aria-live="assertive" class="tn-utility-nav-inline-promo-code-form__help-block-text"></span> 936 </div> 937 </div> 938 </div> 939 </form> 940 <button type="button" class="tn-utility-nav-modal-promo-code-form__btn-open-modal btn btn-primary btn-sm"> 941 Promo Code 942 </button> 943 <form id="tn-utility-nav-modal-promo-code-form" novalidate style="display: none;"> 944 <div class="form-group" data-control-group-for="ApplyPromoCode.PromoCode"> 945<label class="control-label tn-promo-code" for="ApplyPromoCode_PromoCode"><span>Promo Code</span><span aria-hidden="true" class="tn-required-field">Required</span></label><input autocomplete="off" class=" form-control tn-promo-code" data-tn-form-control="true" id="ApplyPromoCode_PromoCode" name="ApplyPromoCode.PromoCode" required="required" type="text" value="" /> </div> 946 </form> 947 948 </div> 949 950 <a href="/cart/details" class="tn-utility-nav-cart-link btn btn-primary btn-sm" aria-label="View Cart, 0 items"> 951 <svg aria-hidden="true" class="tn-icon tn-icon--cart-fill tn-utility-nav-cart-link__icon"><use xlink:href="/_images/sprites.svg#cart-fill" /></svg> 952 <span class="tn-utility-nav-cart-link__label">View Cart</span> 953 <span class="tn-utility-nav-cart-link__quantity-badge">0</span> 954 </a> 955 </section> 956</div> 957 958 959 960<div style="display: none;" data-tn-component-property="2e16b93d-fa49-4b05-b981-9897dc177655_ExpiredModalTitle">Your cart has expired.</div><div style="display: none;" data-tn-component-property="2e16b93d-fa49-4b05-b981-9897dc177655_ExpiredModalText">
960Your order contained expired items and your shopping cart has been emptied.</div><div style="display: none;" data-tn-component-property="2e16b93d-fa49-4b05-b981-9897dc177655_ExpiredModalButton">Close</div><div style="display: none;" data-tn-component-property="2e16b93d-fa49-4b05-b981-9897dc177655_PromoCodeEntrySubhead">Enter Promo Code</div> 961 <main class="tn-cart-details-page" data-tn-page-type="6856252f-fc91-48fc-a119-9cf83a568d31"> 962 963 964 965 966<section class="tn-header-component"> 967 <h1 class="tn-header-component__heading tn-heading " id="tn-page-heading"> 968 Shopping Cart 969 </h1> 970 971 972<div id="tn-error-message-template"></div> 973 974 975<div id="tn-alert-message-template"></div> 976 977 978 979 <div class="tn-header-component__sub-text tn-heading-sub-text"> 980 <div class="theme"> 981<div class="theme-cupresents" style="display:block;"> 982<p><strong>For CU Boulder Faculty, Staff or Student discounts, add an "Adult" ticket to your cart and sign in with your colorado.edu email. Your discount shows at checkout (max 4 tickets/performance, excludes Holiday Festival, CSF Previews, Takács Digital and season tickets). More info on our <a href="https://cupresents.org/ticket-info/discounts/" target="_blank">discount page</a>.</strong><br /> 983<br /> 984Want to see where you're sitting? <a href="https://cupresents.org/your-visit/" rel="noopener" target="_blank">Check out our venue seating maps!</a></p> 985</div> 986 987<div class="theme-macky" style="display:none;"> 988<p>Want to see where you're sitting? <a href="https://www.colorado.edu/macky/your-visit/seating-chart" rel="noopener" target="_blank">Check out our seating chart!</a></p> 989</div> 990</div> 991 992 </div> 993</section> 994 995 996 997 998 999 1000 1001 1002 1003<section class="tn-cart-component" aria-label="Cart Contents"> 1004 1005 <div class="tn-empty-cart-message"> 1006 Your cart is currently empty. 1007 </div> 1008</section> 1009 1010<div class="tn-cart-buttons"> 1011 <div class="tn-cart-buttons__item-container"> 1012 <a href="/events" class="tn-cart-buttons__secondary-action"> 1013 Continue Shopping 1014 </a> 1015 </div> 1016 <div class="tn-cart-buttons__item-container"> 1017 <button type="button" disabled class="tn-cart-buttons__primary-action btn btn-primary"> 1018 Check Out 1019 </button> 1020 </div> 1021</div> 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 </main> 1033 1034 <!-- BEGIN INJECTED FOOTER --> 1035 1036 </div> 1037 </div> 1038 </div> 1039 1040 <!-- Placeholder for footer --> 1041 <div id="footer-inject">Loading footer...</div> <!-- removed class="fade-in" --> 1042 1043 <!-- END INJECTED FOOTER --> 1044 1045
1045<script src="https://production.tnew-assets.com/tnew/public/tnew-runtime.fbce9f756f163e3756fb.js"></script>
1045 1046
1046<script src="https://production.tnew-assets.com/tnew/public/tnew-vendor.39238606c1acf31e864b.js"></script>
1046 1047
1047<script src="https://production.tnew-assets.com/tnew/public/tnew.1724239e89aad2569486.js"></script>
1047 1048 1049
1049<script> 1050 tnew.app.init({"appVersion":"16.0.48.8","tessituraVersion":"16.0.31.98728","environment":"production","rootUrl":"https://tickets.cupresents.org/","bcp47LanguageTag":"en-US","iso4217CurrencyCode":"USD","analyticsConfiguration":{"userId":0,"measurementIds":["G-H465QVKWXL","G-QJ8KBZM7GY"],"isGA4DatalayerEnabled":false,"isEnabled":true},"rumSettings":null,"calendarViewConfig":{"viewAsDayLabel":"Day","viewAsWeekLabel":"Week","viewAsMonthLabel":"Month","firstDayOfWeek":0,"weekdaysLabel":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"monthsLabel":["January","February","March","April","May","June","July","August","September","October","November","December"]}}); 1051 </script>
1051 1052 1053
1053<script> 1054 (function() { 1055 var orderDataModel = {"modeOfSale":0,"number":0,"fees":0.0,"total":0.0,"cartItems":[]}; 1056 1057 var productDataModel = {"packageId":0,"productionSeasonId":0,"performanceId":0,"productTypeDescription":null,"contributionTypeId":0,"fundId":0,"onAccountPaymentMethodId":0,"giftCertificatePaymentMethodId":0,"membershipOrganizationId":0,"membershipLevelId":0}; 1058 1059 var sessionDataModel = {"customerNumber":0,"sessionKey":"b2cnuxTjNo0JdoMfl5dynlazNBlLw3QmNXqHd5faQUxIrWvKUzutRn3+jFCZ66J8F8gl97Mm1Z+R8YSapirArtSrVPSactM5JCR//hfU99w2N+RBJ3ODZljadq/Nv6Xyx+UUy8LLsKf//EoMW/M0+DRmG3WuwltCxTApoEmXzmo=","modeOfSale":16,"isGuest":false,"isAnonymous":true,"sourceId":1,"isRenewalOrder":false}; 1060 1061 var provider = new tnew.lib.GoogleDataLayerProvider(orderDataModel, productDataModel, sessionDataModel); 1062 1063 window.dataLayer = window.dataLayer || []; 1064 1065 var session = provider.getSession(); 1066 1067 window.dataLayer.push(session); 1068 1069 var product = provider.getProduct(); 1070 1071 window.dataLayer.push(product); 1072 1073 var order = provider.transformOrder(); 1074 1075 if (order) { 1076 window.dataLayer.push(order); 1077 } 1078 })(); 1079 </script>
1079 1080 1081 1082 1083 1084
1084<script src="https://production.tnew-assets.com/tnew/public/tnew-cart-details.92971a8c37d350d2350c.js"></script>
1084 1085 1086
1086<script> 1087 (function () { 1088 var jsPageData = {"isPaymentPlanSelectionVisible":false,"isPaymentPlanApplied":false,"ga4DatalayerItems":null,"removeFromCartAnalyticsMap":null}; 1089 1090 window.tnew.page.initialize(jsPageData); 1091 })(); 1092 </script>
1092 1093 1094 1095 1096 <!-- 1097 1098Session MOS: 16 / Original MOS: 16 1099Promo: (1) 1100 1101 -->
1102<script type="text/javascript" src="/_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3&ns=2&cb=327295637" async></script>
1102</body> 1103</html>
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.