1 2 3 4<!DOCTYPE html> 5<html lang="en"> 6<!--[if IE 7]> <html lang="en" xml:lang="en" class="no-js ie ie7 lt-ie9 lt-ie8" xmlns:og="http://ogp.me/ns#"> <![endif]--> 7<!--[if IE 8]> <html lang="en" xml:lang="en" class="no-js ie ie8 lt-ie9" xmlns:og="http://ogp.me/ns#"> <![endif]--> 8<!--[if IE 9]> <html lang="en" xml:lang="en" class="no-js lt-ie9" xmlns:og="http://ogp.me/ns#"> <![endif]--> 9 10 <head> 11 <meta charset="utf-8" /> 12 <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 13 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 14 15 <title>SRU | Slippery Rock University</title> 16 17 <base href="https://www.sru.edu/" /> 18 19 20 21 22 <meta http-equiv="content-language" content="en-us" /> 23 <meta name="description" content="Slippery Rock University of Pennsylvania is your first choice for a rock solid education. Take the next step in your academic higher education experience by applying today at SRU!" /> 24 <meta name="keywords" content="" /> 25 <meta name="author" content="[email protected]" /> 26 <meta name="robots" content="index, follow" /> 27 28 29 <meta property="og:image" content="http://www.sru.edu//images/web/sru-circle-logo.jpg" /> 30 <meta property="og:type" content="website" /> 31 <meta property="og:title" content="Slippery Rock University of Pennsylvania" /> 32 <meta property="og:description" content="Experience the difference at Slippery Rock University. Take the next step in your academic higher education experience by applying today at SRU." /> 33 34 35 36 <link rel="shortcut icon" href="/prebuilt/img/favicon.png" type="image/x-icon" /> 37 38 <link href='//fonts.googleapis.com/css?family=Lato:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic' rel='stylesheet' type='text/css'>
39 <link href='https://fonts.googleapis.com/css?family=Fjalla+One' rel='stylesheet' type='text/css'> 40 <!-- <link rel="profile" href="//microformats.org/profile/hcard" /> --> 41 <link rel="stylesheet" type="text/css" href="/prebuilt/css/main.css?v=547" /> 42 43
43<script src="/prebuilt/js/plugins/modernizr.optimized.js?v=547"></script>
43 44
44<script src="/prebuilt/js/plugins/responsive.js?v=547"></script>
44 45 46<link href='https://fonts.googleapis.com/css?family=Open Sans' rel='stylesheet'> 47<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" /> 48<link rel="stylesheet" href="/prebuilt/css/pre-bread.css?v=sb"> 49<link rel="stylesheet" href="/prebuilt/css/custom.css?v=sc"> 50<meta name="twitter:card" content="summary_large_image"> 51 52 <!-- google fonts preconnect --> 53 <link rel="preconnect" href="https://fonts.googleapis.com" crossorigin> 54 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 55 <!-- style sheets and font icons --> 56 <link rel="stylesheet" href="css/vendors.min.css"/> 57 <link rel="stylesheet" href="css/icon.min.css"/> 58 <link rel="stylesheet" href="css/style.css"/> 59 <link rel="stylesheet" href="css/responsive.css"/> 60 <link rel="stylesheet" href="css/custom.css?v=3"/> 61 62<!-- Google Tag Manager -->
63<script>
vendor: 325 bytes, lines 63-67
63(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 64new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 65j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 66'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 67})(window,document,'script','dataLayer','
67GTM-N4DS29
vendor: 3 bytes, line 67
67');
67</script>
67 68<!-- End Google Tag Manager --> 69 70<!-- Global site tag (gtag.js) - Google Ads: 1014205761 -->
vendor: 66 bytes, lines 70-71
70 71<script async src="https://www.googletagmanager.com/gtag/js?id=
71AW-1014205761
vendor: 12 bytes, line 71
71"></script>
71<script>
vendor: 127 bytes, line 71
71window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', '
71AW-1014205761
vendor: 4 bytes, line 71
71');
71</script>
71 72 73<!--MS Clarity-->
74<script type="text/javascript"> 75 (function(c,l,a,r,i,t,y){ 76 c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; 77 t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; 78 y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); 79 })(window, document, "clarity", "script", "pce8l3fsor"); 80</script>
80 81 82<!--EM Message Title Replace--> 83 <!--
83<script> 84 document.addEventListener("DOMContentLoaded", function() { 85 const div = document.querySelector(".attention"); 86 87 div.childNodes.forEach(node => { 88 if (node.nodeType === Node.TEXT_NODE) { 89 node.nodeValue = "example"; 90 } 91 }); 92 }); 93 </script>
93--> 94 95<style> 96/*events addition*/ 97.sru-event-location { 98 font-size: 1rem; 99 color: #007055; 100 margin-bottom: 8px; 101 text-align: left; 102 font-weight: 700; 103} 104.content th, .mceContentBody th { 105 color: #ffffff; 106} 107.sidebar > h2 { 108font-size: 1.19em; 109} 110@media only screen and (min-width: 767px) { 111 .navigation-container .sidebar h2 { 112 padding: 30px 5px 10px 10px; 113 } 114} 115.sidebar.contact-info a { 116 text-decoration: underline; 117} 118#event-reminder-modal { 119 bottom: 145px; 120} 121@media screen and (min-width: 767px) { 122 .captionContainer { 123 max-width: 800px; 124 } 125} 126 127/* fixes for new css and js overlay*/ 128 129.simple-masthead { 130 z-index: 0; 131} 132 133.deluxe-masthead { 134 z-index: 0; 135} 136 137@media only screen and (min-width: 767px) { 138 .breadcrumbs { 139 z-index: 0; 140 } 141} 142 143.main { 144 margin-top: 139px; 145 padding-bottom: 5em; 146} 147 148@media (max-width: 768px) { 149.main { 150 margin-top: 135px; 151 padding-bottom: 0em; 152 } 153} 154 155.back-to-top { 156 font-family: Lato,sans-serif; 157 font-style: normal; 158} 159 160/*footer bottom padding added for mobile to prevent back-to-top from covering*/ 161@media (max-width: 768px) { 162footer[data-sru] .footer-legal-links { 163 padding-bottom: 120px; 164 } 165} 166 167/*Home video height fixes*/ 168@media screen and (min-width: 1024px) { 169 .home-video { 170 margin-top: 4.1em; 171 } 172} 173 174@media (max-width: 766.98px) { 175 .captionContainer { 176 margin-top: 6em; 177 } 178} 179 180/*Emergency Section CSS fixes for new header*/ 181 182.emergency.open { 183 position: absolute; 184 top: env(safe-area-inset-top, 0); 185 left: 0; 186 right: 0; 187 border-bottom: 3px #ffcb0b solid; 188} 189 190 .emergency { 191 position: absolute; 192 top: env(safe-area-inset-top, 0); 193 left: 0; 194 right: 0; 195 } 196 197.emergency .attention-container { 198 height: 3em; 199} 200 201@media only screen and (min-width: 767px) { 202.emergency .attention-container { 203 height: 3.2em; 204 } 205} 206 207@media only screen and (min-width: 767px) { 208 .emergency .col1 { 209 padding-bottom: 3.5em; 210 } 211} 212 213 .emergency { 214 border-bottom: none; 215 } 216 217/*button fixes homepage*/ 218 219.ctaButton:hover { 220 background-color: #007055; 221 color: #ffcb0b; 222 transition: background-color 0.1s; 223} 224 225#captionBox1 a { 226 color: #fff; 227} 228 229#captionBox2 a { 230 color: #33393c; 231} 232 233/* Call-to-action homepage fix */ 234.call-to-action .ctaButton > a:hover { 235 color: #ffcb0b; 236} 237 238/* ================================ 239 SRU ICON + HEADER/FOOTER HOTFIX 240 ================================ */ 241 242/* 1) IcoMoon font â renamed to avoid collisions with FA/BI/Feather. */ 243@font-face { 244 font-family: 'sru-icomoon'; 245 src: url('/prebuilt/css/fonts/icomoon.woff?7gk0y9') format('woff'); 246 font-weight: normal; 247 font-style: normal; 248 font-display: block; 249} 250 251/* 2) Only classes that start with `icon-` (and are NOT FA/BI/Feather) use IcoMoon. */ 252[class^="icon-"]:not([class^="icon-feather"]):not(.fa):not([class*=" fa-"]):not(.bi):not([class*=" bi-"]), 253[class*=" icon-"]:not([class*="icon-feather"]):not(.fa):not([class*=" fa-"]):not(.bi):not([class*=" bi-"]) { 254 font-family: 'sru-icomoon' !important; 255 speak: never; 256 font-style: normal; 257 font-weight: normal; 258 font-variant: normal; 259 text-transform: none; 260 line-height: 1; 261 -webkit-font-smoothing: antialiased; 262 -moz-osx-font-smoothing: grayscale; 263} 264 265a.icon.icon-social { 266 padding-top: .3em; 267} 268 269/* 3) Keep FA/BI fonts pinned to their own families (prevents any side-effects). */ 270.bi, [class^="bi-"], [class*=" bi-"] { 271 font-family: "bootstrap-icons" !important; 272} 273.fa, [class^="fa-"], [class*=" fa-"] { 274 font-family: 275 "Font Awesome 6 Free", 276 "Font Awesome 6 Pro", 277 "Font Awesome 5 Free", 278 "Font Awesome 5 Pro", 279 FontAwesome !important; 280 font-weight: inherit; 281} 282 283.accordion h2.heading .icon { 284 padding: 0.5em !important; 285} 286 287/* ===== Scoped header/footer fixes ===== */ 288 289/* Mobile (<=991.98px): keep search/MySRU icons white, gold on hover */ 290@media (max-width: 991.98px) { 291 header[data-sru] .header-light .header-icon .icon > a, 292 header[data-sru] .header-light .header-icon .icon .header-language > a, 293 header[data-sru] .header-light .header-icon .icon .header-cart > a, 294 header[data-sru] .header-light .header-icon .icon .header-account > a { 295 color: #fff !important; 296 } 297 header[data-sru] .header-light .header-icon .icon > a:hover, 298 header[data-sru] .header-light .header-icon .icon .header-language > a:hover, 299 header[data-sru] .header-light .header-icon .icon .header-cart > a:hover, 300 header[data-sru] .header-light .header-icon .icon .header-account > a:hover { 301 color: #ffcb0b !important; 302 } 303} 304 305/* Hamburger lines forced white (scoped) */ 306header[data-sru] .navbar-toggler .navbar-toggler-line { 307 background-color: #fff !important; 308} 309header[data-sru] .navbar-toggler:hover .navbar-toggler-line, 310header[data-sru] .navbar-toggler:focus .navbar-toggler-line { 311 background-color: #fff !important; 312} 313header[data-sru] .navbar-toggler { border: 0; } 314 315/* If a mobile dropdown gets tall, allow scrolling inside the open menu */ 316@media (max-width: 991.98px) { 317 header[data-sru] .navbar-collapse { 318 max-height: calc(100vh - 72px); 319 overflow-y: auto; 320 -webkit-overflow-scrolling: touch; 321 } 322} 323 324/* Footer: keep h3 using Bootstrap heading color but scoped to footer only */ 325footer[data-sru] h3 { 326 margin-top: 0;
327 margin-bottom: .5rem; 328 font-weight: 500; 329 line-height: 1.2; 330 color: var(--bs-heading-color); 331} 332 333/*Search form fixes*/ 334.search-form-wrapper .search-form .search-input { 335 height: 40px; 336} 337 338@media (max-width: 575px) { 339 header[data-sru] .search-form-wrapper .search-form .search-input { 340 height: 20px; 341 } 342} 343 344@media (max-width: 991px) { 345.search-form-wrapper .search-form-box { 346 width: 80%; 347 } 348} 349 350.header-demo.navbar .navbar-nav .nav-item:first-child .dropdown-menu a { 351 color: var(--medium-gray); 352} 353 354.header-demo.navbar .navbar-nav .nav-item:first-child .dropdown-menu a:hover { 355 color: var(--dark-gray); 356} 357 358/* video button for pause and play*/ 359@media (min-width: 768px) { 360 .sru-video-control-btn { 361 position: absolute; 362 bottom: 60px; 363 right: 29px; 364 top: auto; 365 left: auto; 366 transform: none; 367 z-index: 100; 368 background: rgba(0, 0, 0, 0.5); 369 color: white; 370 border: none; 371 border-radius: 50%; 372 padding: 15px; 373 cursor: pointer; 374 font-size: 24px; 375 transition: background-color 0.3s; 376 } 377 378 .sru-video-control-btn:hover { 379 background: rgba(0, 0, 0, 0.7); 380 } 381} 382 383@media (max-width: 767px) { 384 .sru-video-control-btn { 385 display: none; 386 } 387} 388 389.flex-item { 390 overflow: visible; 391} 392 393.bi-filetype-pdf::before { 394 color: red; 395 font-size: 1.2em; 396} 397 398.sidebar .bi-filetype-pdf::before { 399 font-size: 1em; 400 color: red; 401} 402 403.col1 a { 404 color: #0066cc; /* nicer blue */ 405 text-decoration: underline; 406} 407 408.col1 a:hover, 409.col1 a:focus { 410 color: #004b99; 411} 412 413/*em message fix likely not needed*/ 414.main { 415 margin-top: 139px; 416 padding-bottom: 5em; 417} 418 419@media (max-width: 768px) { 420 .main { 421 margin-top: 135px; 422 } 423} 424 425.search-form-wrapper .search-close { 426 top: 38px; 427} 428 429/*temp css homepage video overrides for shorter test period*/ 430 431@media screen and (min-width: 1024px) { 432 .masthead-video { 433 height: calc(100vh - 4.6em); 434 } 435} 436 437.homevideo-centerer { 438 height: 80%; 439} 440 441/*homepage video button fix*/ 442@media (max-width: 500px) { 443#mainVideoButton { 444 font-size: 1em; 445 gap: 0px; 446} 447 448@media (min-width: 768px) { 449 #event-reminder-modal { 450 bottom: 600px; 451 } 452} 453</style> 454
455<script type="text/javascript" src="https://my.hellobar.com/65ce10cfacf1adca13570db44c7a648430e91812.js" async="async"></script>
455 456 457 458 <link rel="stylesheet" href="/prebuilt/ui/css/jquery-ui.custom.css" type="text/css" media="all" /> 459 460 461 462 463
463<script> 464 function hideFallbackImage() { 465 //document.getElementById("actualVideo").style.transition = "opacity 2s ease 1s"; 466 document.getElementById("actualVideo").style.visibility = "visible"; 467 } 468 </script>
468 469 470 </head> 471 <body> 472 473 <!--[if gte IE 9]> 474 <style type="text/css"> 475 .gradient { 476 filter: none; 477 } 478 </style> 479 <![endif]--> 480 481 <!--googleoff: all--> 482 483<!-- Google Tag Manager -->
vendor: 63 bytes, lines 483-484
483 484<noscript><iframe src="//www.googletagmanager.com/ns.html?id=
484GTM-N4DS29
vendor: 85 bytes, lines 484-485
484" 485height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
486<!-- End Google Tag Manager --> 487 488 489 490 491<!-- ACCESSIBILITY NAVIGATION --> 492 493<nav class="skip-links" aria-label="Skip links"> 494 <a href="/#main-skip">Skip to main content</a> 495 <a href="/#navbar-skip">Skip to primary navigation</a> 496 <a href="/#keywords">Skip to search</a> 497 <a href="/#footer-skip">Skip to footer</a> 498</nav> 499<!-- /access --> 500 501 <!-- SRU Cookie Banner --> 502 <section id="sru-cookie-example" class="sru-cookie-example sru-cookie-example--hidden" role="region" aria-label="Cookie notice" aria-live="polite"> 503 <div class="sru-cookie-example__inner" role="document"> 504 <p class="sru-cookie-example__text"> 505 We use cookies on this site to enhance your user experience.<br> 506 <a id="cookie-privacy" class="sru-cookie-example__link" href="/web-privacy">Privacy Statement</a> 507 </p> 508 <button type="button" id="sru-cookie-example-ack" class="sru-cookie-example__btn" aria-label="I Understand"> 509 I Understand 510 </button> 511 </div> 512 </section> 513 514 <noscript> 515 <div class="sru-cookie-example-noscript sru-dark-background sru-light-text"> 516 We use cookies on this site to enhance your user experience. 517 <a class="sru-link2" href="/web-privacy">Privacy Statement</a> 518 </div> 519 </noscript> 520 521 522 523 524 525<!--<div class="emerg-switcher-display"> 526<section class="emergency" id="emergency" aria-label="Alert Box"> 527 528 <div class="attention-container"> 529 <div id="focus-bar" class="focus-bar"> 530 <div class="attention">Alert<img src="/prebuilt/img/alert.png" width="24" height="24" class="alert-icon" alt="Red emergency circle" /></div> 531 <div class="showmore">+ Show</div> 532 </div> 533 </div> 534 <div class="alert-container"> 535 <div class="wrapper"> 536 <div class="col1"> 537
537<script type="text/javascript" src="https://s3.amazonaws.com/widgets.omnilert.net/9319a285f0e6642d83124cf1c315ac0b-13251"></script>
537 538 <hr> 539 </div> 540 <div class="col2"> 541 <a href="#" class="emergency-close" id="alert-close"><span>X</span> Close</a> 542 </div> 543 544 </div> 545 546 </div> 547 548</section> 549</div>--> 550 551 552 553 554 555 556<!-- start header --> 557<header data-sru> 558<!-- start navigation --> 559<nav class="navbar navbar-expand-lg header-light header-reverse header-demo" data-header-hover="light" aria-label="Main navigation"> 560 561<div class="header-top-bar" role="navigation" aria-label="Utility navigation"> 562 <div class="container-fluid"> 563 <div class="row align-items-center justify-content-between flex-nowrap m-0" style="height: 42px;"> 564 565<!-- Left Column --> 566<div class="col-auto d-flex align-items-center ps-1 utility-left"> 567 <button type="button" style="border: 0px;" class="menu-toggle d-lg-none fs-14 text-white fw-600" aria-expanded="false" aria-controls="utility-dropdown">Info for <i class="fa-solid fa-angle-down" aria-hidden="true"></i></button> 568 <div id="utility-dropdown" class="utility-dropdown"> 569 <a href="/students" class="fs-14 text-white text-decoration-none">Students</a> 570 <a href="/family" class="fs-14 text-white text-decoration-none">Family</a> 571 <a href="/veterans" class="fs-14 text-white text-decoration-none">Veterans</a> 572 <a href="/alumni" class="fs-14 text-white text-decoration-none">Alumni</a> 573 </div> 574 <div> 575<a href="https://www.givecampus.com/s/6jugpm" target="_blank" rel="noopener noreferrer" class="fs-14 text-white text-decoration-none"> 576 <span class="label bg-white-ice sru-green-text sru-white-background border-radius-10px" style="padding:.4em">Give</span> 577</a> 578 </div> 579</div> 580 <!-- Right Column --> 581<div class="col d-flex align-items-center justify-content-end sru-cta-top"> 582 <a href="/admissions/visit-the-rock" class="fs-14 text-black text-decoration-none">Visit</a> 583 <a href="/admissions/request-information" class="fs-14 text-black text-decoration-none">Request Info</a> 584 <a href="/admissions/apply-now" class="fs-14 text-black text-decoration-none">Apply</a> 585 </div> 586 </div> 587 </div> 588</div> 589 590<div class="container-fluid"> 591<div class="col-auto col-lg-2 me-lg-0 me-auto"> 592<a class="navbar-brand" href="/" aria-label="Slippery Rock home"> 593<img alt="SRU Logo Wordmark" class="default-logo" data-at2x="/images/logos/slippery_rock_university-logo.png" src="/images/logos/slippery_rock_university-logo.png"/> 594<img alt="SRU Logo Wordmark" class="alt-logo" data-at2x="/images/logos/slippery_rock_university-logo-green.png" src="/images/logos/slippery_rock_university-logo-green.png"/> 595<img alt="SRU Logo Wordmark" class="mobile-logo" data-at2x="/images/logos/slippery_rock_university-logo.png" src="/images/logos/slippery_rock_university-logo.png"/> 596</a> 597</div> 598<div class="col-auto col-lg-8 menu-order position-static"> 599<button aria-controls="navbarNav" aria-label="Toggle navigation" class="navbar-toggler float-start" data-bs-target="#navbarNav" data-bs-toggle="collapse" type="button"> 600<span class="navbar-toggler-line"></span> 601<span class="navbar-toggler-line"></span> 602<span class="navbar-toggler-line"></span> 603<span class="navbar-toggler-line"></span> 604</button> 605<div class="collapse navbar-collapse justify-content-center" id="navbarNav"> 606<ul class="navbar-nav"> 607<li class="nav-item dropdown submenu"> 608 <div class="nav-link-wrapper d-inline-flex align-items-center" id="navbarDropdownMenuLinkAcademics"> 609 <a href="/academics" class="nav-link pe-1" id="navbar-skip">Academics</a> 610 <a href="javascript:void(0);" role="button" class="nav-link dropdown-toggle-icon" aria-label="Expand Academics menu" aria-expanded="false" aria-controls="academics-menu"> 611 <i class="fa-solid fa-angle-down dropdown-icon ms-1" aria-hidden="true"></i> 612 </a> 613 </div> 614 <div id="academics-menu" class="dropdown-menu submenu-content background-position-center cover-background xs-pt-1" aria-labelledby="navbarDropdownMenuLinkAcademics"> 615 616 <div class="d-lg-flex mega-menu m-auto"> 617 <ul class="col"> 618 <li class="sub-title" role="heading" aria-level="2">Colleges & Departments</li> 619 <li><a href="/academics/colleges-and-departments/coe">College of Education</a></li> 620 <li><a href="/academics/colleges-and-departments/ces">College of Engineering & Science</a></li> 621 <li><a href="/academics/colleges-and-departments/cohp">College of Health Professions</a></li> 622 <li><a href="/academics/colleges-and-departments/cla">College of Liberal Arts</a></li> 623 <li><a href="/academics/colleges-and-departments/cob">Haverlack College of Business</a></li> 624 </ul> 625 <ul class="col"> 626 <li class="sub-title" role="heading" aria-level="2">Academic Experiences</li> 627 <li><a href="/academics/study-abroad">Study Abroad</a></li> 628 <li><a href="/academics/summer-session">Summer Sessions</a></li> 629 <li><a href="/academics/winter-session">Winter Sessions</a></li> 630 </ul> 631 <ul class="col"> 632 <li class="sub-title" role="heading" aria-level="2">Academic Resources</li> 633 <li><a href="/academics/bailey-library">Bailey Library</a></li> 634 <li><a href="/academics/honors-college">Honors College</a></li> 635 <li><a href="/academics/academic-services">Academic Services & Advisement </a></li> 636 <li><a href="/academics/research">Research Opportunities</a></li> 637 </ul> 638 </div> 639 </div> 640</li> 641 642<li class="nav-item dropdown simple-dropdown"> 643 <div class="nav-link-wrapper d-inline-flex align-items-center" id="navbarDropdownMenuLinkPrograms"> 644 <a href="/programs" class="nav-link pe-1">Programs</a> 645 <a href="javascript:void(0);" role="button" class="nav-link dropdown-toggle-icon" aria-label="Expand Programs menu" aria-expanded="false" aria-controls="programs-menu"> 646 <i class="fa-solid fa-angle-down dropdown-icon ms-1" aria-hidden="true"></i> 647 </a> 648 </div> 649 650<ul id="programs-menu" class="dropdown-menu xs-pt-1" aria-labelledby="navbarDropdownMenuLinkPrograms"> 651<li class="dropdown"> 652<a href="/programs?ptype=Undergraduate&sort=title-asc">Undergraduate</a> 653</li> 654<li class="dropdown"> 655<a href="/programs?ptype=Graduate&sort=title-asc">Graduate</a> 656</li> 657<li class="dropdown"> 658<a href="/programs?ptype=Doctoral&sort=title-asc">Doctoral</a> 659</li> 660<li class="dropdown"> 661<a href="/programs?ptype=Accelerated+Programs&sort=title-asc">Accelerated</a> 662</li> 663<li class="dropdown"> 664<a href="/programs?ptype=Certificates&sort=title-asc">Certificates</a> 665</li> 666<li class="dropdown"> 667<a href="/programs?ptype=Online&sort=title-asc">Online</a> 668</li> 669<li class="dropdown"> 670<a href="/programs">All Programs</a> 671</li> 672</ul> 673</li> 674 675<li class="nav-item dropdown submenu"> 676 <div class="nav-link-wrapper d-inline-flex align-items-center" id="navbarDropdownMenuLinkAdmissions"> 677 <a href="/admissions" class="nav-link pe-1">Admissions & Aid</a> 678 <a href="javascript:void(0);" role="button" class="nav-link dropdown-toggle-icon" aria-label="Expand Admissions and Aid menu" aria-expanded="false" aria-controls="admissions-menu"> 679 <i class="fa-solid fa-angle-down dropdown-icon ms-1" aria-hidden="true"></i> 680 </a> 681 </div> 682 683<div id="admissions-menu" aria-labelledby="navbarDropdownMenuLinkAdmissions" class="dropdown-menu submenu-content xs-pt-1"> 684<div class="d-lg-flex mega-menu m-auto"> 685<ul class="col"> 686<li class="sub-title" role="heading" aria-level="2">Apply</li> 687<li><a href="/admissions/first-year-students">Undergraduate/First-year</a></li> 688<li><a href="/admissions/transfer-admissions">Transfer</a></li> 689<li><a href="/admissions/graduate-admissions">Graduate</a></li> 690<li><a href="/admissions/international-admissions">International</a></li> 691<li><a href="/admissions/apply-now">Apply</a></li> 692</ul> 693<ul class="col"> 694<li class="sub-title" role="heading" aria-level="2">Visit</li> 695<li><a href="https://admission.sru.edu/portal/OpenHouses">
695Open House</a></li> 696<li><a href="https://admission.sru.edu/portal/CampusVisits">Daily Visits</a></li> 697<li><a href="/admissions/visit-the-rock/bus-visit-program">Bus Visits</a></li> 698<li><a href="/admissions/visit-the-rock/virtual-tour">Virtual Tour</a></li> 699<li><a href="/map">Campus Map</a></li> 700</ul> 701<ul class="col"> 702<li class="sub-title" role="heading" aria-level="2">Affording College</li> 703<li><a href="/admissions/estimated-costs-calculator">Costs Calculator</a></li> 704<li><a href="/admissions/financial-aid">Financial Aid</a></li> 705<li><a href="/admissions/financial-aid/military-education-benefits">Military Benefits</a></li> 706<li><a href="/admissions/financial-aid/types-of-aid/scholarships">Scholarships</a></li> 707<li><a href="/admissions/tuition-and-fees">Tuition and Fees</a></li> 708</ul> 709</div> 710</div> 711</li> 712 713<li class="nav-item dropdown submenu"> 714 <div class="nav-link-wrapper d-inline-flex align-items-center" id="navbarDropdownMenuLinkLife"> 715 <a href="/life-at-sru" class="nav-link pe-1">Life at SRU</a> 716 <a href="javascript:void(0);" role="button" class="nav-link dropdown-toggle-icon" aria-label="Expand Life at SRU menu" aria-expanded="false" aria-controls="life-at-sru-menu"> 717 <i class="fa-solid fa-angle-down dropdown-icon ms-1" aria-hidden="true"></i> 718 </a> 719 </div> 720 721<div id="life-at-sru-menu" aria-labelledby="navbarDropdownMenuLinkLife" class="dropdown-menu submenu-content xs-pt-1"> 722<div class="d-lg-flex mega-menu m-auto"> 723<ul class="col"> 724<li class="sub-title" role="heading" aria-level="2">Student Life</li> 725<li><a href="https://slipperyrock.campusdish.com/" target="_blank" rel="noopener noreferrer">Dining<span class="visually-hidden"> (opens in a new tab)</span> <i class="fa-solid fa-up-right-from-square ms-1" aria-hidden="true"></i></a></li> 726<li><a href="/life-at-sru/health-and-wellness/campus-recreation">Campus Recreation</a></li> 727<li><a href="https://sru.campuslabs.com/engage/organization/esports-club" target="_blank" rel="noopener noreferrer">Esports<span class="visually-hidden"> (opens in a new tab)</span> <i class="fa-solid fa-up-right-from-square ms-1" aria-hidden="true"></i></a></li> 728<li><a href="/life-at-sru/housing">Housing</a></li> 729<li><a href="/academics/colleges-and-departments/cob/departments/military-science-(rotc)">ROTC/Military Science</a></li> 730<li><a href="https://sru.campuslabs.com/engage/organizations?branches=238317&branches=238143" target="_blank" rel="noopener noreferrer">Student Organizations<span class="visually-hidden"> (opens in a new tab)</span> <i class="fa-solid fa-up-right-from-square ms-1" aria-hidden="true"></i></a></li> 731</ul> 732<ul class="col"> 733<li class="sub-title" role="heading" aria-level="2">Support Services</li> 734<li><a href="/academics/academic-services/services-for-students-with-disabilities">Accessibility Services</a></li> 735<li><a href="/life-at-sru/health-and-wellness/counseling-center">Counseling Center</a></li> 736<li><a href="/life-at-sru/center-for-career-and-academic-progress">Career and Academic Progress</a></li> 737<li><a href="/offices/dean-of-students">Dean of Students</a></li> 738<li><a href="/life-at-sru/health-and-wellness/student-health-center">Health Center</a></li> 739<li><a href="/life-at-sru/safety">Safety</a></li> 740</ul> 741<ul class="col"> 742<li class="sub-title" role="heading" aria-level="2">Campus Events </li> 743<li><a href="https://rockathletics.com/calendar" target="_blank" rel="noopener noreferrer">Athletics Calendar<span class="visually-hidden"> (opens in a new tab)</span> <i class="fa-solid fa-up-right-from-square ms-1" aria-hidden="true"></i></a></li> 744<li><a href="https://sru.campuslabs.com/engage/events?branches=238317&branches=238143" target="_blank" rel="noopener noreferrer">Student Event Calendar<span class="visually-hidden"> (opens in a new tab)</span> <i class="fa-solid fa-up-right-from-square ms-1" aria-hidden="true"></i></a></li> 745<li><a href="/events">University Event Calendar</a></li> 746</ul> 747</div> 748</div> 749</li> 750 751<li class="nav-item dropdown submenu"> 752 <div class="nav-link-wrapper d-inline-flex align-items-center" id="navbarDropdownMenuLinkAbout"> 753 <a href="/about" class="nav-link pe-1">About</a> 754 <a href="javascript:void(0);" role="button" class="nav-link dropdown-toggle-icon" aria-label="Expand About menu" aria-expanded="false" aria-controls="about-menu"> 755 <i class="fa-solid fa-angle-down dropdown-icon ms-1" aria-hidden="true"></i> 756 </a> 757 </div> 758 759<div id="about-menu" aria-labelledby="navbarDropdownMenuLinkAbout" class="dropdown-menu submenu-content xs-pt-1"> 760<div class="d-lg-flex mega-menu m-auto"> 761<ul class="col"> 762<li class="sub-title" role="heading" aria-level="2">Overview</li> 763<li><a href="/about/awards-and-rankings">
763Awards & Rankings </a></li> 764<li><a href="/about/fast-facts">Fast Facts</a></li> 765<li><a href="/about/history-and-traditions">History & Traditions</a></li> 766<li><a href="/about/mission-and-vision">Mission, Vision, and Values </a></li> 767<li><a href="/life-at-sru/safety">Safety Information</a></li> 768</ul> 769<ul class="col"> 770<li class="sub-title" role="heading" aria-level="2">Administration</li> 771<li><a href="/about/administration/executive-leadership-and-organization">Leadership & Governance</a></li> 772<li><a href="/about/administration/office-of-the-president">Office of the President</a></li> 773<li><a href="/about/strategic-planning">Strategic Plan</a></li> 774</ul> 775<ul class="col"> 776<li class="sub-title" role="heading" aria-level="2">Community and Contact Info</li> 777<li><a href="/directory">Find People</a></li> 778<li><a href="/map">Campus Map</a></li> 779<li><a href="https://www.experiencebutler.com/" target="_blank" rel="noopener noreferrer">Experience Butler County<span class="visually-hidden"> (opens in a new tab)</span> <i class="fa-solid fa-up-right-from-square ms-1" aria-hidden="true"></i></a></li> 780</ul> 781</div> 782</div> 783</li> 784 785<li class="nav-item dropdown submenu"> 786 <a class="nav-link" href="https://rockathletics.com/" target="_blank" rel="noopener noreferrer"> 787 Athletics<span class="visually-hidden"> (opens in a new tab)</span> <i class="fa-solid fa-up-right-from-square ms-1" aria-hidden="true"></i> 788 </a> 789 <div class="d-lg-flex mega-menu m-auto"> 790 </div> 791</li> 792 793</ul> 794</div> 795</div> 796 <div class="col-auto col-lg-2 text-end xs-pe-0"> 797 <div class="col-auto pe-lg-0"> 798 <div class="header-icon"> 799 <div class="header-language-icon icon"> 800 <div class="header-language dropdown"> 801 <a href="https://mysru.sru.edu" target="_blank" rel="noopener noreferrer" aria-label="MySRU opens in a new tab"> 802 <svg class="icon icon-mysru" aria-hidden="true" focusable="false" viewBox="0 0 3304 960"> 803 <g transform="scale(1, -1) translate(0, -960)"> 804 <path d="M423.142 960h187.954c118.586-44.264 234.364-103.062 315.458-203.644-75.148-97.942-144.682-204.634-247.246-276.81-7.764 3.798-23.452 11.23-31.216 15.030 30.554 78.782 95.96 133.946 146.498 198.854 1.818 13.874 5.284 41.456 6.938 55.164-81.59-19.986-122.88-98.106-167.474-161.528-31.216-50.374-71.68-93.976-114.622-134.276-10.736-0.662-32.206-1.818-42.942-2.312 1.322 111.154 107.686 172.758 147.324 267.56-103.39 11.23-164.5-85.718-236.182-142.204 28.076 54.338 69.534 101.74 86.71 161.528-87.040-14.534-143.030-88.030-208.598-139.56 20.81 62.266 106.694 110.164 70.358 181.016-115.284-98.766-160.866-250.218-212.068-387.634 13.874-13.23 27.912-26.26 41.95-39.16 44.924 96.124 90.674 199.036 181.842 260.13-32.206-67.386-69.368-134.772-76.14-210.746 23.288 11.744 52.852 17.358 65.57 42.942 41.29 62.1 84.728 124.202 146.664 167.804-42.942-66.394-96.95-140.716-63.092-223.628 25.436-4.294 50.87-14.552 76.966-9.746 27.912 16.516 51.53 39.292 75.148 61.424 20.644-16.186 38.648-48.226 69.368-34.354 76.8 22.956 120.568 96.95 176.392 149.14-26.592-53.346-54.668-106.034-77.626-161.182-100.418-56.832-206.948-114.472-275.654-210.25-31.38-39.49-29.068-91.334-26.592-138.736 8.258-8.588 24.774-25.6 33.032-34.040 101.244-32.52 177.218 57.64 224.124 134.128 41.62 71.35 66.726 152.096 111.814 220.97 79.774 56.502 159.216 115.96 208.598 202.836 34.684-187.276-24.444-395.726-178.374-514.972-63.752-58.632-148.976-79.112-223.96-117.76h-201.826c-108.51 41.29-221.812 88.36-294.318 183.658-57.31 64.924-84.564 148-117.924 226.14v201.644c28.738 72.672 53.844 148.644 103.722 210.086 74.488 107.356 197.698 166.152 319.422 202.488zM1156.954 845.708c162.52 88.032 369.962 75.644 527.376-17.506 44.262-37.822 87.848-91.996 75.644-154.26-12.386-20.316-28.738-37.988-43.768-56.32-39.638 1.486-87.37-12.058-118.422 19.82-35.18 33.858-58.798 81.094-103.722 103.722-77.626 43.272-184.154 28.572-245.264-36.832 0-16.846 0.164-50.704 0.33-67.716 35.18-33.032 78.286-
80456.98 125.522-67.552 109.832-28.408 222.472-51.366 323.55-105.372 76.8-48.556 125.836-142.056 101.574-233.044-6.292-82.912-67.386-148.15-135.614-189.092-150.132-62.778-326.194-70.54-476.822-5.45-74.654 33.51-141.378 96.932-153.27 181.164-10.404 38.004 20.974 67.072 41.786 94.158 32.702 3.634 65.568 3.288 98.27-0.164 37.492-51.052 68.212-109.352 121.228-146.514 69.368-38.152 152.608-34.024 227.758-18.482 25.27 20.976 48.722 43.932 71.184 68.030-4.626 30.572-12.058 60.448-20.644 90.196-114.126 75.132-256.662 78.452-379.376 134.772-50.374 28.392-100.088 61.424-130.972 111.814-29.4 67.054-22.132 143.69 9.414 208.6 25.27 31.198 53.512 60.102 84.232 86.032zM1896.232 884.52c38.3 12.058 80.914 31.216 120.222 11.726 49.218-18.994 52.026-79.774 65.586-122.88 40.944 50.044 80.582 110.494 147.638 126.514 99.098 19.82 211.406-21.966 262.936-111.484 16.036 38.482 26.92 85.718 68.046 105.538 69.054 38.318 162.518-21.802 158.884-99.924 2.972-143.030-1.982-286.224 1.652-429.418 4.79-53.86 11.562-112.144 46.574-155.598 41.454-49.88 116.274-56.138 173.898-34.336 51.218 17.178 86.378 59.954 119.412 100.402 36.006 173.6 8.092 351.976 20.974 527.376 2.644 61.44 62.118 111.65 123.062 101.574 46.228-2.476 73.976-44.262 98.088-78.286v-767.34c-27.746-28.076-55.164-65.24-98.088-67.072-38.978-7.416-66.742 25.27-96.454 44.098-8.606 34.7-14.716 69.864-19.67 105.39-49.202-42.958-92.64-95.81-154.906-120.236-117.942-47.566-271.36-38.482-361.044 59.954-58.302 56.006-69.848 141.874-73.496 218.674-0.478 154.426-0.33 308.852-0.164 463.442l-15.196-2.808c-18.68-29.068-41.29-55-65.24-79.774-81.756 14.038-162.85 51.53-246.256 22.628-95.794-105.208-82.234-255.67-87.702-387.468-4.972-99.592 17.836-205.956-30.886-298.116-42.116-15.856-92.342-42.778-133.946-10.422-55.644 24.444-54.008 92.836-56.484 144.186-0.33 192.578 0.662 384.99-0.33 577.568-1.982 54.024 8.588 107.866 32.884 156.094zM917.14 605.73c16.516 29.728 32.206 59.622 47.072 90.178 11.23-28.408 21.802-57.146 25.6-87.7-39.64-62.926-93.812-114.952-152.444-160.040 21.472 55 49.548 107.026 79.774 157.564zM630.75 265.316c26.26 18.004 51.86 36.996 77.462 56.006-11.066-22.298-21.636-44.76-32.206-67.222-14.698-34.832-31.712-68.706-48.062-102.894-23.948-28.226-49.548-54.982-75.644-81.26-18.994 4.476-55.164 6.606-49.714 35.196 12.222 71.994 74.984 117.248 128.166 160.174z"></path> 805 </svg> 806 </a> 807 </div> 808 </div> 809 <div class="header-search-icon icon"> 810 <a href="javascript:void(0)" aria-label="Search" class="search-form-icon header-search-form"><i class="feather icon-feather-search" aria-hidden="true"></i></a> 811 <div class="search-form-wrapper"> 812 <button aria-label="Close search" type="button" class="search-close alt-font">x</button> 813 <form id="search-form" name="global-search" role="search" method="post" 814 action="//rockpride.sru.edu/search/index.php" class="search-form text-left"> 815 <div class="search-form-box"> 816 <h2 class="text-sru-primary text-center mb-7 fw-600 fs-60">What are you looking for?</h2> 817 <input class="search-input alt-font" 818 id="keywords" 819 name="q" 820 type="search" 821 placeholder="Search Slippery Rock University" 822 aria-label="Search Slippery Rock University" 823 autocomplete="off"> 824 <button type="submit" aria-label="Search" class="search-button"> 825 <i class="feather icon-feather-search" aria-hidden="true"></i> 826 </button> 827 </div> 828 </form> 829 </div> 830 </div> 831 </div> 832 </div> 833 </div> 834 835 </div> 836 </nav> 837 <!-- end navigation --> 838 </header> 839 <!-- end header --> 840 841 <!--googleon: all--> 842 843 844 845 846 847 848 849 850 <!--Video Masthead Starts--> 851 <section id="home-video" class="home-video" role="region" aria-label="SRU Masthead"> 852 <h1 class="visually-hidden">Slippery Rock University</h1> 853 854 <div id="main-skip" class="homevideo-centerer"> 855 <div class="captionContainerOuter"> 856 <div class="caption-centerer"> 857 <div class="captionContainer"> 858 <p id="mainVideoHeading">HEALTHY FUTURES START HERE</p> 859 <p id="mainVideoSubheading">Explore career-driven programs designed for graduate study and professional success.</p> 860 861 <a href="https://www.sru.edu/programs?interest=Health+and+Medicine%2CWellness+and+Fitness&sort=title-asc" title="Find Your Major" id="mainVideoButton" onclick="#" target="">Find Your Major<span id="chevronsIcon" class="material-symbols-outlined">double_arrow</span></a> 862 </div> 863 </div> 864 </div> 865 <button id="sru-video-toggle-btn" aria-label="Pause video" class="sru-video-control-btn"> 866 <i class="bi bi-pause-fill"></i> 867 </button> 868 </div> 869 <div class="masthead-video" style="background-image: url('/images/Home/video-fallback/healthcare-hero-fallback.jpg');"> 870 <img class="fallbackImage" tabindex="-1" alt="Students looking at musculoskeletal system" src="/images/Home/video-fallback/healthcare-hero-fallback.jpg"/> 871 <video id="actualVideo" tabindex="-1" aria-hidden="true" oncanplay="hideFallbackImage()" playsinline autoplay muted loop width="100%" height="100%"> 872 <source src="//rockpride.sru.edu/videos/homepage/HealthcareHero.mp4" type="video/mp4"> 873 </video> 874 <p style="position:absolute; left:-9999px; top:auto; width:1px; height:1px; overflow:hidden;">This background video, without audio, shows several clips of Slippery Rock University students enjoying multiple experiences on campus.</p> 875 876 </div> 877 878 <ul class="call-to-action"> 879 <li class="ctaButton" style="border-left:none;"> <a href="/admissions/apply-now" >Apply</a> 880</li> 881 <li class="ctaButton"> <a href="/admissions/visit-the-rock" >Visit</a> 882</li> 883 <li class="ctaButton" style="border-right:none;"> <a href="/admissions/request-information" >Request Info</a> 884</li> 885 </ul> 886 887 <!-- /masthead-inner-container --> 888 </section> 889 <section id="billboardSection" class="billboards" role="region" aria-label="SRU Billboards"> 890 891<!--Billboards Start--> 892 893 <!-- box 1 --> 894
895 <span class="mastheadSpanner" id="masthead1"> 896 <div class="quarterBoxLeft" id="imageBox1"> 897 <a href="https://news.sru.edu/events/photo/?tribe-bar-search=Hispanic+Heritage+Month" tabindex="-1" title="Learn More" target="_blank"> 898 <img alt="Join us to celebrate Hispanic Heritage" src="/images/Home/billboard/HispanicHeritageMonth26.jpg" /></a> 899 900 </div> 901 902 <div class="quarterBoxLeft" id="captionBox1"> 903 <a href="https://news.sru.edu/events/photo/?tribe-bar-search=Hispanic+Heritage+Month" title="Learn More" target="_blank"> 904 905 <div class="quarterContent" id="quarterContent1"><p class="quarterHeadlinemedium">Together, We Are More</p><p class="quarterSubheadline">Experience music, culture and meaningful conversations as SRU celebrates Hispanic Heritage Month, Sept. 15 to Oct. 15. <span class="material-symbols-outlined chevron-billboard">double_arrow</span></p> 906 </div></a> 907 </div> 908 </span> 909 910<!-- box 2 --> 911 912 913<!--Billboards Start--> 914 915 <!-- box 1 --> 916 917 918<!-- box 2 --> 919 920 <span class="mastheadSpanner" id="masthead2"> 921 <div class="quarterBoxRight" id="captionBox2"> 922 <a href="https://sideline.bsnsports.com/schools/pennsylvania/slipperyrock/slippery-rock-university" title="View Now" target="_blank"> 923 <div class="quarterContent"><p class="quarterHeadlinemedium">Fresh Starts. Fresh Styles.</p><p class="quarterSubheadline">Gear up with fresh Rock apparel by visiting the new SRU Sideline Store and receive a 20% discount through Oct. 17. <span class="material-symbols-outlined chevron-billboard">double_arrow</span></p></div> 924 </a></div> 925 926 <div class="quarterBoxRight" id="imageBox2"> 927 <a href="https://sideline.bsnsports.com/schools/pennsylvania/slipperyrock/slippery-rock-university" tabindex="-1" title="View Now" target="_blank"> 928 <img alt="SideLine Store Items and Grand Opening" src="/images/Home/billboard/sideline-store-billboard.jpg" /> 929 </a> 930 </div> 931 932 </span> 933 </section> 934 <!-- /masthead --> 935 936 937 938 939 940 941<section id="featured-headlines" class="featured-headlines" role="region" aria-label="SRU News"> 942 <div class="featured-headlines-inner-container"> 943 <h2 class="news">Top Stories</h2><span class="insert-js featured"></span> 944 <div class="news-home-button-container"><a href="https://www.sru.edu/news" title="SRU News" id="news-home-button-utility" target="_blank" rel="noopener" aria-label="read top storiesdoublearrow" style=" 945 text-align: center; 946">READ TOP STORIES<span id="chevronsIcon" class="material-symbols-outlined">double_arrow</span></a></div> 947 </div> 948</section> 949<section id="featured-headlines" class="featured-headlines home-awards-section" role="region" aria-label="University Events"> 950 <div class="featured-headlines-inner-container"> 951 <h2 class="news">University Events</h2> 952 <span class="insert-js general"></span> 953 <div class="news-home-button-container" style="width: 325px;"> 954 <a href="https://events.sru.edu" title="University Events" id="news-home-button-utility" rel="noopener" aria-label="view university eventsdoublearrow">VIEW UNIVERSITY EVENTS<span id="chevronsIcon" class="material-symbols-outlined">double_arrow</span></a> 955 </div> 956 </div> 957</section> 958 959 960 961 962 <!--googleoff: all--> 963 964 965 966 967 968<!-- start footer --> 969 <footer class="footer-demo bg-dark-slate-blue pb-4 sm-pb-50px" style="background-image: url(/images/footer/old-main-footer.jpg)" data-sru aria-label="Site footer"> 970 <h2 class="visually-hidden" style="color:#ffffff;">Slippery Rock University Footer</h2> 971 <div> 972 <div class="col-lg-12 col-md-12 col-sm-12 text-center elements-social social-icon-style-09" role="navigation" aria-label="Footer social media links"> 973 <ul class="extra-large-icon light"> 974 <li><a class="facebook" href="https://www.facebook.com/slipperyrockuniversity" id="footer-skip" target="_blank" rel="noopener noreferrer" aria-label="Facebook opens in a new tab"><i class="fa-brands fa-facebook-f" aria-hidden="true"></i><span aria-hidden="true"></span></a></li> 975 <li><a class="instagram" href="https://instagram.com/slipperyrockuniversity/" target="_blank" rel="noopener noreferrer" aria-label="Instagram opens in a new tab"><i class="fa-brands fa-instagram" aria-hidden="true"></i><span aria-hidden="true"></span></a></li> 976 <li><a class="linkedin" href="https://www.linkedin.com/edu/school?id=19309" target="_blank" rel="noopener noreferrer" aria-label="LinkedIn opens in a new tab"><i class="fa-brands fa-linkedin-in" aria-hidden="true"></i><span aria-hidden="true"></span></a></li> 977 <li><a class="youtube" href="https://www.youtube.com/c/slipperyrockuniversity" target="_blank" rel="noopener noreferrer" aria-label="YouTube opens in a new tab"><i class="fa-brands fa-youtube" aria-hidden="true"></i><span aria-hidden="true"></span></a></li> 978 <li><a class="tiktok" href="https://www.tiktok.com/@slipperyrockuniv" target="_blank" rel="noopener noreferrer" aria-label="TikTok opens in a new tab"><i class="fa-brands fa-tiktok" aria-hidden="true"></i><span aria-hidden="true"></span></a></li> 979 <li><a class="zenfolio" href="https://slipperyrockuniversity.zenfolio.com/" target="_blank" rel="noopener noreferrer" aria-label="Zenfolio opens in a new tab"><i class="fa-solid fa-camera" aria-hidden="true"></i><span aria-hidden="true"></span></a></li> 980 <li><a class="vimeo" href="https://vimeo.com/slipperyrockuniversity" target="_blank" rel="noopener noreferrer" aria-label="Vimeo opens in a new tab"><i class="fa-brands fa-vimeo-v" aria-hidden="true"></i><span aria-hidden="true"></span></a></li> 981 <li><a class="heyzine" href="https://heyzine.com/shelf/3616e4631d.html" target="_blank" rel="noopener noreferrer" aria-label="Heyzine opens in a new tab"><i class="fa-solid fa-book-open" aria-hidden="true"></i><span aria-hidden="true"></span></a></li> 982 </ul> 983 </div> 984 </div> 985 986 <div class="container"> 987 <div class="row mb-6 md-mb-30px"> 988 <div class="col-xl-5 col-lg-6 md-mb-30px text-center text-lg-start"> 989 <h3 class="text-white fw-600 alt-font mb-40px ls-minus-1px md-mb-30px md-w-60 sm-w-70 xs-w-100 md-mx-auto">Your First Choice for a <span class="bg-highlight-footer">Rock Solid</span> Education.</h3> 990 <div class="row"> 991 <div class="col-lg-5 col-sm-6 xs-mb-20px"> 992 <span class="alt-font fs-14 fw-600 text-uppercase d-block ls-1px lh-18 sru-gold-text-ada">Admissions</span> 993 <a href="mailto:[email protected]">[email protected]</a> 994 </div> 995 <div class="col-lg-5 col-sm-6">
996 <span class="alt-font fs-14 fw-600 text-uppercase d-block ls-1px lh-18 sru-gold-text-ada">Call Us!</span> 997 <a href="tel:+8007789111">800.778.9111</a> 998 </div> 999 </div> 1000 </div> 1001 <div class="col-lg-2 col-6 offset-xl-1 text-center text-lg-start" role="navigation" aria-label="Join SRU links"> 1002 <span class="alt-font fs-14 fw-600 text-uppercase text-white ls-1px d-block mb-5px" role="heading" aria-level="2">Join SRU</span> 1003 <ul> 1004 <li><a href="/admissions/apply-now">Apply</a></li> 1005 <li><a href="https://careers.sru.edu/" target="_blank" rel="noopener noreferrer" aria-label="Employment Opportunities opens in a new tab">Employment Opportunities</a></li> 1006 <li><a href="/alerts">RockAlerts Emergency Notification System</a></li> 1007 <li><a href="/give">Ways to Give</a></li> 1008 <li><a href="/faculty-and-staff">Faculty & Staff</a></li> 1009 </ul> 1010 </div> 1011 <div class="col-lg-2 col-6 text-center text-lg-start" role="navigation" aria-label="Explore SRU links"> 1012 <span class="alt-font fs-14 fw-600 text-uppercase text-white ls-1px d-block mb-5px" role="heading" aria-level="2">Explore SRU</span> 1013 <ul> 1014 <li><a href="/life-at-sru/campus-climate-and-culture">Campus Climate & Culture</a></li> 1015 <li><a href="/map" target="_blank" rel="noopener noreferrer" aria-label="Campus Maps opens in a new tab">Campus Maps</a></li> 1016 <li><a href="/offices">Discover Offices </a></li> 1017 <li><a href="/directory">Find People</a></li> 1018 <li><a href="/events">University Events</a></li> 1019 <li><a href="https://news.sru.edu" target="_blank" rel="noopener noreferrer" aria-label="University News opens in a new tab">University News</a></li> 1020 <li><a href="https://www.experiencebutler.com/" target="_blank" rel="noopener noreferrer">Experience Butler County<span class="visually-hidden"> (opens in a new tab)</span> <i class="fa-solid fa-up-right-from-square ms-1" aria-hidden="true"></i></a></li> 1021 </ul> 1022 </div> 1023 1024 <div class="col-lg-2 order-first order-lg-4 text-center text-lg-start md-mb-20px"> 1025 <a href="/" class="footer-logo" aria-label="Slippery Rock University home"><img src="/images/logos/sru-seal-white.png" data-at2x="/images/logos/sru-seal-white.png" alt="SRU Modern Seal"></a> 1026 <div class="row mt-3 footer-copyright-wrap"> 1027 <div class="col-12"> 1028 <p class="footer-copyright mb-0 text-center"> 1029 © Slippery Rock University of Pennsylvania 1030 </p> 1031 </div> 1032 </div> 1033 </div> 1034 </div> 1035 <div class="row"> 1036 <div class="col-12" role="navigation" aria-label="Footer legal links"> 1037 <ul class="footer-legal-links justify-content-center justify-content-lg-start"> 1038 <li><a href="/academics/academic-services/services-for-students-with-disabilities/accessibility-statement">Accessibility Statement</a></li> 1039 <li><a href="/students/student-consumer-information">Consumer Information</a></li> 1040 <li><a href="https://secure.ethicspoint.com/domain/media/en/gui/37117/index.html" target="_blank" rel="noopener noreferrer" aria-label="Fraud & Abuse Hotline opens in a new tab">Fraud & Abuse Hotline</a></li> 1041 <li><a href="https://www.passhe.edu/student-complaints.html" target="_blank" rel="noopener noreferrer" aria-label="File a Complaint opens in a new tab">File a Complaint</a></li> 1042 <li><a href="https://rockpride.sru.edu/policies/#search=discrimination">Non-discrimination</a></li> 1043 <li><a href="/web-privacy">Privacy Statement</a></li> 1044 <li><a href="https://rockpride.sru.edu/policies/">Policies</a></li> 1045 <li><a href="/right-to-know">Right to Know</a></li> 1046 <li><a href="https://rockpride.sru.edu/support/">Support</a></li> 1047 <li><a href="/title-ix">Title IX</a></li> 1048 </ul> 1049 </div> 1050 </div> 1051 1052 <div class="access"> 1053 <a href="/#top" class="back-to-top" aria-label="Back to Top">Back to Top</a> 1054 </div><!-- /access --> 1055
1055<script type="application/ld+json"> 1056{ "@context" : "http://schema.org", 1057 "@type" : "Organization", 1058 "name" : "Slippery Rock University of Pennsylvania", 1059 "url" : "https://www.sru.edu", 1060 "sameAs" : [ "https://www.facebook.com/slipperyrockuniversity", 1061 "https://www.linkedin.com/edu/school?id=19309", 1062 "https://instagram.com/slipperyrockuniversity", 1063 "https://www.youtube.com/c/slipperyrockuniversity", 1064 "https://slipperyrockuniversity.zenfolio.com/"] 1065} 1066 </script>
1066 1067 </footer> 1068 <!-- end footer --> 1069 1070 <!--googleon: all--> 1071 1072
1072<script src="/prebuilt/js/global.js?v=547"></script>
1072 1073 1074
1074<script src="/prebuilt/ui/js/jquery-ui-1.10.4.custom.min.js?v=1" type="text/javascript"></script>
1074 1075 1076
1076<script src="/prebuilt/js/main.js?v=547"></script>
1076 1077 1078
1078<script src="/prebuilt/js/carousel.js?v=547"></script>
1078 1079 1080 1081
1081<script src="/prebuilt/js/touch.js?v=547"></script>
1081 1082 1083 1084 1085
1086<script> 1087 function updateRequestText() { 1088 const items = document.querySelectorAll("li.ctaButton"); 1089 const targetItem = items[2]; // 0-based index: 3rd item 1090 1091 if (!targetItem) return; 1092 1093 const link = targetItem.querySelector("a"); 1094 if (!link) return; 1095 1096 if (window.innerWidth <= 500) { 1097 link.textContent = "Request"; 1098 } else { 1099 link.textContent = "Request Info"; 1100 } 1101 } 1102 1103 // Initial check 1104 updateRequestText(); 1105 1106 // Update on resize 1107 window.addEventListener("resize", updateRequestText); 1108</script>
1108 1109
1110<script> 1111 // Get the video and the button elements 1112 const video = document.getElementById('actualVideo'); 1113 const toggleButton = document.getElementById('sru-video-toggle-btn'); 1114 1115 // Function to handle the play/pause toggle 1116 function toggleVideoPlayPause() { 1117 if (video.paused) { 1118 video.play(); 1119 toggleButton.innerHTML = '<i class="bi bi-pause-fill"></i>'; 1120 toggleButton.setAttribute('aria-label', 'Pause video'); 1121 } else { 1122 video.pause(); 1123 toggleButton.innerHTML = '<i class="bi bi-play-fill"></i>'; 1124 toggleButton.setAttribute('aria-label', 'Play video'); 1125 } 1126 } 1127 1128 // Attach the toggle function to the button's click event 1129 toggleButton.addEventListener('click', toggleVideoPlayPause); 1130</script>
1130 1131
1132<script> 1133/** 1134 * News + Events with skeleton loaders + per-image loading spinner 1135 * Updated for new WordPress news custom post type + The Events Calendar REST API 1136 */ 1137(function () { 1138 const NEWS_BASE = "https://news.sru.edu/wp-json/wp/v2"; 1139 const NEWS_CATEGORY_SLUG = "topdisplay"; 1140 const NEWS_EXCLUDE_FETCH = ["not-on-homepage"]; 1141 const NEWS_EXCLUDE_BADGES = ["featured", "not-on-homepage", "topdisplay"]; 1142 1143 const EVENTS_ENDPOINT = "https://news.sru.edu/wp-json/tribe/events/v1/events"; 1144 const EVENTS_TIMEOUT_MS = 3000; 1145 const EVENTS_MAX_ATTEMPTS = 4; 1146 1147 // Number of cards actually displayed. 1148 const COUNT = 3; 1149 1150 // Fetch a broad candidate pool so ongoing multi-day events 1151 // are not missed before local expiration filtering occurs. 1152 const EVENTS_FETCH_COUNT = 100; 1153 1154 const safeText = (html) => { 1155 const tmp = new DOMParser().parseFromString(String(html || ""), "text/html"); 1156 return tmp.body.textContent || ""; 1157 }; 1158 1159 const formatNewsDate = (iso) => 1160 new Intl.DateTimeFormat("en-US", { 1161 month: "long", 1162 day: "numeric", 1163 year: "numeric" 1164 }).format(new Date(iso)); 1165 1166 /** 1167 * Format a Date object as YYYY-MM-DD for TEC. 1168 */ 1169 function formatApiDate(d) { 1170 return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`; 1171 } 1172 1173 /** 1174 * Look back 30 days so an ongoing multi-day event 1175 * can still be returned even though its start date 1176 * is already in the past. 1177 */ 1178 function getApiWindowStart() { 1179 const d = new Date(); 1180 1181 d.setDate(d.getDate() - 30); 1182 1183 return formatApiDate(d); 1184 } 1185 1186 /** 1187 * Look ahead six months so we have plenty of 1188 * upcoming events available to fill the three cards. 1189 */ 1190 function getApiWindowEnd() { 1191 const d = new Date(); 1192 1193 d.setMonth(d.getMonth() + 6); 1194 1195 return formatApiDate(d); 1196 } 1197 1198 /** 1199 * Build the TEC API URL using a broad date window. 1200 * 1201 * Expired events may be returned by this request, 1202 * but isEventStillCurrent() removes them before 1203 * anything is displayed. 1204 */ 1205 function buildEventsApiUrl() { 1206 const params = new URLSearchParams({ 1207 per_page: EVENTS_FETCH_COUNT, 1208 start_date: getApiWindowStart(), 1209 end_date: getApiWindowEnd() 1210 }); 1211 1212 return `${EVENTS_ENDPOINT}?${params.toString()}`; 1213 } 1214 1215 /** 1216 * Parse The Events Calendar date strings consistently. 1217 * 1218 * TEC commonly returns values like: 1219 * 2026-08-25 14:00:00 1220 * 1221 * Converting the space to "T" makes it reliably parse as a local 1222 * date/time instead of relying on browser-specific parsing. 1223 */ 1224 function parseEventDate(value) { 1225 if (!value) return null; 1226 1227 const normalized = String(value).trim().replace(" ", "T"); 1228 const date = new Date(normalized); 1229 1230 return isNaN(date.getTime()) ? null : date; 1231 } 1232 1233 /** 1234 * Returns midnight immediately AFTER the supplied event date. 1235 * 1236 * Example: 1237 * Event date = Aug. 25 1238 * Expiration = Aug. 26 at 12:00 AM 1239 */ 1240 function getNextMidnight(value) { 1241 const date = parseEventDate(value); 1242 if (!date) return null; 1243 1244 return new Date( 1245 date.getFullYear(), 1246 date.getMonth(), 1247 date.getDate() + 1, 1248 0, 1249 0, 1250 0, 1251 0 1252 ); 1253 } 1254 1255 /** 1256 * Determine whether an event should still be displayed. 1257 * 1258 * Rules: 1259 * 1260 * 1. Timed event with a valid end date/time: 1261 * Keep it until the exact end time. 1262 * 1263 * 2. All-day event: 1264 * Keep it through its final calendar day. 1265 * Remove it at midnight the following day. 1266 * 1267 * 3. Event without a usable end date/time: 1268 * Keep it for its start date. 1269 * Remove it at midnight the following day. 1270 */ 1271 function isEventStillCurrent(ev) { 1272 const now = new Date(); 1273 1274 const start = parseEventDate(ev.start_date); 1275 const end = parseEventDate(ev.end_date); 1276 1277 const isAllDay = 1278 ev.all_day === true || 1279 ev.all_day === 1 || 1280 ev.all_day === "1" || 1281 ev.all_day === "true"; 1282 1283 // All-day event: 1284 // use the end date when available, otherwise the start date. 1285 if (isAllDay) { 1286 const expiration = getNextMidnight(ev.end_date || ev.start_date); 1287 1288 if (!expiration) { 1289 return true; 1290 } 1291 1292 return now < expiration; 1293 } 1294 1295 // Normal timed event with an end time. 1296 if (end) { 1297 return now < end; 1298 } 1299 1300 // No end time: 1301 // keep it through the start date, then remove at midnight. 1302 if (start) { 1303 const expiration = getNextMidnight(ev.start_date); 1304 1305 if (!expiration) { 1306 return true; 1307 } 1308 1309 return now < expiration; 1310 } 1311 1312 // If TEC somehow gives us an event with unusable date data, 1313 // don't silently throw it away. 1314 return true; 1315 } 1316 1317 /** 1318 * Format the event date/date range. 1319 * 1320 * An event beginning exactly at midnight is displayed 1321 * as "All Day" instead of "12:00 AM". 1322 */ 1323 function formatEventDateRange(startIso, endIso, allDay = false) { 1324 const s = parseEventDate(startIso); 1325 const e = endIso ? parseEventDate(endIso) : null; 1326 1327 if (!s) return ""; 1328 1329 const dateFull = new Intl.DateTimeFormat("en-US", { 1330 month: "long", 1331 day: "numeric", 1332 year: "numeric" 1333 });
1334 1335 const dateMonthDay = new Intl.DateTimeFormat("en-US", { 1336 month: "long", 1337 day: "numeric" 1338 }); 1339 1340 const dayOnly = new Intl.DateTimeFormat("en-US", { 1341 day: "numeric" 1342 }); 1343 1344 const timeFmt = new Intl.DateTimeFormat("en-US", { 1345 hour: "numeric", 1346 minute: "2-digit" 1347 }); 1348 1349 const startsAtMidnight = 1350 s.getHours() === 0 && 1351 s.getMinutes() === 0 && 1352 s.getSeconds() === 0; 1353 1354 if (!e || isNaN(e.getTime())) { 1355 if (allDay || startsAtMidnight) { 1356 return `${dateFull.format(s)}, All Day`; 1357 } 1358 1359 return `${dateFull.format(s)}, ${timeFmt.format(s)}`; 1360 } 1361 1362 const sameY = 1363 s.getFullYear() === e.getFullYear(); 1364 1365 const sameM = 1366 s.getMonth() === e.getMonth(); 1367 1368 const sameD = 1369 s.getDate() === e.getDate(); 1370 1371 if (sameY && sameM && sameD) { 1372 if (allDay || startsAtMidnight) { 1373 return `${dateFull.format(s)}, All Day`; 1374 } 1375 1376 return `${dateFull.format(s)}, ${timeFmt.format(s)}`; 1377 } 1378 1379 if (sameY) { 1380 if (sameM) { 1381 return `${dateMonthDay.format(s)}â${dayOnly.format(e)}, ${s.getFullYear()}`; 1382 } 1383 1384 return `${dateMonthDay.format(s)} â ${dateMonthDay.format(e)}, ${s.getFullYear()}`; 1385 } 1386 1387 return `${dateFull.format(s)} â ${dateFull.format(e)}`; 1388 } 1389 1390 function injectSharedCSS() { 1391 if (document.getElementById("sru-skeleton-css")) return; 1392 1393 const css = ` 1394 .image-wrapper { 1395 position:relative; 1396 width:100%; 1397 aspect-ratio:16/9; 1398 overflow:visible; 1399 background:#f3f3f3; 1400 } 1401 1402 @supports not (aspect-ratio:1) { 1403 .image-wrapper { 1404 height:220px; 1405 } 1406 } 1407 1408 .image-wrapper img { 1409 width:100%; 1410 height:100%; 1411 object-fit:cover; 1412 display:block; 1413 opacity:0; 1414 transition:transform .3s ease, box-shadow .3s ease; 1415 } 1416 1417 .image-wrapper.img-loaded img { 1418 opacity:1; 1419 } 1420 1421 .img-loader { 1422 position:absolute; 1423 inset:0; 1424 display:flex; 1425 align-items:center; 1426 justify-content:center; 1427 background:rgba(255,255,255,0.6); 1428 transition:opacity .3s ease, visibility .3s ease; 1429 } 1430 1431 .image-wrapper.img-loaded .img-loader { 1432 opacity:0; 1433 visibility:hidden; 1434 } 1435 1436 .spinner { 1437 width:32px; 1438 height:32px; 1439 border:3px solid #ddd; 1440 border-top-color:#999; 1441 border-radius:50%; 1442 animation:sru-spin 1s linear infinite; 1443 } 1444 1445 @keyframes sru-spin { 1446 to { 1447 transform:rotate(360deg); 1448 } 1449 } 1450 1451 .skel-card { 1452 display:flex; 1453 flex-direction:column; 1454 } 1455 1456 .skel-block { 1457 border-radius:6px; 1458 background:linear-gradient( 1459 90deg, 1460 #eee 25%, 1461 #f5f5f5 37%, 1462 #eee 63% 1463 ); 1464 background-size:400% 100%; 1465 animation:skel-shimmer 1.25s linear infinite; 1466 } 1467 1468 .skel-img { 1469 width:100%; 1470 height:100%; 1471 } 1472 1473 .skel-line { 1474 height:14px; 1475 margin-top:10px; 1476 } 1477 1478 .skel-line.w60 { 1479 width:60%; 1480 } 1481 1482 .skel-line.w80 { 1483 width:80%; 1484 } 1485 1486 .skel-line.w40 { 1487 width:40%; 1488 } 1489 1490 @keyframes skel-shimmer { 1491 0% { 1492 background-position:100% 0; 1493 } 1494 1495 100% { 1496 background-position:0 0; 1497 } 1498 } 1499 1500 .post-category { 1501 position:absolute; 1502 bottom:8px; 1503 left:8px; 1504 background:rgba(0,0,0,.72); 1505 color:#fff; 1506 padding:6px 10px; 1507 font-size:13px; 1508 font-weight:700; 1509 border-radius:4px; 1510 text-transform:uppercase; 1511 text-decoration:none; 1512 z-index:10; 1513 margin-right:6px; 1514 display:inline-block; 1515 } 1516 1517 .post-category + .post-category { 1518 margin-left:6px; 1519 } 1520 `; 1521 1522 const style = document.createElement("style"); 1523 style.id = "sru-skeleton-css"; 1524 style.textContent = css; 1525 1526 document.head.appendChild(style); 1527 } 1528
1529 function renderSkeletonCard(extraItemClasses = "") { 1530 const item = document.createElement("div"); 1531 item.className = 1532 `flex-item ${extraItemClasses}`.trim() + 1533 " skel-card"; 1534 1535 const imgWrap = document.createElement("div"); 1536 imgWrap.className = "image-wrapper"; 1537 1538 const skelImg = document.createElement("div"); 1539 skelImg.className = "skel-block skel-img"; 1540 1541 imgWrap.appendChild(skelImg); 1542 1543 const content = document.createElement("div"); 1544 content.className = "flex-content"; 1545 1546 ["w60", "w80", "w40"].forEach(w => { 1547 const line = document.createElement("div"); 1548 1549 line.className = 1550 `skel-block skel-line ${w}`; 1551 1552 content.appendChild(line); 1553 }); 1554 1555 item.appendChild(imgWrap); 1556 item.appendChild(content); 1557 1558 return item; 1559 } 1560 1561 function makeContainer( 1562 targetSelector, 1563 extraContainerClasses = "" 1564 ) { 1565 const mount = 1566 document.querySelector(targetSelector); 1567 1568 if (!mount) return null; 1569 1570 const container = 1571 document.createElement("div"); 1572 1573 container.className = 1574 `flex-container ${extraContainerClasses}`.trim(); 1575 1576 mount.appendChild(container); 1577 1578 return container; 1579 } 1580 1581 function withImgLoader(imageWrapper, img) { 1582 const overlay = 1583 document.createElement("div"); 1584 1585 overlay.className = "img-loader"; 1586 1587 const spin = 1588 document.createElement("div"); 1589 1590 spin.className = "spinner"; 1591 1592 overlay.appendChild(spin); 1593 imageWrapper.appendChild(overlay); 1594 1595 const markLoaded = () => 1596 imageWrapper.classList.add("img-loaded"); 1597 1598 img.addEventListener( 1599 "load", 1600 markLoaded, 1601 { once:true } 1602 ); 1603 1604 img.addEventListener( 1605 "error", 1606 markLoaded, 1607 { once:true } 1608 ); 1609 } 1610 1611 function getNewsCategoriesFromEmbed(post) { 1612 const terms = 1613 post && 1614 post._embedded && 1615 post._embedded["wp:term"] 1616 ? post._embedded["wp:term"] 1617 .flat() 1618 .filter(Boolean) 1619 : []; 1620 1621 const exclude = 1622 new Set(NEWS_EXCLUDE_BADGES); 1623 1624 const categories = terms 1625 .filter( 1626 t => 1627 t.taxonomy === "category" && 1628 t.slug && 1629 !exclude.has(t.slug) 1630 ); 1631 1632 /* 1633 * One-time override: 1634 * For the Sept. 22, 2026 news article, prefer Faculty Focus 1635 * if the article belongs to that category. 1636 */ 1637 const postDate = 1638 String(post.date || "").slice(0, 10); 1639 1640 if (postDate === "2026-09-22") { 1641 const facultyFocus = 1642 categories.find( 1643 t => t.slug === "faculty-focus" 1644 ); 1645 1646 if (facultyFocus) { 1647 return [{ 1648 name: facultyFocus.name, 1649 1650 link: facultyFocus.link 1651 ? facultyFocus.link.replace( 1652 "/category/", 1653 "/news/" 1654 ) 1655 : `https://news.sru.edu/${facultyFocus.slug}/` 1656 }]; 1657 } 1658 } 1659 1660 /* 1661 * Normal behavior: 1662 * use the first eligible news category. 1663 */ 1664 return categories 1665 .slice(0, 1) 1666 .map(t => ({ 1667 name:t.name, 1668 1669 link:t.link 1670 ? t.link.replace( 1671 "/category/", 1672 "/news/" 1673 ) 1674 : `https://news.sru.edu/${t.slug}/` 1675 })); 1676 } 1677 1678 function getEventCategoryNames(ev) { 1679 const arr = 1680 Array.isArray(ev.categories) 1681 ? ev.categories 1682 : []; 1683 1684 return arr 1685 .map(c => c && c.name) 1686 .filter(Boolean) 1687 .slice(0, 1); 1688 } 1689 1690 async function fetchJSON(url, opts = {}) { 1691 const res = await fetch(url, { 1692 cache:"no-store", 1693 ...opts 1694 }); 1695 1696 if (!res.ok) { 1697 throw new Error( 1698 "HTTP " + res.status 1699 ); 1700 } 1701 1702 return res.json(); 1703 } 1704 1705 async function fetchWithTimeoutRetry( 1706 url, 1707 options = {}, 1708 timeoutMs = 3000, 1709 maxAttempts = 4 1710 ) { 1711 for ( 1712 let attempt = 1; 1713 attempt <= maxAttempts; 1714 attempt++ 1715 ) { 1716 const controller = 1717 new AbortController(); 1718 1719 const timer = 1720 setTimeout( 1721 () => controller.abort(), 1722 timeoutMs 1723 ); 1724
1725 try { 1726 const res = await fetch(url, { 1727 ...options, 1728 signal:controller.signal, 1729 cache:"no-store" 1730 }); 1731 1732 clearTimeout(timer); 1733 1734 if (!res.ok) { 1735 throw new Error( 1736 "HTTP " + res.status 1737 ); 1738 } 1739 1740 return await res.json(); 1741 1742 } catch (err) { 1743 clearTimeout(timer); 1744 1745 if (attempt === maxAttempts) { 1746 throw err; 1747 } 1748 1749 await new Promise( 1750 r => setTimeout(r, 500) 1751 ); 1752 } 1753 } 1754 } 1755 1756 async function loadNews() { 1757 injectSharedCSS(); 1758 1759 const container = 1760 makeContainer( 1761 ".insert-js.featured" 1762 ); 1763 1764 if (!container) return; 1765 1766 const skels = []; 1767 1768 for ( 1769 let i = 0; 1770 i < COUNT; 1771 i++ 1772 ) { 1773 const s = 1774 renderSkeletonCard(); 1775 1776 skels.push(s); 1777 container.appendChild(s); 1778 } 1779 1780 try { 1781 let excludeIds = []; 1782 1783 if (NEWS_EXCLUDE_FETCH.length) { 1784 const results = 1785 await Promise.all( 1786 NEWS_EXCLUDE_FETCH.map( 1787 slug => 1788 fetchJSON( 1789 `${NEWS_BASE}/categories?slug=${encodeURIComponent(slug)}` 1790 ) 1791 ) 1792 ); 1793 1794 excludeIds = 1795 results 1796 .flat() 1797 .map(c => c.id) 1798 .filter(Boolean); 1799 } 1800 1801 const catArr = 1802 await fetchJSON( 1803 `${NEWS_BASE}/categories?slug=${encodeURIComponent(NEWS_CATEGORY_SLUG)}` 1804 ); 1805 1806 if ( 1807 !Array.isArray(catArr) || 1808 !catArr.length 1809 ) { 1810 container.innerHTML = 1811 `<p>'${NEWS_CATEGORY_SLUG}' category not found.</p>`; 1812 1813 return; 1814 } 1815 1816 const categoryId = 1817 catArr[0].id; 1818 1819 let url = 1820 `${NEWS_BASE}/news?categories=${categoryId}&_embed&per_page=${COUNT}`; 1821 1822 if (excludeIds.length) { 1823 url += 1824 `&categories_exclude=${excludeIds.join(",")}`; 1825 } 1826 1827 const posts = 1828 await fetchJSON(url); 1829 1830 if ( 1831 !Array.isArray(posts) || 1832 !posts.length 1833 ) { 1834 container.innerHTML = 1835 `<p>No posts found for '${NEWS_CATEGORY_SLUG}'.</p>`; 1836 1837 return; 1838 } 1839 1840 posts.forEach( 1841 (post, idx) => { 1842 const card = 1843 document.createElement("div"); 1844 1845 card.className = 1846 "flex-item"; 1847 1848 const imageWrapper = 1849 document.createElement("div"); 1850 1851 imageWrapper.className = 1852 "image-wrapper"; 1853 1854 const media = 1855 post._embedded && 1856 post._embedded["wp:featuredmedia"] && 1857 post._embedded["wp:featuredmedia"][0]; 1858 1859 if ( 1860 media && 1861 media.source_url 1862 ) { 1863 const a = 1864 document.createElement("a"); 1865 1866 a.href = post.link; 1867 a.target = "_blank"; 1868 a.rel = 1869 "noopener noreferrer"; 1870 1871 const img = 1872 document.createElement("img"); 1873 1874 img.loading = "lazy"; 1875 img.src = 1876 media.source_url; 1877 1878 img.alt = 1879 media.alt_text || 1880 safeText( 1881 post.title.rendered || 1882 "News image" 1883 ); 1884 1885 withImgLoader( 1886 imageWrapper, 1887 img 1888 ); 1889 1890 a.appendChild(img); 1891 imageWrapper.appendChild(a); 1892 } 1893 1894 getNewsCategoriesFromEmbed(post) 1895 .forEach(t => { 1896 const a = 1897 document.createElement("a"); 1898 1899 a.className = 1900 "post-category"; 1901 1902 a.href = t.link; 1903 a.target = "_blank"; 1904 a.rel = 1905 "noopener noreferrer"; 1906 1907 a.textContent = 1908 safeText(t.name); 1909 1910 imageWrapper.appendChild(a); 1911 }); 1912 1913 card.appendChild( 1914 imageWrapper 1915 ); 1916 1917 const content = 1918 document.createElement("div"); 1919 1920 content.className = 1921 "flex-content"; 1922 1923 const pub = 1924 document.createElement("div"); 1925 1926 pub.className = 1927 "pubdate"; 1928 1929 pub.textContent = 1930 formatNewsDate( 1931 post.date 1932 ); 1933 1934 content.appendChild(pub); 1935 1936 const h3 = 1937 document.createElement("h3"); 1938 1939 h3.className = 1940 "article-title"; 1941 1942 const titleA = 1943 document.createElement("a"); 1944 1945 titleA.href = 1946 post.link; 1947 1948 titleA.target = 1949 "_blank"; 1950 1951 titleA.rel = 1952 "noopener noreferrer"; 1953 1954 titleA.textContent = 1955 safeText( 1956 post.title.rendered || 1957 "Untitled" 1958 ); 1959 1960 h3.appendChild(titleA); 1961 content.appendChild(h3); 1962 1963 card.appendChild(content); 1964 1965 if ( 1966 skels[idx] && 1967 skels[idx].parentNode 1968 ) { 1969 skels[idx] 1970 .parentNode 1971 .replaceChild( 1972 card, 1973 skels[idx] 1974 ); 1975 } else { 1976 container.appendChild(card); 1977 } 1978 } 1979 ); 1980 1981 for ( 1982 let j = posts.length; 1983 j < skels.length; 1984 j++ 1985 ) { 1986 if ( 1987 skels[j] && 1988 skels[j].parentNode 1989 ) { 1990 skels[j] 1991 .parentNode 1992 .removeChild( 1993 skels[j] 1994 ); 1995 } 1996 } 1997 1998 } catch (err) { 1999 console.error( 2000 "[news] load failed:", 2001 err 2002 ); 2003 2004 container.innerHTML = 2005 "<p>News is currently unavailable. Please try again later.</p>"; 2006 } 2007 } 2008 2009 async function loadEvents() { 2010 injectSharedCSS(); 2011 2012 const container = 2013 makeContainer( 2014 ".insert-js.general", 2015 "awards-flex-container" 2016 ); 2017 2018 if (!container) return; 2019 2020 const skels = []; 2021 2022 for ( 2023 let i = 0; 2024 i < COUNT; 2025 i++ 2026 ) { 2027 const s = 2028 renderSkeletonCard( 2029 "awards-flex-item" 2030 ); 2031 2032 skels.push(s); 2033 container.appendChild(s); 2034 } 2035 2036 try { 2037 /* 2038 * Fetch a broad window of events. 2039 * 2040 * The 30-day lookback makes sure an ongoing multi-day 2041 * event is returned even when its start date has passed. 2042 * 2043 * Expired events are removed locally BEFORE taking 2044 * the first three cards. 2045 */ 2046 const data = 2047 await fetchWithTimeoutRetry( 2048 buildEventsApiUrl(), 2049 {}, 2050 EVENTS_TIMEOUT_MS, 2051 EVENTS_MAX_ATTEMPTS 2052 ); 2053 2054 const allEvents = 2055 Array.isArray(data.events) 2056 ? data.events 2057 : []; 2058 2059 /* 2060 * Remove events whose actual display life has ended. 2061 * 2062 * Timed event: 2063 * disappears immediately after its end date/time. 2064 * 2065 * All-day event: 2066 * remains through its final calendar day. 2067 * 2068 * No-end-time event: 2069 * disappears at midnight following its start day. 2070 */ 2071 const items = 2072 allEvents 2073 .filter( 2074 isEventStillCurrent 2075 ) 2076 .slice( 2077 0, 2078 COUNT 2079 ); 2080 2081 if (!items.length) { 2082 container.innerHTML = 2083 "<p>No upcoming events available.</p>"; 2084 2085 return; 2086 } 2087
2088 items.forEach( 2089 (ev, idx) => { 2090 const card = 2091 document.createElement("div"); 2092 2093 card.className = 2094 "flex-item awards-flex-item"; 2095 2096 const imageWrapper = 2097 document.createElement("div"); 2098 2099 imageWrapper.className = 2100 "image-wrapper"; 2101 2102 const eventUrl = 2103 ev.url || "#"; 2104 2105 const imageUrl = 2106 ev.image && 2107 ev.image.url 2108 ? ev.image.url 2109 : ""; 2110 2111 const title = 2112 ev.title || 2113 "Untitled event"; 2114 2115 if (imageUrl) { 2116 const a = 2117 document.createElement("a"); 2118 2119 a.href = 2120 eventUrl; 2121 2122 a.tabIndex = -1; 2123 a.target = "_blank"; 2124 2125 a.rel = 2126 "noopener noreferrer"; 2127 2128 const img = 2129 document.createElement("img"); 2130 2131 img.loading = "lazy"; 2132 img.src = imageUrl; 2133 2134 img.alt = 2135 safeText( 2136 title || 2137 "Event image" 2138 ); 2139 2140 withImgLoader( 2141 imageWrapper, 2142 img 2143 ); 2144 2145 a.appendChild(img); 2146 imageWrapper.appendChild(a); 2147 } 2148 2149 getEventCategoryNames(ev) 2150 .forEach(name => { 2151 const badge = 2152 document.createElement("a"); 2153 2154 badge.className = 2155 "post-category"; 2156 2157 badge.href = 2158 eventUrl; 2159 2160 badge.target = 2161 "_blank"; 2162 2163 badge.rel = 2164 "noopener noreferrer"; 2165 2166 badge.textContent = 2167 safeText(name); 2168 2169 imageWrapper.appendChild( 2170 badge 2171 ); 2172 }); 2173 2174 card.appendChild( 2175 imageWrapper 2176 ); 2177 2178 const content = 2179 document.createElement("div"); 2180 2181 content.className = 2182 "flex-content"; 2183 2184 const dateDiv = 2185 document.createElement("div"); 2186 2187 dateDiv.className = 2188 "pubdate"; 2189 2190 const isAllDay = 2191 ev.all_day === true || 2192 ev.all_day === 1 || 2193 ev.all_day === "1" || 2194 ev.all_day === "true"; 2195 2196 dateDiv.textContent = 2197 formatEventDateRange( 2198 ev.start_date, 2199 ev.end_date, 2200 isAllDay 2201 ); 2202 2203 content.appendChild( 2204 dateDiv 2205 ); 2206 2207 const locationName = 2208 ev.venue && 2209 ev.venue.venue 2210 ? safeText( 2211 ev.venue.venue 2212 ) 2213 : ""; 2214 2215 if (locationName) { 2216 const loc = 2217 document.createElement("div"); 2218 2219 loc.className = 2220 "sru-event-location"; 2221 2222 loc.textContent = 2223 locationName; 2224 2225 content.appendChild(loc); 2226 } 2227 2228 const h3 = 2229 document.createElement("h3"); 2230 2231 h3.className = 2232 "article-title"; 2233 2234 const titleA = 2235 document.createElement("a"); 2236 2237 titleA.href = 2238 eventUrl; 2239 2240 titleA.target = 2241 "_blank"; 2242 2243 titleA.rel = 2244 "noopener noreferrer"; 2245 2246 titleA.textContent = 2247 safeText(title); 2248 2249 h3.appendChild( 2250 titleA 2251 ); 2252 2253 content.appendChild( 2254 h3 2255 ); 2256 2257 card.appendChild( 2258 content 2259 ); 2260 2261 if ( 2262 skels[idx] && 2263 skels[idx].parentNode 2264 ) { 2265 skels[idx] 2266 .parentNode 2267 .replaceChild( 2268 card, 2269 skels[idx] 2270 ); 2271 } else { 2272 container.appendChild( 2273 card 2274 ); 2275 } 2276 } 2277 ); 2278 2279 /* 2280 * Remove unused skeletons if fewer than three 2281 * valid upcoming events remain. 2282 */ 2283 for ( 2284 let j = items.length; 2285 j < skels.length; 2286 j++ 2287 ) { 2288 if ( 2289 skels[j] && 2290 skels[j].parentNode 2291 ) { 2292 skels[j] 2293 .parentNode 2294 .removeChild( 2295 skels[j] 2296 ); 2297 } 2298 } 2299 2300 } catch (err) { 2301 console.error( 2302 "[events] load failed:", 2303 err 2304 ); 2305 2306 container.innerHTML = 2307 "<p>Events are currently unavailable. Please try again later.</p>"; 2308 } 2309 } 2310 2311 loadNews(); 2312 loadEvents(); 2313})(); 2314</script>
2314 2315 2316 2317 2318
2318<script type="text/javascript"> 2319 var querystring = new Date().getTime(); 2320 2321 //On any click 2322 document.addEventListener('click', function (e) { 2323 var x = e.target || e.originalTarget || e.srcElement; 2324 if (x.nodeName === 'A') { 2325 var href = x.getAttribute('href'); 2326 if (href) { 2327 var patt = new RegExp(".pdf"); 2328 if (patt.test(href)) { 2329 href += (/\?/.test(href) ? '&' : '?') + querystring; 2330 x.setAttribute('href', href); 2331 } 2332 } 2333 } 2334 }, false); 2335 2336 </script>
2336 2337 2338 2339 2340
2341<script> 2342//Hamburger mobile nav click propogation fix 2343document.addEventListener('DOMContentLoaded', function () { 2344 var toggler = document.querySelector('.navbar-toggler'); 2345 if (!toggler) return; 2346 2347 toggler.addEventListener('click', function (e) { 2348 e.stopPropagation(); 2349 }); 2350}); 2351</script>
2351 2352
2353<script> 2354(function(){ 2355 var KEY = 'sruCookieAckV2'; 2356 var banner = document.getElementById('sru-cookie-example'); 2357 var btn = document.getElementById('sru-cookie-example-ack'); 2358 var firstSkip = document.querySelector('.skip-links a:last-of-type'); 2359 2360 if (!banner || !btn) return; 2361 2362 var acknowledged = false; 2363 try { acknowledged = localStorage.getItem(KEY) === '1'; } catch(e){} 2364 2365 // If already acknowledged, remove banner immediately 2366 if (acknowledged) { 2367 banner.remove(); 2368 return; 2369 } 2370 2371 // Show banner on first visit 2372 banner.classList.remove('sru-cookie-example--hidden'); 2373 banner.classList.add('sru-cookie-example--visible'); 2374 2375 // Track user input type to decide post-dismiss focus behavior 2376 let keyboardUser = false; 2377 document.addEventListener('keydown', (e) => { 2378 if (e.key === 'Tab' || e.key === 'Enter' || e.key === ' ') { 2379 keyboardUser = true; 2380 } 2381 }); 2382 document.addEventListener('mousedown', () => { keyboardUser = false; }); 2383 document.addEventListener('touchstart', () => { keyboardUser = false; }); 2384 2385 // Explicit consent only 2386 btn.addEventListener('click', function(){ 2387 try { localStorage.setItem(KEY, '1'); } catch(e){} 2388 window.dataLayer = window.dataLayer || []; 2389 window.dataLayer.push({ event: 'sru_cookie_acknowledged' }); 2390 2391 // Remove banner from DOM entirely 2392 banner.remove(); 2393 2394 // Only move focus if user is navigating via keyboard 2395 if (keyboardUser && firstSkip && typeof firstSkip.focus === 'function') { 2396 firstSkip.focus({ preventScroll:true }); 2397 } 2398 }); 2399 2400 // Prevent ESC from dismissing (no implicit consent) 2401 banner.addEventListener('keydown', function(e){ 2402 if(e.key === 'Escape'){ 2403 e.preventDefault(); 2404 e.stopPropagation(); 2405 } 2406 }); 2407 2408})(); 2409</script>
2409 2410
2411<script> 2412//mobile nav dropdown click fix 2413document.addEventListener('DOMContentLoaded', function () { 2414 const mql = window.matchMedia('(max-width: 991.98px)'); 2415 2416 function swallowFor(label) { 2417 // Stop all upstream handlers, but let the link navigate 2418 const handler = (e) => { 2419 if (!mql.matches) return; // desktop: do nothing 2420 e.stopImmediatePropagation(); // kill other handlers (including delegated ones) 2421 // do NOT call preventDefault â we want navigation 2422 }; 2423 // Stop both click and touchstart (many menus listen on touchstart) 2424 label.addEventListener('click', handler, { capture: true }); 2425 label.addEventListener('touchstart', handler, { capture: true }); 2426 } 2427 2428 // 1) Only the text label (not the chevron) should navigate without toggling 2429 document 2430 .querySelectorAll('.nav-link-wrapper > a.nav-link:not(.dropdown-toggle-icon)') 2431 .forEach(swallowFor); 2432 2433 // 2) Ensure the chevron still toggles normally 2434 document.querySelectorAll('.nav-link-wrapper .dropdown-toggle-icon').forEach(toggle => { 2435 const parent = toggle.closest('.nav-item.dropdown'); 2436 const menu = parent && parent.querySelector('.dropdown-menu'); 2437 if (!parent || !menu) return; 2438 2439 const setOpen = (open) => { 2440 parent.classList.toggle('show', open); 2441 menu.classList.toggle('show', open); 2442 toggle.setAttribute('aria-expanded', String(open)); 2443 const icon = toggle.querySelector('.dropdown-icon'); 2444 if (icon) icon.classList.toggle('rotated', open); 2445 }; 2446 2447 toggle.addEventListener('click', (e) => { 2448 if (!mql.matches) return; // desktop: ignore (hover CSS handles it) 2449 e.preventDefault(); 2450 e.stopImmediatePropagation(); 2451 setOpen(!parent.classList.contains('show')); 2452 }); 2453 }); 2454}); 2455</script>
2455 2456
2457<script> 2458//keyboard navigation ada 2459document.addEventListener('DOMContentLoaded', function () { 2460 const dropdowns = document.querySelectorAll('.nav-item.dropdown'); 2461 let lastOpened = null; 2462 let keyboardMode = false; 2463 const menuBreakPoint = 991; // match main.js 2464 2465 // Detect keyboard vs mouse input 2466 document.addEventListener('keydown', e => { 2467 if (['Tab', 'Enter', ' '].includes(e.key)) keyboardMode = true; 2468 }); 2469 document.addEventListener('mousedown', () => keyboardMode = false); 2470 2471 dropdowns.forEach(drop => { 2472 const toggle = drop.querySelector('.dropdown-toggle-icon'); 2473 const icon = toggle ? toggle.querySelector('.dropdown-icon') : null; 2474 if (!toggle) return; 2475 2476 toggle.addEventListener('keydown', e => { 2477 // Enter or Space opens/closes 2478 if (e.key === 'Enter' || e.key === ' ') { 2479 e.preventDefault(); 2480 keyboardMode = true; 2481 const isOpen = drop.classList.contains('open'); 2482 2483 // Close other open dropdowns 2484 document.querySelectorAll('.nav-item.dropdown.open').forEach(d => { 2485 if (d !== drop) { 2486 d.classList.remove('open', 'menu-left'); 2487 const i = d.querySelector('.dropdown-icon'); 2488 const t = d.querySelector('.dropdown-toggle-icon'); 2489 i?.classList.remove('rotated'); 2490 t?.setAttribute('aria-expanded', 'false'); 2491 } 2492 }); 2493 2494 if (!isOpen) { 2495 // Desktop: use existing hover logic 2496 if (window.innerWidth > menuBreakPoint) { 2497 $(drop).trigger('mouseenter'); 2498 } else { 2499 // Mobile: manual toggle 2500 const menu = drop.querySelector('.dropdown-menu'); 2501 const wasVisible = menu?.classList.contains('show'); 2502 document.querySelectorAll('.navbar-nav .dropdown-menu.show').forEach(m => m.classList.remove('show')); 2503 document.querySelectorAll('.navbar-nav .dropdown-toggle.show').forEach(t => t.classList.remove('show')); 2504 if (!wasVisible) { 2505 menu?.classList.add('show'); 2506 toggle.classList.add('show'); 2507 } 2508 } 2509 2510 drop.classList.add('open'); 2511 toggle.setAttribute('aria-expanded', 'true'); 2512 icon?.classList.add('rotated'); 2513 lastOpened = drop; 2514 } else { 2515 $(drop).trigger('mouseleave'); 2516 drop.classList.remove('open', 'menu-left'); 2517 toggle.setAttribute('aria-expanded', 'false'); 2518 icon?.classList.remove('rotated'); 2519 lastOpened = null; 2520 2521 // Mobile: also hide dropdown manually 2522 if (window.innerWidth <= menuBreakPoint) { 2523 drop.querySelector('.dropdown-menu')?.classList.remove('show'); 2524 toggle.classList.remove('show'); 2525 } 2526 } 2527 } 2528 }); 2529 2530 // Hover tracking for mouse users 2531 drop.addEventListener('mouseenter', () => { 2532 if (keyboardMode) return; 2533 2534 lastOpened = drop; 2535 toggle.setAttribute('aria-expanded', 'true'); 2536 icon?.classList.add('rotated'); 2537 }); 2538 2539 drop.addEventListener('mouseleave', () => { 2540 if (keyboardMode) return; 2541 2542 lastOpened = null; 2543 toggle.setAttribute('aria-expanded', 'false'); 2544 icon?.classList.remove('rotated'); 2545 }); 2546 }); 2547 2548}); 2549</script>
2549 2550
2551<script> 2552// utility dropdowns on mobile 2553document.addEventListener('DOMContentLoaded', function () { 2554 const toggle = document.querySelector('.utility-left .menu-toggle'); 2555 const container = document.querySelector('.utility-left'); 2556 const dropdown = document.querySelector('.utility-dropdown'); 2557 2558 if (!toggle || !container || !dropdown) return; 2559 2560 const icon = toggle.querySelector('i'); 2561 2562 toggle.addEventListener('click', function () { 2563 const isOpen = container.classList.toggle('open'); 2564 toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false'); 2565 2566 if (icon) { 2567 icon.classList.toggle('fa-angle-down', !isOpen); 2568 icon.classList.toggle('fa-angle-up', isOpen); 2569 } 2570 }); 2571}); 2572</script>
2572 2573
2574<script> 2575//Search skip link and search focus items 2576document.addEventListener('DOMContentLoaded', () => { 2577 2578 const input = document.getElementById('keywords'); 2579 const panel = document.querySelector('.search-form-wrapper'); 2580 const openBtn = document.querySelector('.header-search-form, .search-form-icon'); 2581 const closeBtn = document.querySelector('.search-close'); 2582 2583 // ------------------------------- 2584 // Visibility helper 2585 // ------------------------------- 2586 function isVisible(el) { 2587 if (!el) return false; 2588 const s = window.getComputedStyle(el); 2589 return s.display !== 'none' && s.visibility !== 'hidden'; 2590 } 2591 2592 // ------------------------------- 2593 // Focus the input when visible 2594 // ------------------------------- 2595 function focusWhenVisible() { 2596 let tries = 0; 2597 (function wait() { 2598 if (isVisible(input)) { 2599 input.focus(); 2600 history.replaceState(null, '', location.pathname + location.search); 2601 return; 2602 } 2603 if (tries++ < 30) requestAnimationFrame(wait); 2604 })(); 2605 } 2606 2607 // ------------------------------- 2608 // Open search + focus input 2609 // ------------------------------- 2610 function openAndFocus() { 2611 if (!isVisible(panel) && openBtn && typeof openBtn.click === "function") { 2612 openBtn.click(); 2613 } 2614 focusWhenVisible(); 2615 } 2616 2617 // ------------------------------- 2618 // Skip link behavior 2619 // ------------------------------- 2620 document.addEventListener('click', e => { 2621 const link = e.target.closest('a[href="#keywords"]'); 2622 if (link) { 2623 e.preventDefault(); 2624 openAndFocus(); 2625 } 2626 }); 2627 2628 window.addEventListener('hashchange', () => { 2629 if (location.hash === '#keywords') openAndFocus(); 2630 }); 2631 if (location.hash === '#keywords') openAndFocus(); 2632 2633 if (openBtn) { 2634 openBtn.addEventListener('click', () => { 2635 focusWhenVisible(); 2636 }); 2637 } 2638 2639 // ------------------------------- 2640 // When clicking the X close button â focus search icon 2641 // ------------------------------- 2642 if (closeBtn && openBtn) { 2643 closeBtn.addEventListener('click', () => { 2644 setTimeout(() => openBtn.focus(), 50); 2645 }); 2646 } 2647 2648 // ------------------------------- 2649 // *** ESCAPE KEY â FIXED & SCOPED *** 2650 // 2651 // Only do anything IF: 2652 // - The close button exists 2653 // - AND it is visible (meaning search overlay is actually open) 2654 // 2655 // Otherwise â ignore Escape completely. 2656 // ------------------------------- 2657 document.addEventListener('keydown', e => { 2658 if (e.key !== 'Escape') return; 2659 2660 // Only handle Escape if the search overlay is open 2661 if (closeBtn && isVisible(closeBtn)) { 2662 2663 // Trigger the same behavior as clicking X 2664 if (typeof closeBtn.click === 'function') { 2665 closeBtn.click(); 2666 } 2667 2668 // And return focus to search icon 2669 setTimeout(() => { 2670 if (openBtn && typeof openBtn.focus === 'function') { 2671 openBtn.focus(); 2672 } 2673 }, 50); 2674 } 2675 }); 2676 2677}); 2678</script>
2678 2679
2680<script> 2681// legacy accordion keyboard fix 2682document.addEventListener('DOMContentLoaded', function () { 2683 2684 // Remove Hammer accordion handlers if present 2685 if (window.jQuery) { 2686 $('.accordion').off('tap click'); 2687 $('.result').off('tap click'); 2688 $('.sidebar').off('tap click'); 2689 } 2690 2691 const accordions = document.querySelectorAll('.accordion'); 2692 let lock = false; 2693 2694 function toggleAccordion(acc) { 2695 if (lock) return; 2696 lock = true; 2697 2698 const isOpen = acc.classList.contains('open'); 2699 const icon = acc.querySelector('.icon'); 2700 2701 acc.classList.toggle('open', !isOpen); 2702 acc.setAttribute('aria-expanded', String(!isOpen)); 2703 2704 if (icon) { 2705 icon.classList.toggle('icon-minus', !isOpen); 2706 icon.classList.toggle('icon-plus', isOpen); 2707 } 2708 2709 setTimeout(() => { lock = false; }, 400); 2710 } 2711 2712 accordions.forEach(acc => { 2713 2714 // set initial aria state 2715 const isOpen = acc.classList.contains('open'); 2716 acc.setAttribute('aria-expanded', String(isOpen)); 2717 2718 // CLICK â only header or icon toggles 2719 acc.addEventListener('click', function (e) { 2720 if (e.target.closest('h2.heading') || e.target.closest('.icon')) { 2721 e.preventDefault(); 2722 toggleAccordion(acc); 2723 } 2724 }); 2725 2726 // KEYBOARD â only when accordion itself has focus 2727 acc.addEventListener('keydown', function (e) { 2728 2729 const isEnter = e.key === 'Enter'; 2730 const isSpace = (e.key === ' ' || e.code === 'Space'); 2731 2732 if (!isEnter && !isSpace) return; 2733 2734 // If focus is NOT the accordion itself, bail. 2735 // This prevents Enter on links/buttons from closing it. 2736 if (document.activeElement !== acc) return; 2737 2738 e.preventDefault(); 2739 toggleAccordion(acc); 2740 }); 2741 2742 }); 2743 2744}); 2745</script>
2745 2746
2747<script> 2748//PDF icon addition 2749document.addEventListener("DOMContentLoaded", function () { 2750 const pdfLinks = document.querySelectorAll('a[href$=".pdf"], a[href$=".PDF"]'); 2751 2752 pdfLinks.forEach(link => { 2753 2754 if (!link.hasAttribute("target")) { 2755 link.setAttribute("target", "_blank"); 2756 } 2757 2758 if (link.dataset.pdfIconAdded === "true") return; 2759 if (link.querySelector('.bi-filetype-pdf')) return; 2760 2761 const icon = document.createElement("i"); 2762 icon.className = "bi bi-filetype-pdf"; 2763 icon.setAttribute("aria-hidden", "true"); 2764 icon.style.marginLeft = "0.35rem"; 2765 2766 // Insert after last non-BR node 2767 let lastChild = link.lastChild; 2768 while (lastChild && lastChild.nodeName === "BR") { 2769 lastChild = lastChild.previousSibling; 2770 } 2771 2772 if (lastChild) { 2773 link.insertBefore(icon, lastChild.nextSibling); 2774 } else { 2775 link.appendChild(icon); 2776 } 2777 2778 // Mark as processed 2779 link.dataset.pdfIconAdded = "true"; 2780 }); 2781}); 2782</script>
2782 2783
2784<script> 2785//accordion url hashing 2786document.addEventListener("DOMContentLoaded", function () { 2787 if (!window.location.hash) return; 2788 2789 var target = document.querySelector(window.location.hash); 2790 if (!target || !target.classList.contains("accordion")) return; 2791 2792 target.classList.add("open"); 2793 2794 setTimeout(function () { 2795 var offset = 130; 2796 var top = target.getBoundingClientRect().top + window.pageYOffset - offset; 2797 2798 window.scrollTo({ 2799 top: top, 2800 behavior: "smooth" 2801 }); 2802 }, 250); 2803}); 2804</script>
2804 2805
2806<script defer src="/PreBuilt/js/emerg.js"></script>
2806
2807<script src="https://cdn.botpress.cloud/webchat/v2.2/inject.js"></script>
2807
2808<script src="https://files.bpcontent.cloud/2025/03/28/19/20250328192236-BN4AMXN4.js"></script>
2808 2809 2810 <!-- new javascript libraries --> 2811
2811<script type="text/javascript" src="js/jquery.js"></script>
2811 2812
2812<script type="text/javascript" src="js/vendors.min.js"></script>
2812 2813
2813<script type="text/javascript" src="js/main.js"></script>
2813 2814 2815<!--slate-->
2816<script async="async" src="https://admission.sru.edu/ping">/**/</script>
2816 2817 </body> 2818</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.