1 2 3 4<!DOCTYPE html> 5<html lang="en" class="has-js"> 6 <head> 7 8 9 10 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"> 14 <meta name="robots" content="index,follow"> 15 16<meta name="revisit-after" content="2"> 17<meta name="description" content="Health & Safety Training and Consultancy. Book your NEBOSH, IOSH, NVQ, CITB training course via classroom, online or in-house learning." /> 18<meta name="author" content="" /> 19<title>Welcome | Phoenix Health & Safety</title> 20 21<meta property="og:title" content="Welcome | Phoenix Health & Safety" /> 22<meta property="og:description" content="Health & Safety Training and Consultancy. Book your NEBOSH, IOSH, NVQ, CITB training course via classroom, online or in-house learning." /> 23<meta property="og:type" content="website" /> 24<meta property="og:url" content="https://www.phoenixhsc.co.uk/login/" /> 25 26 27<link rel="canonical" href="https://www.phoenixhsc.co.uk/login/" /> 28 29<link rel="icon" type="image/png" sizes="96x96" href="/dist/fav/phoenix/favicon-96x96.png" /> 30<link rel="icon" type="image/svg+xml" href="/dist/fav/phoenix/favicon.svg" /> 31<link rel="shortcut icon" href="/dist/fav/phoenix/favicon.ico" /> 32<link rel="apple-touch-icon" sizes="180x180" href="/dist/fav/phoenix/apple-touch-icon.png" /> 33<meta name="apple-mobile-web-app-title" content="phoenix" /> 34<link rel="manifest" href="/dist/fav/phoenix/site.webmanifest" /> 35 36 37 <meta property="og:image" content="https://www.phoenixhsc.co.uk/media/vczbwz2w/phoenix-share.jpg" /> 38 39 40 41 42<!-- TrustBox script -->
43<script type="text/javascript" src="//widget.trustpilot.com/bootstrap/v5/tp.widget.bootstrap.min.js" async></script>
43 44<!-- End TrustBox script --><!-- Google Tag Manager WILMINGTON -->
45<script>
vendor: 327 bytes, lines 45-49
45(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 46new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 47j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 48'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 49})(window,document,'script','dataLayer','
49GTM-PLMVK2PR
vendor: 3 bytes, line 49
49');
49</script>
49 50<!-- End Google Tag Manager --> 51 52<!-- Google Tag Manager BRAND -->
53<script>
vendor: 327 bytes, lines 53-57
53(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 54new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 55j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 56'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 57})(window,document,'script','dataLayer','
57GTM-K8MBP74
vendor: 3 bytes, line 57
57');
57</script>
57 58<!-- End Google Tag Manager --> 59 60
60<script defer src="/dist/main.0ba3c627a67071207dd4.js"></script>
60<script defer src="/dist/phoenix.a326ed7f92f4e57df83c.js"></script>
60<link rel="stylesheet" href="/dist/phoenix.b581372478641c7900ca.css"> 61 62 <style> 63 @media (max-width: 1199.98px) { 64 header.siteheader .topbar nav { 65 transform: translate3d(100%,0,0); 66 position: fixed; 67 right: 0; 68 top: clamp(112px, 9vw, 140px); 69 } 70 } 71 </style> 72 73
73<script>let url="/umbraco/engage/pagedata/ping",pageviewId="4e1b82cc447141ec90317d4036cd2d9e";if("function"==typeof navigator.sendBeacon&&"function"==typeof Blob){let e=new Blob([pageviewId],{type:"text/plain"});navigator.sendBeacon(url,e)}else{let a=new XMLHttpRequest;a.open("POST",url,1),a.setRequestHeader("Content-Type","text/plain"),a.send(pageviewId)}</script>
73</head> 74 <body> 75 76<!-- Google Tag Manager (noscript) WILMINGTON -->
vendor: 68 bytes, lines 76-77
76 77<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
77GTM-PLMVK2PR
vendor: 83 bytes, lines 77-78
77" 78height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
79<!-- End Google Tag Manager (noscript) --> 80 81<!-- Google Tag Manager (noscript) BRAND -->
vendor: 68 bytes, lines 81-82
81 82<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
82GTM-K8MBP74
vendor: 83 bytes, lines 82-83
82" 83height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
84<!-- End Google Tag Manager (noscript) --> 85 86 87 88<div class="skiplinks" aria-label="Skip links" role="region"> 89 <a tabindex="1" href="#skiplink-content">Skip to content</a> 90 <a tabindex="2" href="#skiplink-menu">Skip to menu</a> 91 <a tabindex="3" href="#skiplink-footer">Skip to footer</a> 92</div> 93 94<div class="notice-bar"> 95 96</div> 97 98<header class="siteheader"> 99 100 <input class="hidden" type="checkbox" name="toggle_menu" id="toggle_menu" tabindex="-1"> 101 <input class="hidden" type="checkbox" name="toggle_search" id="toggle_search" tabindex="-1"> 102 <div class="topbar"> 103 <div class="topline"> 104 <a href="/" id="header-logo" class="logo has-small-logo" tabindex="4"> 105 <img src="/media/5rwhs15p/phoenix-mobile-logo.svg" class="small-screen-site-logo full-image" alt="Phoenix Health and Safety" /> 106 107 <img src="/media/qj4nujqu/phoenixhsc-logo.svg" class="main-site-logo full-image" alt="Phoenix Health and Safety" /> 108 </a> 109 <div class="right"> 110 <label for="toggle_search" tabindex="6"> 111 <span></span> 112 Search 113 </label> 114 115 <a href="/login/" target="_blank" tabindex="7" class="login"> 116 <span></span> 117 Login 118 </a> 119 120 <a href="https://checkout.phoenixhsc.co.uk" rel="nofollow" target="_self" tabindex="8" class="cart"> 121 <span class="cart-icon"></span> 122 <span class="cart-active hidden"></span> 123 Cart 124 </a> 125 <!-- only display on mobile devices--> 126 <label for="toggle_menu" tabindex="9"> 127 <div class="hamburger"> 128 <span class="hamburger-box"> 129 <span class="hamburger-inner"></span> 130 </span> 131 </div> 132 Menu 133 </label> 134 </div> 135 </div> 136 137 <div class="searchblock"> 138 <div class="container"> 139 <div class="col-12"> 140 <label class="close" for="toggle_search">Close</label> 141 142 143<form action="/search-results/" name="b165ea31-f239-47be-b0f7-bbe7d2036c62" method="GET" autocomplete="off" data-id="20618" class="form-horizontal form-contextualsearch"> 144 <input type="text" placeholder="Type here to search the site..." name="criteria" id="746c7bc7-12c9-48bf-8944-1a3025bc5589" class="search-input" /> 145 <button type="submit">Search</button> 146 <ul class="contextual-search-results-list hidden"></ul> 147</form> 148 </div> 149 </div> 150 </div> 151 152 153<nav class="cc-primary-nav" id="skiplink-menu"> 154 <div> 155 <a class="block button navigation-link-button" 156 href="/quick-course-finder/" 157 158 >Quick Course Finder 159 </a> 160 <ul class="primary"> 161 <li> 162 <a href="/quick-course-finder/" >Quick Course Finder</a> 163 </li> 164 <li> 165 <a class="children " href="/training/">Training <span></span></a> 166 <ul> 167 <li> 168 <a href="/training/nebosh-courses/">NEBOSH Courses</a> 169 </li> 170 <li> 171 <a href="/training/nebosh-exams/">NEBOSH Exams</a> 172 </li> 173 <li> 174 <a href="/training/iosh-courses/">IOSH Courses</a> 175 </li> 176 <li> 177 <a href="/training/isep-courses/">ISEP Courses</a> 178 </li> 179 <li> 180 <a href="/training/nvq/">NVQ</a> 181 </li> 182 <li> 183 <a href="/training/iso-courses/">ISO Courses</a> 184 </li> 185 <li> 186 <a href="/training/first-aid-courses/">First Aid Courses</a> 187 </li> 188 <li> 189 <a href="/training/construction-courses/">Construction Courses</a> 190 </li> 191 <li> 192 <a href="/training/rtitb-courses/">RTITB Courses</a> 193 </li> 194 <li> 195 <a href="/training/short-health-safety-courses/">Short Health & Safety Courses</a> 196 </li> 197 </ul> 198 </li> 199 <li> 200 <a class="children " href="/ways-to-learn/">Ways to Learn <span></span></a> 201 <ul> 202 <li> 203 <a href="/ways-to-learn/online-health-safety-courses/">Online Health & Safety Courses</a> 204 </li> 205 <li> 206 <a href="/ways-to-learn/virtual-classroom-health-safety-courses/">Virtual Classroom Health & Safety Courses</a> 207 </li> 208 <li> 209 <a href="/ways-to-learn/classroom-health-safety-courses/">Classroom Health & Safety Courses</a> 210 </li> 211 <li> 212 <a href="/ways-to-learn/in-house-health-safety-courses/">In-house Health & Safety Courses</a> 213 </li> 214 <li> 215 <a href="/ways-to-learn/distance-learning-health-safety-courses/">Distance Learning Health & Safety Courses</a> 216 </li> 217 </ul> 218 </li> 219 <li> 220 <a class="children " href="/business-solutions/">Business Solutions <span></span></a> 221 <ul> 222 <li> 223 <a href="/business-solutions/consultancy/">Consultancy</a> 224 </li> 225 <li> 226 <a href="/business-solutions/health-safety-audits/">Health & Safety Audits</a> 227 </li> 228 <li> 229 <a href="/business-solutions/risk-assessment/">Risk Assessment</a> 230 </li> 231 <li> 232 <a href="/business-solutions/inspections/">Inspections</a> 233 </li> 234 <li> 235 <a href="/business-solutions/support-packages/">Support Packages</a> 236 </li> 237 <li> 238 <a href="/business-solutions/policies/">Policies</a> 239 </li> 240 <li> 241 <a href="/business-solutions/in-company-courses/">In Company Courses</a> 242 </li> 243 </ul> 244 </li> 245 <li> 246 <a href="/training-venues/" >Training Venues</a> 247 </li> 248 <li> 249 <a href="/contact-us/" >Contact Us</a> 250 </li> 251 </ul> 252 253 <ul class="inline dark social"> 254 <li><a class="facebook" href="https://www.facebook.com/PhoenixHSC/" target="_blank" rel="noopener">Facebook</a></li> 255 <li><a class="instagram" href="https://www.instagram.com/phoenixhsc/?hl=en" target="_blank" rel="noopener">Instagram</a></li> 256 <li><a class="linkedin" href="https://www.linkedin.com/company/phoenix-hsc" target="_blank" rel="noopener">LinkedIn</a></li> 257 <li><a class="youtube" href="https://www.youtube.com/c/PhoenixhscCoUk" target="_blank" rel="noopener">YouTube</a></li> 258 </ul> 259 260 <label for="toggle_menu" tabindex="0" class="navigation-capture">Close menu (tabbing again will automatically close this menu)</label> 261 </div> 262</nav> 263 264 265 </div> 266 267 268 <nav aria-label="Breadcrumb" class="breadcrumb content-block"> 269 <ol itemscope itemtype="http://schema.org/BreadcrumbList"> 270 <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"> 271 <a href="/" itemprop="item" class="mr-2 "><span itemprop="name">Home</span></a>| 272 <meta itemprop="position" content="1" /> 273 </li> 274 <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"> 275 <a href="/login/" itemprop="item" class="mr-2 current-page"><span itemprop="name">Login</span></a> 276 <meta itemprop="position" content="2" /> 277 </li> 278 </ol> 279 </nav> 280 281 282 283</header>
284 <main role="main" id="skiplink-content" class="has-breadcrumb"> 285 286 287 288<div class="header-image thin bg-white with-divider bg-left-1 bg-right-1"> 289 <div class="content"> 290 <div class="dividers"> 291 <h1>Login</h1> 292 <p class="t-s-24 t-w-500">Access your purchases and training courses. </p> 293 </div> 294 </div> 295 296 <img src="/media/mjykqsim/short-health-safety-courses_axxahu.webp" alt="" /> 297 298</div> 299 300 301 302 303 304 305<section class="grid two-column md:gap-2 bg-white "> 306 307<div class="container"> 308 309 310<div class="col-6"> 311 312 313 314 315 316<div 317 class="item content-block radius-2 bg-grey-mid" 318 > 319 <div class="content flex "> 320 321 322<h2 class="divider t-c-blue-dark-mid t-s-36 t-a-left ">Customer Login</h2> 323<p>To checkout, review your recent purchases or download course material for your delegates, login here:</p> 324 325 326 327 328 329<div class="button-wrapper align-left"> 330 <a class="block button" 331 href="https://checkout.phoenixhsc.co.uk/login" 332 target="_blank" rel="noopener"> 333 Account Login 334 </a> 335</div> 336 </div> 337</div> 338</div> 339 340<div class="col-6"> 341 342 343 344 345 346<div 347 class="item content-block radius-2 bg-blue-dark-mid" 348 > 349 <div class="content flex "> 350 351 352<h2 class="divider t-c-white t-s-36 t-a-left ">Student e-Learning login</h2> 353<p>If you are booked on an e-learning course or any course with online training, click below to login.</p> 354 355 356 357 358 359<div class="button-wrapper align-left"> 360 <a class="block button" 361 href="https://my.phoenixhsc.co.uk/" 362 target="_blank" rel="noopener"> 363 E-learning Platform 364 </a> 365</div> 366 </div> 367</div> 368</div> 369</div> 370 371</section> 372 373<section class="grid one-column bg-white no-top"> 374 375<div class="container"> 376 377 378<div class="col-12"> 379 380 381 382 383 384<div 385 class="item content-block radius-2 " 386 > 387 <div class="content flex "> 388 389 390 391 392 393 394 395<section class="grid one-column bg-white"> 396 397<div class="container"> 398 399 400<div class="col-12"> 401 402 403 404 405 406<div 407 class="item content-block radius-2 " 408 > 409 <div class="content flex "> 410 411 412 413 <div> 414 <!-- TrustBox widget - Mini --> 415<div class="trustpilot-widget" data-locale="en-US" data-template-id="53aa8807dec7e10d38f59f32" data-businessunit-id="4becf33200006400050b69bf" data-style-height="150px" data-style-width="100%" data-token="4c451698-25cb-4bd7-bfb7-dd81d14b6dd0"> 416 <a href="https://www.trustpilot.com/review/www.phoenixhsc.co.uk" target="_blank" rel="noopener">Trustpilot</a> 417</div> 418<!-- End TrustBox widget --> 419 420<style> 421.sponsor-logo-block { 422 display: flex; 423 justify-content: center; 424 align-items: center; 425 flex-wrap: wrap; 426 margin-top: 2rem; 427} 428img.sponsor-logo { 429 margin: 1rem 1.5rem; 430} 431</style> 432 </div> 433 434 435<p style="text-align: center;">A selection of some of the great companies we work with</p> 436<p class="sponsor-logo-block"><img class="sponsor-logo" src="/media/ehbj5nif/schneider-logo-1602159224cs7yr_i8wfse_q4lx0u.webp" alt="Schneider"><img class="sponsor-logo" src="/media/ulghhvo2/quadriga-logo-1602159226putca_wm3kw3_abqdgz.webp" alt="Quadriga"><img class="sponsor-logo" src="/media/x42pymh3/gilbertson-logo-1602159232xufqz_wosglq_hbpuyx.webp" alt="Gilberson"><img class="sponsor-logo" src="/media/lode2wun/niceic-logo-1602159227o0fjt_n3nmji_y2g9rc.webp" alt="Niceic"></p> 437 </div> 438</div> 439</div> 440</div> 441 442</section> 443 444 </div> 445</div> 446</div> 447</div> 448 449</section> 450 451 452 453 </main> 454 <footer class="sitefooter bg-grey-dark" id="skiplink-footer"> 455 456 457 458 <div class="footer-doormat-nav"> 459 460 461 462 463 464<section class="grid four-column"> 465 466<div class="container"> 467 468 469<div class="col-3"> 470 471 472 473 474 475<div 476 class="item " 477 > 478 <div class="content flex "> 479 480 481 482 <ul class="doormat-link-block"> 483 <li class="heading">About us</li> 484 <li><a href="/about-us/">About Phoenix</a></li> 485 <li><a href="/insight/">Blogs & Insights</a></li> 486 <li><a href="/about-us/phoenix-pass-pledge/">Our Pass Pledge</a></li> 487 <li><a href="/about-us/vacancies/">Vacancies</a></li> 488 <li><a href="/faq/">FAQs</a></li> 489 <li><a href="/contact-us/">Contact Us</a></li> 490 </ul> 491 492<p class="t-s-20"> </p> 493<p class="t-s-20"><strong>Got a question?</strong></p> 494<p><strong>Call us on:</strong> <a rel="noopener noreferrer" href="tel:03455008811">0345 500 8811</a><br><strong>WhatsApp:</strong> <a rel="nofollow noopener" href="https://wa.me/441543657637" target="_blank">+44 1543 657637</a><br><strong>Email us:</strong> <a rel="noopener noreferrer" href="mailto:[email protected]">[email protected]</a></p> 495<p>Send us your enquiry using our<strong> <a href="/contact-us">contact form</a></strong></p> 496 </div> 497</div> 498</div> 499 500<div class="col-3"> 501 502 503 504 505 506<div 507 class="item "
508 > 509 <div class="content flex "> 510 511 512 513 <ul class="doormat-link-block"> 514 <li class="heading">Courses</li> 515 <li><a href="/training/nebosh-courses/">NEBOSH Courses</a></li> 516 <li><a href="/training/iosh-courses/">IOSH Courses</a></li> 517 <li><a href="/training/isep-courses/">ISEP Courses</a></li> 518 <li><a href="/training/nvq/">NVQ Courses</a></li> 519 <li><a href="/training/proqual-courses/">ProQual Courses</a></li> 520 <li><a href="/training/iso-courses/">ISO Courses</a></li> 521 <li><a href="/training/construction-courses/">Construction Courses</a></li> 522 <li><a href="/training/first-aid-courses/">First Aid Courses</a></li> 523 <li><a href="/training/rtitb-courses/">RTITB Courses</a></li> 524 <li><a href="/training/bohs-courses/">BOHS Courses</a></li> 525 <li><a href="/ways-to-learn/in-house-health-safety-courses/">In-house</a></li> 526 <li><a href="/ways-to-learn/online-health-safety-courses/">E-Learning</a></li> 527 <li><a href="/ways-to-learn/distance-learning-health-safety-courses/">Distance Learning</a></li> 528 <li><a href="/training/short-health-safety-courses/">Short Courses</a></li> 529 </ul> 530 531 </div> 532</div> 533</div> 534 535<div class="col-3"> 536 537 538 539 540 541<div 542 class="item " 543 > 544 <div class="content flex "> 545 546 547 548 <ul class="doormat-link-block"> 549 <li class="heading">Popular Courses</li> 550 <li><a href="/courses/nebosh-national-general-certificate/">NEBOSH General Certificate</a></li> 551 <li><a href="/courses/iosh-managing-safely/">IOSH Managing Safely</a></li> 552 <li><a href="/courses/nebosh-national-diploma/">NEBOSH National Diploma</a></li> 553 <li><a href="/courses/nebosh-construction-health-safety-certificate/">NEBOSH Construction Certificate</a></li> 554 <li><a href="/courses/nebosh-certificate-in-fire-safety/">NEBOSH Certificate in Fire Safety</a></li> 555 </ul> 556 557 </div> 558</div> 559</div> 560 561<div class="col-3"> 562 563 564 565 566 567<div 568 class="item " 569 > 570 <div class="content flex "> 571 572 573 574 <ul class="doormat-link-block"> 575 <li class="heading">Business Solutions</li> 576 <li><a href="/business-solutions/consultancy/">Consultancy</a></li> 577 <li><a href="/business-solutions/in-company-courses/">In-Company Training</a></li> 578 <li><a href="/business-solutions/support-packages/">Health and Safety Support Packages</a></li> 579 <li><a href="/business-solutions/health-safety-audits/">Health and Safety Auditing</a></li> 580 <li><a href="/business-solutions/risk-assessment/">Health and Safety Risk Assessments</a></li> 581 <li><a href="/business-solutions/inspections/">Health and Safety Inspections</a></li> 582 <li><a href="/business-solutions/policies/">Health and Safety Policies</a></li> 583 </ul> 584 585 </div> 586</div> 587</div> 588</div> 589 590</section> 591<section class="grid one-column"> 592 593<div class="container"> 594 595 596<div class="col-12"> 597 598 599 600 601 602<div 603 class="item " 604 > 605 <div class="content flex "> 606 607 608 609<p><img class="footer-card-logo" src="/media/etsnulob/card-icon-amex_uvqseq.webp" alt="American Express"><img class="footer-card-logo" src="/media/ff5hopbv/card-icon-mastercard_nt7pgn.webp" alt="Mastercard"><img class="footer-card-logo" src="/media/3qbmphae/card-icon-maestro_huiw9n.webp" alt="Maestro"><img class="footer-card-logo" src="/media/omvkdjuj/card-icon-visa_mrvf3w.webp" alt="VISA"><img class="footer-card-logo" src="/media/fcwprkf3/card-icon-visa-electron_jvxh0u.webp" alt="VISA Electron"><img class="footer-card-logo" src="/media/3z1pjuzn/klarna_logo_etmjcb.webp" alt="Klarna"></p> 610 </div> 611</div> 612</div> 613</div> 614 615</section> 616 617 </div> 618 619<div class="flex-container align-center"> 620 <div class="col-12 md:pb-0"> 621 <div class="item"> 622 <ul class="inline justify-center md:justify-right al
622ign-center association"> 623 <li class="md:pl-2"> 624 625 <a href="https://#" 626 target="_blank" rel="noopener" 627 > 628 <img data-src="/media/frhds11y/nqa_iso14001_bw.jpg?v=1dd3ad700b8beb0" data-srcset="/media/frhds11y/nqa_iso14001_bw.jpg?width=180&height=270&quality=70&v=1dd3ad700b8beb0 180w" data-sizes="auto" class="full-image lazyload" alt="ISO 14001 Environmental Management" width="180" height="270" /> 629 </a> 630 </li> 631 <li class="md:pl-2"> 632 633 <a href="https://wilmingtonplc.com/" 634 target="_blank" rel="noopener" 635 > 636 <img data-src="/media/wqviyf20/wilmington_plc_logo_white-1.png?v=1dd3ad6fe5e05d0" data-srcset="/media/wqviyf20/wilmington_plc_logo_white-1.png?width=180&height=51&quality=70&v=1dd3ad6fe5e05d0 180w" data-sizes="auto" class="full-image lazyload" alt="Wilmington PLC" width="180" height="51" /> 637 </a> 638 </li> 639 </ul> 640 </div> 641 </div> 642</div> 643 644<div class="flex-container align-center"> 645 <nav class="col-12 md:col-8"> 646 <div class="item"> 647 <ul class="inline justify-center md:justify-left"> 648 649 <li> 650 <a href="/site-terms-and-conditions/" 651 652 >Terms & Conditions</a> 653 </li> 654 <li> 655 <a href="/privacy-notice/" 656 657 >Privacy Notice</a> 658 </li> 659 <li> 660 <a href="/copyright-notice/" 661 662 >Copyright Notice</a> 663 </li> 664 <li> 665 <a href="/cookie-policy/" 666 667 >Cookie Policy</a> 668 </li> 669 <li> 670 <a href="/accessibility-statement/" 671 672 >Accessibility Statement</a> 673 </li> 674 </ul> 675 <p class="copyright-text">© Phoenix HSC (UK) Ltd | Company No. 06534364 | Registered office: Wilmington plc, Suite 215/216 Fort Dunlop, 2nd Floor, Fort Parkway, Birmingham, B24 9FD</p> 676 </div> 677 </nav> 678 <div class="col-12 md:col-4"> 679 <div class="item"> 680 <ul class="inline justify-center md:justify-right social"> 681 <li><a class="facebook" href="https://www.facebook.com/PhoenixHSC/" target="_blank" rel="noopener">Facebook</a></li> 682 <li><a class="instagram" href="https://www.instagram.com/phoenixhsc/?hl=en" target="_blank" rel="noopener">Instagram</a></li> 683 <li><a class="linkedin" href="https://www.linkedin.com/company/phoenix-hsc" target="_blank" rel="noopener">LinkedIn</a></li> 684 <li><a class="youtube" href="https://www.youtube.com/c/PhoenixhscCoUk" target="_blank" rel="noopener">YouTube</a></li> 685 </ul> 686 </div> 687 </div> 688</div> 689 </footer> 690 691 692<div class="basket-modal-overlay hidden"> 693 <div class="basket-modal" aria-modal="true" role="dialog" tabindex="0"> 694 <div class="container bg-white radius-2 p-3"> 695 <div class="col-12"> 696 <div class="status-text t-c-pink-mid t-s-24">Adding to basket...</div> 697 <div class="success-div hidden"> 698 <h3 class="course-modal-name t-c-pink-mid t-s-24">Product successfully added to cart</h3> 699 <form> 700 <button class="modal-continue block button md:mr-1">Continue</button> 701 <a href="https://checkout.phoenixhsc.co.uk" class="modal-goto-cart block button md:ml-1">Go to cart</a> 702 </form> 703 </div> 704 <div class="error-div hidden"> 705 <button class="error-close block button">Continue</button> 706 </div> 707 </div> 708 </div> 709 </div> 710</div> 711 712 713 <div class="modal-overlay hidden"> 714 <div class="tutor-modal" aria-modal="true" role="dialog" tabindex="0"> 715 <div class="container bg-white radius-2"> 716 <a href="#" data-id="" class="close">Close</a> 717 <div class="col-12 sm:col-6 md:col-3 tutor-modal-img"></div> 718 <div class="col-12 md:col-9 tutor-modal-descriptor"> 719 <h3 class="tutor-modal-name t-s-36"></h3> 720 <h4 class="tutor-modal-job-title t-s-26"></h4> 721 <div class="tutor-modal-bio"></div> 722 </div> 723 </div> 724 </div> 725</div> 726 727 728
728<script> 729 window.ak = '2AIR6T2TtoFH3M8BTik5rnZmiTCSkHPR6rrexU2TYWRKtZaikWm38gSoQz6OvJd8'; 730 window.node = 20618; 731 window.culture = 'en-GB'; 732 </script>
732 733 734 735 736 737 738 739
739<script src="/App_Plugins/UmbracoForms/Assets/promise-polyfill/dist/polyfill.min.js?v=13.9.11" type="application/javascript"></script>
739<script src="/App_Plugins/UmbracoForms/Assets/aspnet-client-validation/dist/aspnet-validation.min.js?v=13.9.11" type="application/javascript"></script>
739 740 741 742<style> 743html { 744 scroll-behavior: smooth; 745} 746.bg-grey-mid, .hover\:bg-grey-mid:active, .hover\:bg-grey-mid:focus, .hover\:bg-grey-mid:hover { 747 background-color: #e9ecef; 748 color: unset; 749} 750.discover { 751 display: none; 752} 753.radius-2, .blocklink, form:not(.mktoForm) button.block, .single-product-block .price { 754 border-radius: 0.1rem; 755} 756.blocklink:hover { 757 box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px; 758} 759a.block { 760border-radius: 0.1rem !important; 761} 762form.form-contextualsearch { 763border-radius: 0.1rem !important; 764} 765 766img.footer-card-logo { 767 display: inline-flex; 768 float: right; 769 padding-left: 4px; 770 padding-bottom: 4px; 771 height: 40px; 772 width: auto; 773} 774.header-image.thin.bg-white.with-divider.bg-left-1.bg-right-1 img { 775 filter: brightness(0.5); 776} 777.header-image.thin p { 778 color: #ffffff; 779} 780.header-image h1 { 781 margin-top: 5rem; 782margin-bottom: 2.5rem; 783} 784.bg-white a.arrow { 785filter: unset !important; 786-webkit-filter: unset !important; 787 margin-top: 0rem !important; 788 margin-bottom: 1.5rem; 789} 790a.arrow:after { 791width: 1rem !important; 792right: 24px !important; 793} 794.tick-box-sale { 795 display: flex; 796 flex-direction: row; 797 align-items: flex-start; 798} 799img.tick-image { 800 margin-right: 1rem; 801 margin-top: -1px; 802} 803.tick-box-content strong { 804 font-size: 1.2rem; 805} 806.tick-box-content { 807 margin-right: 2rem; 808} 809section.bg-gray-dark-mid { 810 background: #353a40; 811} 812table td { 813 background-color: unset; 814} 815.enrol-desc { 816 text-align: left; 817} 818.header-image p.t-s-24.t-w-500 { 819 color: #ffffff; 820} 821.insight time { 822 margin-top: 4rem; 823} 824@media (min-width: 800px) { 825 .enrolment-block .event-variant { 826 grid-template-columns: 0.05fr 2.7fr 100px 160px !important; 827 } 828} 829</style> 830
831<script> 832const continueBtn = document.querySelector('.modal-continue'); 833 834if (continueBtn) { 835 continueBtn.textContent = 'Continue shopping'; 836} 837</script>
837<script> 838(function () { 839 function isBST(date) { 840 var year = date.getFullYear(); 841 842 var march = new Date(year, 2, 31); 843 var lastSundayMarch = new Date(year, 2, march.getDate() - march.getDay()); 844 845 var october = new Date(year, 9, 31); 846 var lastSundayOctober = new Date(year, 9, october.getDate() - october.getDay()); 847 848 return date >= lastSundayMarch && date < lastSundayOctober; 849 } 850 851 function pad(num) { 852 return num < 10 ? "0" + num : "" + num; 853 } 854 855 function createDateTime(d, m, y, hour, minute) { 856 return new Date( 857 parseInt(y, 10), 858 parseInt(m, 10) - 1, 859 parseInt(d, 10), 860 parseInt(hour, 10), 861 parseInt(minute, 10) 862 ); 863 } 864 865 function formatDate(date) { 866 return pad(date.getDate()) + "/" + pad(date.getMonth() + 1) + "/" + date.getFullYear(); 867 } 868 869 function formatTime(date) { 870 return pad(date.getHours()) + ":" + pad(date.getMinutes()); 871 } 872 873 function addOneHour(date) { 874 return new Date(date.getTime() + 60 * 60 * 1000); 875 } 876 877 function adjustTimes(node) { 878 if (!node || !node.classList || !node.classList.contains("enrol-desc")) return; 879 if (node.getAttribute("data-bst-adjusted") === "true") return; 880 881 var html = node.innerHTML; 882 883 // Format A: dd/mm/yyyy ... (hh:mm-hh:mm) 884 var formatA = 885 /(\d{2})\/(\d{2})\/(\d{4}).*?\((\d{2}):(\d{2})-(\d{2}):(\d{2})\)/; 886 887 // Format B: dd/mm/yyyy hh:mm - dd/mm/yyyy hh:mm 888 var formatB = 889 /(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2})\s*-\s*(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2})/; 890 891 var matchA = html.match(formatA); 892 893 if (matchA) { 894 var baseDate = new Date( 895 parseInt(matchA[3], 10), 896 parseInt(matchA[2], 10) - 1, 897 parseInt(matchA[1], 10) 898 ); 899 900 if (isBST(baseDate)) { 901 var startDateTime = createDateTime(matchA[1], matchA[2], matchA[3], matchA[4], matchA[5]); 902 var endDateTime = createDateTime(matchA[1], matchA[2], matchA[3], matchA[6], matchA[7]); 903 904 var newStartDateTime = addOneHour(startDateTime); 905 var newEndDateTime = addOneHour(endDateTime); 906 907 var originalDate = matchA[1] + "/" + matchA[2] + "/" + matchA[3]; 908 var newDate = formatDate(newStartDateTime); 909 910 var oldSegment = matchA[0]; 911 var newSegment = oldSegment 912 .replace(originalDate, newDate) 913 .replace( 914 "(" + matchA[4] + ":" + matchA[5] + "-" + matchA[6] + ":" + matchA[7] + ")", 915 "(" + formatTime(newStartDateTime) + "-" + formatTime(newEndDateTime) + ")" 916 ); 917 918 node.innerHTML = html.replace(oldSegment, newSegment); 919 node.setAttribute("data-bst-adjusted", "true"); 920 return; 921 } 922 } 923 924 var matchB = html.match(formatB); 925 926 if (matchB) { 927 var startDateTime = createDateTime(matchB[1], matchB[2], matchB[3], matchB[4], matchB[5]); 928 var endDateTime = createDateTime(matchB[6], matchB[7], matchB[8], matchB[9], matchB[10]); 929 930 var changed = false; 931 932 if (isBST(startDateTime)) { 933 startDateTime = addOneHour(startDateTime); 934 changed = true; 935 } 936 937 if (isBST(endDateTime)) { 938 endDateTime = addOneHour(endDateTime); 939 changed = true; 940 } 941 942 if (changed) { 943 var newStr = 944 formatDate(startDateTime) + " " + formatTime(startDateTime) + 945 " - " + 946 formatDate(endDateTime) + " " + formatTime(endDateTime); 947 948 node.innerHTML = html.replace(matchB[0], newStr); 949 node.setAttribute("data-bst-adjusted", "true"); 950 } 951 } 952 } 953 954 // Initial run 955 var nodes = document.querySelectorAll(".enrol-desc"); 956 for (var i = 0; i < nodes.length; i++) { 957 adjustTimes(nodes[i]); 958 } 959 960 // MutationObserver for dynamic updates 961 var observer = new MutationObserver(function (mutations) { 962 for (var m = 0; m < mutations.length; m++) { 963 var mutation = mutations[m]; 964 965 for (var n = 0; n < mutation.addedNodes.length; n++) { 966 var node = mutation.addedNodes[n]; 967 968 if (node.nodeType === 1) { 969 if (node.classList && node.classList.contains("enrol-desc")) { 970 adjustTimes(node); 971 } else if (node.querySelectorAll) { 972 var found = node.querySelectorAll(".enrol-desc"); 973 for (var f = 0; f < found.length; f++) { 974 adjustTimes(found[f]); 975 } 976 } 977 } 978 } 979 } 980 }); 981 982 observer.observe(document.body, { childList: true, subtree: true }); 983})(); 984</script>
984<style> 985 .mktoForm { 986 margin: 5%; 987 width: unset !important; 988 } 989 .mktoFormRow { 990 display: flex; 991 flex-direction: column; 992 } 993 .mktoFieldWrap { 994 display: flex; 995 flex-direction: column; 996 align-content: flex-start; 997 } 998 .mktoForm label.mktoLabel { 999 margin-bottom: 0.8rem !important; 1000 font-weight: bold !important; 1001 color: #1a1a1a !important; 1002 width: 100% !important; 1003 } 1004 .mktoButtonRow { 1005 display: flex !important; 1006 justify-content: center; 1007 } 1008 .mktoForm .mktoButtonWrap { 1009 margin-left: 0 !important; 1010 width: 100% !important; 1011 } 1012 button.mktoButton { 1013 width: 100%; 1014 background-image: unset !important; 1015 } 1016 .mktoForm .mktoButtonWrap button { 1017 background-color: #066cff !important; 1018 } 1019 .mktoForm .mktoButtonWrap button:hover { 1020 background-color: #16174f !important; 1021 } 1022 input.mktoField { 1023 width: 100% !important; 1024 padding-left: 24px !important; 1025 } 1026 .mktoForm textarea.mktoField { 1027 width: 100% !important; 1028 padding-left: 24px !important; 1029 } 1030 span.mktoButtonWrap.mktoSimple { 1031 width: 100%; 1032 display: inline-flex; 1033 } 1034 .mktoForm input[type=text], .mktoForm input[type=url], .mktoForm input[type=email], .mktoForm input[type=tel], .mktoForm input[type=number], .mktoForm input[type=date], .mktoForm select.mktoField, .mktoForm textarea.mktoField { 1035 border: 1px solid #ddd !important; 1036 } 1037 .mktoRadioList > label, .mktoForm .mktoCheckboxList > label { 1038 display: inline-flex; 1039 align-items: center; 1040 } 1041 .mktoForm input[type=checkbox], /*.mktoForm input[type=radio]*/ { 1042 height: 0px !important; 1043 } 1044 .mktoForm .mktoButtonWrap.mktoRound .mktoButton { 1045 background-color: #be348a !important; 1046 background-image: unset !important; 1047 background-image: unset !important; 1048 background-image: unset !important; 1049 background-image: unset !important; 1050 } 1051 .mktoForm .mktoButtonWrap.mktoRound .mktoButton:hover { 1052 background-color: #8d044e !important; 1053 box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px !important; 1054 } 1055 .mktoErrorArrowWrap { 1056 display: none; 1057 } 1058 .mktoError { 1059 right: unset !important; 1060 bottom: unset !important; 1061 position: unset !important; 1062 } 1063 .mktoForm .mktoError .mktoErrorMsg { 1064 max-width: 100% !important; 1065 background-image: unset !important; 1066 box-shadow: unset !important; 1067 text-shadow: unset !important; 1068 } 1069 input.mktoField.mktoInvalid { 1070 border: 2px solid #FF6868 !important; 1071 } 1072 .mktoForm input[type=text]:focus, .mktoForm input[type=url]:focus, .mktoForm input[type=email]:focus, .mktoForm input[type=tel]:focus, .mktoForm input[type=number]:focus, .mktoForm input[type=date]:focus, .mktoForm select.mktoField:focus, .mktoForm textarea.mktoField:focus { 1073 border: 2px solid #888 !important; 1074 } 1075.mktoHtmlText { 1076 font-size: 0.8rem !important; 1077 line-height: 1.5 !important; 1078 width: 100% !important; 1079} 1080.mktoCaptchaDisclaimer { 1081 font-size: 0.8rem !important; 1082 line-height: 1.5 !important; 1083 margin-bottom: 1rem !important; 1084} 1085.mktoForm select.mktoField { 1086 -webkit-border-radius: 8px !important; 1087 -moz-border-radius: 8px !important; 1088 border-radius: 8px !important; 1089width: 100% !important; 1090} 1091input[type="checkbox"] { 1092 float: unset !important; 1093 appearance: none !important; 1094 -webkit-appearance: none; 1095 padding: 14px !important; 1096 border-radius: 4px; 1097 margin-right: 8px; 1098 position: relative; 1099 cursor: pointer; 1100} 1101input[type="checkbox"]:checked { 1102 background-color: #007BFF !important; 1103 border-color: #007BFF !important; 1104} 1105input[type="checkbox"]:checked::after { 1106 content: "â"; 1107 color: white; 1108 position: absolute; 1109 top: 4px; 1110 left: 7px; 1111 font-size: 18px !important; 1112} 1113.mktoCheckboxList label { 1114 padding-top: 0.35rem !important; 1115} 1116.mktoCheckboxList, .mktoRadioList { 1117 display: grid; 1118 grid-template-columns: auto 1fr; 1119 column-gap: 4px; 1120 row-gap: 12px; 1121 align-items: center; 1122} 1123.mktoRadioList { 1124 row-gap: unset !important;
1125 align-items: baseline !important; 1126} 1127input[type=radio].mktoField { 1128 width: 20px !important; 1129 height: 20px !important; 1130 margin-right: 4px !important; 1131 position: relative; 1132 top: 4px !important; 1133} 1134#in-house-form-placeholder { 1135 width: 75%; 1136} 1137button.mktoButton { 1138 color: #ffffff !important; 1139 font-weight: 700; 1140 font-size: 1.2rem !important; 1141} 1142</style>
1142<script> 1143(function () { 1144 // --------------------------------------------------------------------- 1145 // SHARED LOCATION-PREFIX UTILITY 1146 // Single source of truth for stripping the "Phoenix - " / "Test Company - " 1147 // prefix from location strings. Exposed on window.PhoenixEnrolClean so the 1148 // product-page pricing-card scripts can reuse it instead of keeping their 1149 // own copy of the regex. 1150 // --------------------------------------------------------------------- 1151 const LOCATION_PREFIXES = ['Phoenix', 'Test Company']; 1152 1153 const locationPrefixPattern = new RegExp( 1154 '^\\s*(' + LOCATION_PREFIXES.map(function (p) { 1155 return p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 1156 }).join('|') + ')\\s*[-\u2013\u2014]\\s*', 1157 'i' 1158 ); 1159 1160 function stripLocationPrefix(text) { 1161 return typeof text === 'string' ? text.replace(locationPrefixPattern, '').trim() : text; 1162 } 1163 1164 window.PhoenixEnrolClean = window.PhoenixEnrolClean || {}; 1165 window.PhoenixEnrolClean.locationPrefixPattern = locationPrefixPattern; 1166 window.PhoenixEnrolClean.stripLocationPrefix = stripLocationPrefix; 1167 1168 // Location VALUES to rename for display â applied to both the enrol-desc 1169 // Location line and the dropdown option text, so the two stay consistent 1170 // and the renamed value sorts alphabetically under its new name. 1171 // Keys are matched case-insensitively against the trimmed, prefix-stripped 1172 // location text. 1173 const LOCATION_VALUE_RENAMES = { 1174 'heathrow': 'London Heathrow' 1175 }; 1176 1177 function applyLocationRename(text) { 1178 const trimmed = (text || '').trim(); 1179 const key = trimmed.toLowerCase(); 1180 return Object.prototype.hasOwnProperty.call(LOCATION_VALUE_RENAMES, key) 1181 ? LOCATION_VALUE_RENAMES[key] 1182 : trimmed; 1183 } 1184 1185 window.PhoenixEnrolClean.applyLocationRename = applyLocationRename; 1186 1187 // --------------------------------------------------------------------- 1188 // Location VALUES to drop entirely from the enrol-desc block. 1189 // (3) Location: Public Virtual -> whole line removed 1190 // (4) Location: Exam -> whole line removed 1191 // The Venue line that follows (if any) is still labelled as normal, since 1192 // that's usually where the actual platform (e.g. Teams) is named. 1193 // --------------------------------------------------------------------- 1194 const LOCATION_VALUES_TO_HIDE = ['Public Virtual', 'Exam']; 1195 1196 function shouldHideLocationValue(text) { 1197 const normalized = (text || '').trim().toLowerCase(); 1198 return LOCATION_VALUES_TO_HIDE.some(function (v) { return v.toLowerCase() === normalized; }); 1199 } 1200 1201 // (5) Venue: Teams -> Venue: Microsoft Teams. 1202 // Runs as a final pass so it catches the label whether it was just 1203 // auto-generated below or was already present in the source content. 1204 function renameTeamsVenue(partHtml) { 1205 if (partHtml === null) return partHtml; 1206 1207 const text = getTextFromHtml(partHtml); 1208 if (!/^Venue:\s*Teams$/i.test(text)) return partHtml; 1209 1210 return partHtml.replace(/Teams\s*$/i, 'Microsoft Teams'); 1211 } 1212 1213 // --------------------------------------------------------------------- 1214 // enrol-desc line cleanup (Location / Venue / Speaker / Starts labelling, 1215 // hiding Recording/Live Streamed/E-Learning/Barco lines, hiding specific 1216 // Location values, and the Teams -> Microsoft Teams venue rename) 1217 // --------------------------------------------------------------------- 1218 function getTextFromHtml(html) { 1219 const temp = document.createElement('div'); 1220 temp.innerHTML = html; 1221 1222 return temp.textContent 1223 .replace(/\u00a0/g, ' ') 1224 .replace(/\s+/g, ' ') 1225 .trim(); 1226 } 1227 1228 function isExcludedLine(html) { 1229 const text = getTextFromHtml(html) 1230 .replace(/^(Location|Venue):\s*/i, '') 1231 .trim(); 1232 1233 return /^(Recording|Live Streamed|E[\s\-ââ]?Learning(?: Module)?|Barco)$/i.test(text); 1234 } 1235 1236 function isLabelledLine(html) { 1237 const text = getTextFromHtml(html); 1238 return /^(Location|Venue|Speaker|Starts):/i.test(text); 1239 } 1240 1241 function cleanEnrolDescriptions(root) { 1242 const items = []; 1243 1244 if (root && root.matches && root.matches('.enrol-desc')) { 1245 items.push(root); 1246 } 1247 1248 if (root && root.closest) { 1249 const closest = root.closest('.enrol-desc'); 1250 if (closest) { 1251 items.push(closest); 1252 } 1253 } 1254 1255 if (root && root.querySelectorAll) { 1256 items.push(...root.querySelectorAll('.enrol-desc')); 1257 } 1258
1259 [...new Set(items)].forEach(function (el) { 1260 let parts = el.innerHTML 1261 .trim() 1262 .split(/<br\s*\/?>/i) 1263 .map(function (part) { 1264 return part.trim(); 1265 }) 1266 .filter(function (part) { 1267 return part && !isExcludedLine(part); 1268 }); 1269 1270 let hasLocationPrefix = false; 1271 1272 for (let i = 0; i < parts.length; i++) { 1273 const lineText = getTextFromHtml(parts[i]); 1274 1275 // Convert "Phoenix - X" / "Test Company - X" into Location 1276 if (locationPrefixPattern.test(lineText)) { 1277 hasLocationPrefix = true; 1278 1279 const locationValue = applyLocationRename(stripLocationPrefix(lineText)); 1280 1281 // The next unlabelled line becomes Venue â done before the hide 1282 // check below so a hidden Location (Public Virtual / Exam) can 1283 // still surface its Venue (e.g. Teams) on the following line. 1284 if ( 1285 parts[i + 1] && 1286 !isLabelledLine(parts[i + 1]) && 1287 !isExcludedLine(parts[i + 1]) 1288 ) { 1289 parts[i + 1] = '<strong>Venue: </strong>' + getTextFromHtml(parts[i + 1]); 1290 } 1291 1292 parts[i] = shouldHideLocationValue(locationValue) 1293 ? null 1294 : '<strong>Location: </strong>' + locationValue; 1295 } 1296 } 1297 1298 // If there is no Phoenix/Test Company location line, label the second line as Venue 1299 // only when the following line is Speaker or Starts 1300 if (!hasLocationPrefix && parts[1]) { 1301 const secondLine = parts[1].trim(); 1302 const thirdLine = parts[2] ? parts[2].trim() : ''; 1303 1304 if ( 1305 !isLabelledLine(secondLine) && 1306 !isExcludedLine(secondLine) && 1307 /^(Speaker|Starts):/i.test(getTextFromHtml(thirdLine)) 1308 ) { 1309 parts[1] = '<strong>Venue: </strong>' + getTextFromHtml(secondLine); 1310 } 1311 } 1312 1313 // Final passes: drop hidden/empty lines, then apply the Teams rename 1314 parts = parts 1315 .filter(function (part) { 1316 return part !== null && part && !isExcludedLine(part); 1317 }) 1318 .map(renameTeamsVenue); 1319 1320 const cleaned = parts.join('<br>'); 1321 1322 if (cleaned !== el.innerHTML.trim()) { 1323 el.innerHTML = cleaned; 1324 } 1325 }); 1326 } 1327 1328 // --------------------------------------------------------------------- 1329 // <select class="enrol-location"> option text cleanup + (2) alphabetical sort 1330 // --------------------------------------------------------------------- 1331 function isPlaceholderOption(opt) { 1332 const text = (opt.textContent || '').trim().toLowerCase(); 1333 return !opt.value || opt.value === '0' || text === '' || 1334 text.indexOf('select') !== -1 || text.indexOf('please') !== -1; 1335 } 1336 1337 function sortLocationOptions(select) { 1338 const optionsArray = Array.from(select.options); 1339 const placeholders = optionsArray.filter(isPlaceholderOption); 1340 const realOptions = optionsArray.filter(function (opt) { return !isPlaceholderOption(opt); }); 1341 1342 const sorted = realOptions.slice().sort(function (a, b) { 1343 return a.textContent.trim().localeCompare(b.textContent.trim(), undefined, { 1344 sensitivity: 'base', 1345 numeric: true 1346 }); 1347 }); 1348 1349 // Skip the DOM write if it's already in order â this select gets 1350 // re-checked on every mutation, so writing unconditionally would keep 1351 // re-triggering the MutationObserver below in a loop. 1352 const alreadySorted = realOptions.every(function (opt, i) { return opt === sorted[i]; }); 1353 if (alreadySorted) return; 1354 1355 const selectedValue = select.value; 1356 1357 placeholders.concat(sorted).forEach(function (opt) { 1358 select.appendChild(opt); 1359 }); 1360 1361 // appendChild moves existing <option> nodes without firing 'change'; 1362 // restore the previously selected value explicitly just in case. 1363 select.value = selectedValue; 1364 } 1365 1366 function cleanLocationDropdowns(root) { 1367 const selects = []; 1368 1369 if (root && root.matches && root.matches('select.enrol-location')) { 1370 selects.push(root); 1371 } 1372 1373 if (root && root.querySelectorAll) { 1374 selects.push(...root.querySelectorAll('select.enrol-location')); 1375 } 1376
1377 [...new Set(selects)].forEach(function (select) { 1378 Array.from(select.options).forEach(function (option) { 1379 const stripped = stripLocationPrefix(option.textContent); 1380 const cleanedText = applyLocationRename(stripped); 1381 1382 if (cleanedText !== option.textContent) { 1383 option.textContent = cleanedText; 1384 } 1385 }); 1386 1387 sortLocationOptions(select); 1388 }); 1389 } 1390 1391 // --------------------------------------------------------------------- 1392 // (1) Hide "Self-paced" / "Blended" text in the child <div> of an 1393 // .event-variant, without removing the div itself. 1394 // --------------------------------------------------------------------- 1395 const EVENT_VARIANT_LABELS_TO_HIDE = ['Self-paced', 'Blended']; 1396 1397 function cleanEventVariantLabels(root) { 1398 const variants = []; 1399 1400 if (root && root.matches && root.matches('.event-variant')) { 1401 variants.push(root); 1402 } 1403 1404 if (root && root.querySelectorAll) { 1405 variants.push(...root.querySelectorAll('.event-variant')); 1406 } 1407 1408 [...new Set(variants)].forEach(function (variant) { 1409 Array.from(variant.children).forEach(function (child) { 1410 if (child.tagName !== 'DIV') return; 1411 1412 const text = child.textContent.trim(); 1413 const matches = EVENT_VARIANT_LABELS_TO_HIDE.some(function (label) { 1414 return label.toLowerCase() === text.toLowerCase(); 1415 }); 1416 1417 if (matches && child.textContent !== '') { 1418 child.textContent = ''; 1419 } 1420 }); 1421 }); 1422 } 1423 1424 // --------------------------------------------------------------------- 1425 // (8) Append "+ VAT" after the price in each .event-variant. 1426 // The price div is the unclassed child <div> whose text is just a £ amount 1427 // (e.g. "£175", "£1,295.00"). The suffix goes in its own span so it can be 1428 // styled separately (.enrol-vat) and so re-runs can see it's already there. 1429 // --------------------------------------------------------------------- 1430 const VAT_SUFFIX = '+vat'; 1431 const PRICE_PATTERN = /^£\s?\d[\d,]*(\.\d{1,2})?$/; 1432 1433 // Matches the "+vat" treatment on the product-page pricing cards: 1434 // smaller, lighter, with a small gap after the price. 1435 if (!document.getElementById('enrol-vat-style')) { 1436 const vatStyle = document.createElement('style'); 1437 vatStyle.id = 'enrol-vat-style'; 1438 vatStyle.textContent = 1439 '.event-variant [data-enrol-price]{' + 1440 'font-size:1.1rem;' + 1441 'font-weight:700;' + 1442 'color:#0f1a4a;' + 1443 'white-space:nowrap;' + 1444 '}' + 1445 '.event-variant .enrol-vat{' + 1446 'font-size:0.8rem;' + 1447 'font-weight:400;' + 1448 'color:#6b7280;' + 1449 'margin-left:2px;' + 1450 'white-space:nowrap;' + 1451 '}'; 1452 document.head.appendChild(vatStyle); 1453 } 1454 1455 function addVatToPrices(root) { 1456 const variants = []; 1457 1458 if (root && root.matches && root.matches('.event-variant')) { 1459 variants.push(root); 1460 } 1461 1462 if (root && root.querySelectorAll) { 1463 variants.push(...root.querySelectorAll('.event-variant')); 1464 } 1465 1466 [...new Set(variants)].forEach(function (variant) { 1467 Array.from(variant.children).forEach(function (child) { 1468 if (child.tagName !== 'DIV' || child.className) return; 1469 1470 // Mark the price div for styling (data attribute rather than a class, 1471 // so the unclassed-div check above keeps working on re-runs). 1472 if (child.querySelector('.enrol-vat')) { 1473 if (!child.hasAttribute('data-enrol-price')) child.setAttribute('data-enrol-price', ''); 1474 return; 1475 } 1476 1477 const text = child.textContent.replace(/\u00a0/g, ' ').trim(); 1478 if (!PRICE_PATTERN.test(text)) return; 1479 1480 child.setAttribute('data-enrol-price', ''); 1481 1482 const vat = document.createElement('span'); 1483 vat.className = 'enrol-vat'; 1484 vat.textContent = VAT_SUFFIX; 1485 child.appendChild(vat); 1486 }); 1487 }); 1488 } 1489 1490 // --------------------------------------------------------------------- 1491 // (6) On any URL containing "exam", hide .enrolment.bg-white.radius-1 1492 // elements whose text contains "(EXAM)". 1493 // --------------------------------------------------------------------- 1494 const isExamUrl = /exam/i.test(window.location.href); 1495 1496 function hideExamEnrolments(root) { 1497 if (!isExamUrl) return; 1498 1499 const candidates = []; 1500 1501 if (root && root.matches && root.matches('.enrolment.bg-white.radius-1')) { 1502 candidates.push(root); 1503 } 1504 1505 if (root && root.querySelectorAll) { 1506 candidates.push(...root.querySelectorAll('.enrolment.bg-white.radius-1')); 1507 } 1508
1509 [...new Set(candidates)].forEach(function (el) { 1510 if (el.textContent.indexOf('(EXAM)') !== -1 && el.style.display !== 'none') { 1511 el.style.display = 'none'; 1512 } 1513 }); 1514 } 1515 1516 // --------------------------------------------------------------------- 1517 // (7) On pages where (EXAM) events are shown rather than hidden (i.e. 1518 // everywhere the exam-URL rule above does NOT apply), strip the literal 1519 // "(EXAM)" text out of the label to tidy up the display. Only the text 1520 // is removed â the element itself stays visible. 1521 // --------------------------------------------------------------------- 1522 function stripExamText(el) { 1523 const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null); 1524 let node; 1525 1526 while ((node = walker.nextNode())) { 1527 if (/\(EXAM\)/i.test(node.nodeValue)) { 1528 node.nodeValue = node.nodeValue 1529 .replace(/\s*\(EXAM\)\s*/gi, ' ') 1530 .replace(/\s+/g, ' ') 1531 .trim(); 1532 } 1533 } 1534 } 1535 1536 function tidyExamLabels(root) { 1537 if (isExamUrl) return; // these get hidden entirely instead â see hideExamEnrolments 1538 1539 const candidates = []; 1540 1541 if (root && root.matches && root.matches('.enrolment.bg-white.radius-1')) { 1542 candidates.push(root); 1543 } 1544 1545 if (root && root.querySelectorAll) { 1546 candidates.push(...root.querySelectorAll('.enrolment.bg-white.radius-1')); 1547 } 1548 1549 [...new Set(candidates)].forEach(function (el) { 1550 if (el.textContent.indexOf('(EXAM)') !== -1) { 1551 stripExamText(el); 1552 } 1553 }); 1554 } 1555 1556 // --------------------------------------------------------------------- 1557 // (9) Hide an .enrol-month-header when every .enrolment between it and 1558 // the next month header is display: none. Headers are flat siblings of 1559 // the enrolments inside .enrol-options, so we walk forward until the next 1560 // header. Only headers this script hid (data-month-hidden) are ever 1561 // un-hidden, so it won't fight any other script that hides them. 1562 // --------------------------------------------------------------------- 1563 function hideEmptyMonthHeaders(root) { 1564 const scope = root && root.querySelectorAll ? root : document; 1565 1566 scope.querySelectorAll('.enrol-month-header').forEach(function (header) { 1567 let sibling = header.nextElementSibling; 1568 let hasEnrolments = false; 1569 let hasVisible = false; 1570 1571 while (sibling && !sibling.classList.contains('enrol-month-header')) { 1572 if (sibling.classList.contains('enrolment')) { 1573 hasEnrolments = true; 1574 if (sibling.style.display !== 'none') { 1575 hasVisible = true; 1576 break; 1577 } 1578 } 1579 sibling = sibling.nextElementSibling; 1580 } 1581 1582 const shouldHide = hasEnrolments && !hasVisible; 1583 1584 if (shouldHide && header.style.display !== 'none') { 1585 header.style.display = 'none'; 1586 header.setAttribute('data-month-hidden', 'true'); 1587 } else if (!shouldHide && header.hasAttribute('data-month-hidden')) { 1588 header.style.display = ''; 1589 header.removeAttribute('data-month-hidden'); 1590 } 1591 }); 1592 } 1593 1594 function cleanAll() { 1595 cleanEnrolDescriptions(document); 1596 cleanLocationDropdowns(document); 1597 cleanEventVariantLabels(document); 1598 addVatToPrices(document); 1599 hideExamEnrolments(document); 1600 tidyExamLabels(document); 1601 hideEmptyMonthHeaders(document); // last, so it sees the final visibility 1602 } 1603 1604 // Run immediately 1605 cleanAll(); 1606 1607 // Watch for API/dropdown-rendered changes. Style attribute changes are 1608 // watched too, so the month headers react if anything else hides/shows an 1609 // enrolment. Every write above is guarded, so this settles after one pass. 1610 const observer = new MutationObserver(function () { 1611 cleanAll(); 1612 }); 1613 1614 observer.observe(document.body, { 1615 childList: true, 1616 subtree: true, 1617 characterData: true, 1618 attributes: true, 1619 attributeFilter: ['style'] 1620 }); 1621 1622 // Extra backup for dropdown/user-triggered API updates 1623 document.addEventListener('change', function () { 1624 setTimeout(cleanAll, 50); 1625 setTimeout(cleanAll, 250); 1626 setTimeout(cleanAll, 750); 1627 }); 1628 1629 document.addEventListener('click', function () { 1630 setTimeout(cleanAll, 50); 1631 setTimeout(cleanAll, 250); 1632 setTimeout(cleanAll, 750); 1633 }); 1634})(); 1635</script>
1635<script> 1636(function () { 1637 function cleanText(text) { 1638 return (text || "").replace(/\s+/g, " ").trim(); 1639 } 1640 function hideCountryFilter() { 1641 var headings = document.querySelectorAll("h4"); 1642 for (var i = 0; i < headings.length; i++) { 1643 if (cleanText(headings[i].textContent) === "Filter by country") { 1644 headings[i].parentElement.style.display = "none"; 1645 break; 1646 } 1647 } 1648 } 1649 hideCountryFilter(); 1650 var observer = new MutationObserver(hideCountryFilter); 1651 observer.observe(document.body, { 1652 childList: true, 1653 subtree: true 1654 }); 1655})(); 1656</script>
1656<!-- Start of LiveChat (www.livechat.com) code -->
1657<script> 1658 window.__lc = window.__lc || {}; 1659 window.__lc.license = 2651931; 1660 window.__lc.integration_name = "manual_channels"; 1661 window.__lc.product_name = "livechat"; 1662 ;(function(n,t,c){function i(n){return e._h?e._h.apply(null,n):e._q.push(n)}var e={_q:[],_h:null,_v:"2.0",on:function(){i(["on",c.call(arguments)])},once:function(){i(["once",c.call(arguments)])},off:function(){i(["off",c.call(arguments)])},get:function(){if(!e._h)throw new Error("[LiveChatWidget] You can't use getters before load.");return i(["get",c.call(arguments)])},call:function(){i(["call",c.call(arguments)])},init:function(){var n=t.createElement("script");n.async=!0,n.type="text/javascript",n.src="https://cdn.livechatinc.com/tracking.js",t.head.appendChild(n)}};!n.__lc.asyncInit&&e.init(),n.Live⦠1663</script>
1663 1664<noscript><a href="https://www.livechat.com/chat-with/2651931/" rel="nofollow">Chat with us</a>, powered by <a href="https://www.livechat.com/?welcome" rel="noopener nofollow" target="_blank">LiveChat</a></noscript> 1665<!-- End of LiveChat code --> 1666 1667
1667<script src="/Assets/Umbraco.Engage/Scripts/umbracoEngage.analytics.js"></script>
1667 1668 1669 1670 1671
1671<script src="/Assets/Umbraco.Engage/Scripts/umbracoEngage.analytics.ga4-bridge.min.js"></script>
1671 1672
1672<script src="/Assets/Umbraco.Engage/Scripts/umbracoEngage.analytics.blockerdetection.js"></script>
1672 1673
1673<script>typeof umbracoEngage!=="undefined"&&umbracoEngage.analytics&&umbracoEngage.analytics.init("4e1b82cc-4471-41ec-9031-7d4036cd2d9e")</script>
1673</body> 1674</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.