<div class="find-courses hidden" data-redirect-url="/components/preview/efl-venue-results-page" data-course-name="W1VC" data-radius="25" data-behaviour="bing-map-search" data-course-blockid="" data-course-isprocourse="False">
    <button class="lightbox-overlay__close" id="close">
        <span class="visually-hidden">Close dialog</span>
    </button>
    <div class="find-courses__image-wrapper">
        <img src="/assets/example-content/find-courses-bg.png" loading="lazy">
    </div>
    <div class="find-courses__search">
        <div class="find-courses__search--pin"></div>
        <div class="steps search-step-1">
            <div class="default-steps">
                <h2>Let’s find a course</h2>
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vestibulum</p>
            </div>
            <div class="error-steps hidden">
                <h2>Sorry, no courses found</h2>
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vestibulum.
                    <a href="/" target="_blank" class="contactus">Contact Us</a>
                </p>
            </div>
            <a href="/" class="cta cta--primary  location-denied hidden" id="location-denied" tabindex="0">location blocked by browser</a>

            <a href="/" class="cta cta--primary  current-location-found hidden" id="current-location-found" tabindex="0">Location found</a>

            <a href="/" class="cta cta--primary  use-current-location" id="use-current-location" tabindex="0">Use Current location</a>

            <a href="/" class="cta cta--secondary  enter-postcode" id="enter-postcode" tabindex="0">Enter postcode</a>

        </div>
        <div class="steps search-step-2 hidden">
            <h2>Let’s find a course near you</h2>
            <div class="find-courses__postcode">
                <div id="searchBoxContainer">
                    <input type="text" id="searchBox" class="find-courses__postcode-input" placeholder="Enter your postcode" autocomplete="off" />
                </div>
            </div>
            <a href="/" class="cta cta--primary  postcode-search" id="postcode-search" tabindex="0">Search</a>

        </div>
        <div class="steps search-step-3 hidden">
            <h2>Searching...</h2>
            <div class="loading">
                <div class="loader"></div>
                <div class="efl-logo"></div>
            </div>
        </div>
    </div>
</div>

No notes defined.

{
  "cta1": {
    "copy": "Use Current location",
    "modifier": "primary",
    "id": "use-current-location",
    "additionalClass": "use-current-location"
  },
  "cta2": {
    "copy": "Enter postcode",
    "modifier": "secondary",
    "id": "enter-postcode",
    "additionalClass": "enter-postcode"
  },
  "cta3": {
    "copy": "Search",
    "modifier": "primary",
    "id": "postcode-search",
    "additionalClass": "postcode-search"
  },
  "cta4": {
    "copy": "Location found",
    "modifier": "primary",
    "id": "current-location-found",
    "additionalClass": "current-location-found hidden"
  },
  "cta5": {
    "copy": "Confirmation and Payment",
    "modifier": "primary",
    "id": "confirmation-and-payment",
    "additionalClass": "confirmation-and-payment"
  },
  "cta6": {
    "copy": "location blocked by browser",
    "modifier": "primary",
    "id": "location-denied",
    "additionalClass": "location-denied hidden"
  }
}
  • Content:
    import { Dialog } from '../lightbox-overlay/lightbox-overlay';
    import bingMap from '../bing-map/bing-map';
    
    export default parentElement => {
      const DIALOG_ID = 'find-courses-dialog';
      const headers = {
        // 'Ocp-Apim-Subscription-Key': '8279c7fab35f432daf1a0bd395a9ae48',
      };
      const preReqModal = document.querySelector(
        '[data-behaviour="pre-req-modal"]'
      );
    
      const swithScreen = ({ screen }) => {
        const modalWindow = document.querySelector('#find-courses-dialog');
        const allSteps = modalWindow.querySelector('.find-courses__search');
    
        allSteps.querySelectorAll('.steps').forEach(steps => {
          steps.classList.add('hidden');
        });
        screen.classList.remove('hidden');
      };
    
      const searchByCurrentLocation = target => {
        const allSteps = target.closest('.find-courses__search');
        const screen = allSteps.querySelector('.search-step-1 ');
    
        const deniedCta = screen.querySelector('.location-denied');
        const Cta = screen.querySelector('#use-current-location');
    
        const onDeniedClick = e => {
          e.preventDefault();
        };
    
        deniedCta.addEventListener('click', onDeniedClick);
    
        if (navigator.geolocation) {
          navigator.geolocation.getCurrentPosition(
            position => {
              const modalWindow = document.querySelector('#find-courses-dialog');
    
              modalWindow.querySelector('.search-longitude').value =
                position.coords.longitude;
              modalWindow.querySelector('.search-latitude').value =
                position.coords.latitude;
              const cta = screen.querySelector('.current-location-found');
    
              target.querySelector('.loading').remove();
              target.classList.remove('searching');
              target.classList.add('hidden');
              cta.classList.remove('hidden');
              setTimeout(() => {
                cta.click();
              }, 1000);
            },
            error => {
              Cta.classList.add('hidden');
              deniedCta.classList.remove('hidden');
              console.log(error);
            }
          );
        } else {
          // eslint-disable-next-line no-console
          console.log('Geolocation is not supported by this browser.');
        }
      };
    
      const searchByLocation = event => {
        event.preventDefault();
        const { target } = event;
    
        target.classList.add('searching');
        target.insertAdjacentHTML(
          'beforeend',
          '<div class="loading"><span class="efl-logo"></span><span class="loader"></span></div>'
        );
        searchByCurrentLocation(target);
      };
    
      const searchByPostcode = event => {
        event.preventDefault();
        const { target } = event;
        const allSteps = target.closest('.find-courses__search');
        const screen = allSteps.querySelector('.search-step-2');
        const map = screen.querySelector('.MicrosoftMap');
        const inputBox = screen.querySelector('.find-courses__postcode-input');
        const btn = screen.querySelector('.postcode-search');
    
        swithScreen({ screen });
        screen
          .querySelector('.postcode-search')
          .setAttribute('disabled', 'disabled');
        if (!map) {
          bingMap('bingMapsearchBox', 'bingMapsearchBoxContainer');
        }
        inputBox.focus();
        // input value empty check
        inputBox.addEventListener('input', e => {
          if (!e.target.value) {
            btn.setAttribute('disabled', 'disabled');
          }
        });
      };
    
      async function searchVenueCallback(longitude, latitude) {
        const modalWindow = document.querySelector('#find-courses-dialog');
        const {
          courseName,
          courseBlockid,
          courseIsprocourse,
        } = modalWindow.querySelector('.find-courses').dataset;
        let blockid = '';
        // replace url with `/seachVenue/` in development to see results
        // const url = `/Courses/GetAvailableCourses/?postCodeLon=${longitude}
        // &postCodeLat=${latitude}&courseName=${courseName}`;
    
        if (courseBlockid) {
          blockid = `&blockId=${courseBlockid}`;
        }
        const url = `${
          window.location.origin
        }/Courses/GetAvailableCourses/?postCodeLon=${longitude}&postCodeLat=${latitude}&courseName=${courseName}&isProCourse=${courseIsprocourse}${blockid}`;
        // eslint-disable-next-line compat/compat
        const response = await fetch(url, {
          headers,
        });
    
        return response.json();
      }
    
      const checkVenueAvailable = (longitude, latitude) => {
        const modalWindow = document.querySelector('#find-courses-dialog');
        const allSteps = modalWindow.querySelector('.find-courses__search');
    
        try {
          searchVenueCallback(longitude, latitude).then(response => {
            if (response && response.isCourseAvailable) {
              const {
                redirectUrl,
                courseName,
                courseBlockid,
                courseIsprocourse,
              } = modalWindow.querySelector('.find-courses').dataset;
              let blockid = '';
    
              if (courseBlockid) {
                blockid = `&blockId=${courseBlockid}`;
              }
    
              // eslint-disable-next-line no-restricted-globals
              location.href = `${redirectUrl}?postCodeLon=${longitude}&postCodeLat=${latitude}&courseName=${courseName}&isProCourse=${courseIsprocourse}${blockid}`;
            } else {
              const screen = allSteps.querySelector('.search-step-1');
    
              screen.querySelector('.default-steps').classList.add('hidden');
              screen.querySelector('.error-steps').classList.remove('hidden');
              const cta = screen.querySelector('.current-location-found');
              const currentCta = screen.querySelector('.use-current-location');
              const deniedCta = screen.querySelector('.location-denied');
    
              if (deniedCta.classList.contains('hidden')) {
                currentCta.classList.remove('hidden');
              } else {
                currentCta.classList.add('hidden');
              }
    
              cta.classList.add('hidden');
              swithScreen({ screen });
              currentCta.focus();
            }
          });
        } catch (e) {
          throw new Error('Uable to retrive match score ::', e);
        }
      };
    
      const searchVenue = event => {
        event.preventDefault();
        const { target } = event;
        const allSteps = target.closest('.find-courses__search');
        const screen = allSteps.querySelector('.search-step-3');
        const modalWindow = document.querySelector('#find-courses-dialog');
        const longitude = modalWindow.querySelector('.search-longitude').value;
        const latitude = modalWindow.querySelector('.search-latitude').value;
    
        swithScreen({ screen });
        checkVenueAvailable(longitude, latitude);
      };
    
      const generateLightBox = labelId => {
        let html = parentElement.outerHTML;
    
        html = html.replace('find-courses hidden', 'find-courses');
        html = html.replace('id="searchBox"', 'id="bingMapsearchBox"');
        html = html.replace(
          'id="searchBoxContainer"',
          'id="bingMapsearchBoxContainer"'
        );
        return `
        <div role="dialog" id="${DIALOG_ID}" aria-labelledby="${labelId}" aria-modal="true" class="lightbox-overlay">
          ${html}
          <input type="hidden" class="search-longitude" value=""/>
          <input type="hidden" class="search-latitude" value=""/>
        </div>`;
      };
    
      const removeLightBox = () => {
        document.getElementById(DIALOG_ID).remove();
        if (document.querySelector('#find-course-near-me')) {
          document
            .querySelector('#find-course-near-me')
            .closest('a')
            .focus();
        }
      };
    
      const searchButton = document.querySelector('#find-course-near-me');
    
      if (!searchButton) {
        return;
      }
    
      if (
        preReqModal &&
        preReqModal.getAttribute('data-pre-req-check') === 'false'
      ) {
        return;
      }
    
      const openLightbox = focusBtn => {
        // Create the lightbox
        const lightboxContainer = document.createElement('div');
    
        lightboxContainer.innerHTML = generateLightBox({
          labelId: focusBtn.getAttribute('id'),
        });
        document.body.appendChild(lightboxContainer);
        // eslint-disable-next-line no-new
        new Dialog({
          dialogId: DIALOG_ID,
          focusAfterClosed: focusBtn,
          focusFirst: 'close',
          closeCallBack: () => removeLightBox(),
        });
    
        const postcodeBtn = lightboxContainer.querySelector('.enter-postcode');
        const searchBtn = lightboxContainer.querySelector('.postcode-search');
        const currentBtn = lightboxContainer.querySelector('.use-current-location');
        const currentSearchBtn = lightboxContainer.querySelector(
          '.current-location-found'
        );
    
        lightboxContainer.querySelector('#close').focus();
    
        // Find current location coordinates
        currentBtn.addEventListener('click', e => {
          searchByLocation(e);
        });
    
        // search venue by current location
        currentSearchBtn.addEventListener('click', e => {
          searchVenue(e);
        });
    
        // load map screen
        postcodeBtn.addEventListener('click', e => {
          searchByPostcode(e);
        });
    
        // search venue by longitude and latitude
        searchBtn.addEventListener('click', e => {
          if (searchBtn.getAttribute('disabled') === 'disabled') {
            e.preventDefault();
            return;
          }
          searchVenue(e);
        });
      };
    
      if (searchButton) {
        searchButton.addEventListener('keyup', event => {
          if (event.keyCode === 13) {
            // Cancel the default action, if needed
            event.preventDefault();
            searchButton.click();
          }
        });
    
        searchButton.addEventListener('click', event => {
          event.preventDefault();
          const allSteps = parentElement.querySelector('.find-courses__search');
          const screen = allSteps.querySelector('.search-step-1');
    
          allSteps.querySelectorAll('.steps').forEach(steps => {
            steps.classList.add('hidden');
          });
          screen.classList.remove('hidden');
    
          openLightbox(searchButton);
        });
      }
    };
    
  • URL: /components/raw/find-courses/find-courses.js
  • Filesystem Path: src/library/components/find-courses/find-courses.js
  • Size: 9.7 KB
  • Content:
    /* stylelint-disable no-descending-specificity */
    .find-courses {
      display: flex;
      flex-direction: column;
      border-radius: 0.8rem;
      box-shadow: 0 4px 6px rgba(91, 104, 133, 0.1);
      max-width: 34.3rem;
      background-color: $white;
      position: relative;
      max-height: 51.1rem;
      min-width: 34.3rem;
      .lightbox-overlay__close {
        top: 1.6rem;
        right: 1.6rem;
        width: 3.2rem;
        height: 3.2rem;
        &::before {
          width: 3.2rem;
          height: 3.2rem;
        }
      }
      &__image-wrapper {
        height: 17rem;
        width: 100%;
        border-radius: 0.8rem 0.8rem 0 0;
        overflow: hidden;
        img {
          height: 100%;
          object-fit: cover;
          width: 100%;
        }
      }
      &__search {
        padding: 2.4rem;
        padding-bottom: 5.2rem;
        text-align: center;
        position: relative;
        height: 34.1rem;
        &--pin {
          background: url('./assets/images/map-pin.svg') no-repeat center;
          width: 7.2rem;
          height: 7.2rem;
          display: flex;
          margin: 0 auto;
          top: -3.6rem;
          position: absolute;
          left: 0;
          right: 0;
        }
    
        &--success {
          padding: 3.5rem;
          img {
            margin: 0 auto;
            width: 6.5rem;
            height: 6.5rem;
            margin-top: 2.4rem;
          }
        }
        .steps {
          img {
            margin: 0 auto;
            width: 8.6rem;
            height: 8.6rem;
          }
        }
        h2 {
          @extend .efl-heading-2;
    
          color: $blue;
          margin-top: 2.4rem;
        }
        p {
          @extend .efl-p-1;
    
          color: $color-interface-light;
          margin-top: 0.8rem;
        }
        .error-steps {
          p {
            margin-top: 1.6rem;
          }
          a {
            text-decoration: underline;
            color: $crest-blue;
          }
          a.redlink {
            color: $red;
          }
        }
        .cta--primary {
          background-color: $blue-accent3;
          margin: 0 auto;
          margin-top: 3.2rem;
          color: $white;
        }
        .cta--secondary {
          margin: 0 auto;
          margin-top: 1.6rem;
          &:hover {
            background-color: transparent;
            color: $blue;
          }
        }
        .cta {
          &.use-current-location {
            position: relative;
            &::after {
              content: '';
              background: url('./assets/images/location-pin-white.svg') no-repeat
                center right;
              width: 1.4rem;
              height: 2rem;
              position: absolute;
              right: 1.6rem;
              left: initial;
              bottom: initial;
              top: initial;
            }
            .loading {
              position: absolute;
              width: 2.8rem;
              height: 2.8rem;
              right: 1.6rem;
              .efl-logo {
                background-image: url('./assets/images/efl-loader-logo.svg');
                background-size: 1.13rem 1.37rem;
              }
              .loader {
                position: absolute;
                left: 0;
                &::after {
                  background: $blue-accent3;
                }
              }
            }
            &.searching {
              &::after {
                display: none;
              }
            }
          }
          &.current-location-found {
            &::after {
              content: '';
              background: url('./assets/images/tick-circle.svg') no-repeat center
                right;
              width: 2.1rem;
              height: 2.1rem;
              position: absolute;
              right: 1.6rem;
              left: initial;
              bottom: initial;
              top: initial;
            }
          }
    
          &.confirmation-and-payment {
            &::after {
              content: '';
              background: url('./assets/images/tick-circle.svg') no-repeat center
                right;
              width: 2.1rem;
              height: 2.1rem;
              position: absolute;
              right: 1.6rem;
              left: initial;
              bottom: initial;
              top: initial;
            }
          }
          &.postcode-search {
            &[disabled] {
              border: none;
              color: $light-blue;
              background-color: $grey-light;
              cursor: default;
            }
          }
          &.location-denied {
            border: none;
            color: $color-interface-light;
            background-color: $grey-light;
            cursor: default;
          }
        }
        &.location-denied .hidden {
          display: none !important;
        }
        input {
          @extend .efl-p-1;
    
          color: $crest-blue;
          padding: 1.2rem 2.5rem 1.1rem 1rem;
          border: none;
          width: 100%;
          border-bottom: 1px solid $color-interface-light;
          margin-top: 4rem;
          background: url('./assets/images/postcode-search.svg') no-repeat 98%
            center;
          box-sizing: border-box !important;
          line-height: 1.6rem;
          font-weight: 700;
    
          &::-webkit-search-cancel-button {
            -webkit-appearance: none;
            background: url('./assets/images/icon-close-blue.svg') no-repeat center
              right;
            width: 1.4rem;
            height: 1.4rem;
            padding: 0.5rem;
            background-size: 1.6rem;
            background-color: $white;
            margin-right: -1.9rem;
            cursor: pointer;
          }
        }
      }
      #bingMapsearchBoxContainer {
        position: relative;
        .MicrosoftMap {
          position: initial !important;
        }
        .MicrosoftMap .as_container_search {
          width: 100% !important;
          text-align: left;
        }
        .MicrosoftMap .as_container .line1 {
          @extend .efl-p-1;
    
          color: $black;
        }
        .MicrosoftMap .as_container .line2 {
          @extend .efl-p-1;
    
          color: $color-interface-light;
          margin-top: 0.1rem;
        }
        .MicrosoftMap .as_img.maps_address {
          background-image: url('./assets/images/location-pin.svg');
          width: 1.5rem !important;
          height: 2.2rem !important;
          margin-right: 0.8rem;
        }
        .MicrosoftMap .as_container .bingLogoContainer {
          display: none !important;
        }
        .MicrosoftMap .as_container .suggestLink {
          padding: 1.6rem 2.4rem;
          &:hover {
            background-color: $grey-light;
          }
        }
      }
      .loading {
        position: relative;
        margin: 4rem auto;
        width: 10.4em;
        height: 10.4em;
        &.show {
          display: block;
        }
        .efl-logo {
          background-image: url('./assets/images/ef-logo.svg');
          background-repeat: no-repeat;
          background-position: center;
          position: absolute;
          z-index: 2;
          top: 0;
          left: 0;
          background-size: 4.2rem 5.1rem;
          width: 100%;
          height: 100%;
        }
        .loader {
          font-size: 10px;
          text-indent: -9999em;
          width: 100%;
          height: 100%;
          border-radius: 100%;
          overflow: hidden;
          background: rgb(236, 238, 243);
          position: relative;
          -webkit-animation: load3 1.4s infinite linear;
          animation: load3 1.4s infinite linear;
          -webkit-transform: translateZ(0);
          -ms-transform: translateZ(0);
          transform: translateZ(0);
        }
        .loader::before {
          width: 100%;
          height: 50%;
          background: -linear-gradient(0deg, #004aa3 0%, #eceef3 50%);
          background: -moz-linear-gradient(0deg, #004aa3 0%, #eceef3 50%);
          background: -o-linear-gradient(0deg, #004aa3 0%, #eceef3 50%);
          background: -ms-linear-gradient(0deg, #004aa3 0%, #eceef3 50%);
          background: -webkit-linear-gradient(0deg, #004aa3 0%, #eceef3 50%);
          transform-origin: bottom right;
          position: absolute;
          top: 0;
          left: 0;
          content: '';
        }
        .loader::after {
          background: #fff;
          width: 85%;
          height: 85%;
          border-radius: 50%;
          content: '';
          margin: auto;
          position: absolute;
          top: 0;
          left: 0;
          bottom: 0;
          right: 0;
        }
    
        @-webkit-keyframes load3 {
          0% {
            -webkit-transform: rotate(0deg);
            transform: rotate(0deg);
          }
          100% {
            -webkit-transform: rotate(360deg);
            transform: rotate(360deg);
          }
        }
    
        @keyframes load3 {
          0% {
            -webkit-transform: rotate(0deg);
            transform: rotate(0deg);
          }
          100% {
            -webkit-transform: rotate(360deg);
            transform: rotate(360deg);
          }
        }
      }
      &[data-behaviour='pre-req-modal'] {
        .find-courses__search {
          h2 {
            @include text-limit(3);
          }
        }
      }
    
      @media screen and (min-width: $mq-medium) {
        flex-direction: row;
        max-width: 95.2rem;
        max-height: 43.6rem;
        .lightbox-overlay__close {
          &::before {
            background-image: url('./assets/images/search-modal-close.svg');
          }
        }
        &__image-wrapper {
          height: 43.6rem;
          width: 46.2rem;
          border-radius: 0.8rem 0 0 0.8rem;
        }
        &__search {
          padding: 5.2rem 9rem;
          width: 49rem;
          height: 43.6rem;
          &--pin {
            position: initial;
            top: initial;
          }
          h2 {
            font-size: 3.2rem;
            line-height: 3.6rem;
          }
          input {
            font-size: 2rem;
            line-height: 2.8rem;
            font-weight: 500;
            padding: 1.2rem 2.7rem 1.1rem 1rem;
          }
        }
        &[data-behaviour='pre-req-modal'] {
          .find-courses__search {
            width: 59rem;
            padding: 3.2rem 7rem;
          }
        }
      }
    }
    
  • URL: /components/raw/find-courses/find-courses.scss
  • Filesystem Path: src/library/components/find-courses/find-courses.scss
  • Size: 9.3 KB
<div class="find-courses hidden" data-redirect-url="/components/preview/efl-venue-results-page" data-course-name="W1VC" data-radius="25" data-behaviour="bing-map-search" data-course-blockid="" data-course-isprocourse="False">
    <button class="lightbox-overlay__close" id="close">
        <span class="visually-hidden">Close dialog</span>
    </button>
    <div class="find-courses__image-wrapper">
        <img src="/assets/example-content/find-courses-bg.png" loading="lazy">
    </div>
    <div class="find-courses__search">
        <div class="find-courses__search--pin"></div>
        <div class="steps search-step-1">
            <div class="default-steps">
                <h2>Let’s find a course</h2>
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vestibulum</p>
            </div>
            <div class="error-steps hidden">
                <h2>Sorry, no courses found</h2>
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vestibulum.
                    <a href="/" target="_blank" class="contactus">Contact Us</a>
                </p>
            </div>
            {{render '@cta' cta6 merge="true"}}
            {{render '@cta' cta4 merge="true"}}
            {{render '@cta' cta1 merge="true"}}
            {{render '@cta' cta2 merge="true"}}
        </div>
        <div class="steps search-step-2 hidden">
            <h2>Let’s find a course near you</h2>
            <div class="find-courses__postcode">
                <div id="searchBoxContainer">
                    <input type="text" id="searchBox" class="find-courses__postcode-input" placeholder="Enter your postcode" autocomplete="off"/>
                </div>
            </div>
            {{render '@cta' cta3 merge="true"}}
        </div>
        <div class="steps search-step-3 hidden">
            <h2>Searching...</h2>
            <div class="loading">
                <div class="loader"></div>
                <div class="efl-logo"></div>
            </div>
        </div>
    </div>
</div>