Guidance

The @uol-header-local-navigation presents a set of site specific top level links allowing visitors to navigate the local site.

The purpose of this component is to provide consistent navigation throughout the site allowing users to get to key areas within the site easily.

The local navigation must remain consistent throughout the site, ie. if two pages are on the same domain or subdomain the navigation should always be the same.

Examples:

must have the same navigation

must have the same navigation

The local navigation should always start with a “Home” link that returns the user to the site root.

The local navigation supports a single level of sub-navigation to support groups of related links. Example

  • Home
  • Study
    • Undergraduate
    • Masters courses
    • Research degrees
  • Research and innovation
  • Working with business
  • Global

We do not recommend having more than one set of sub-navigation within the local navigation, as illustrated.

The sub-navigation items may also include CTAs (Calls to action). These items are styled differently and should be located at the end of the sub-navigation group.

Section navigation

Once users have navigated to a section of the site using the local navigation, additional navigation can be provided using the @uol-section-nav.

Developer guidance

Current page

If the current page matches a link from the local navigation, the matching navigation link should be set as “current”: true.

Example:

{
  "title": "Home",
  "url": "/",
  "current": true
},

This helps Assistive Technology users know that the link will not take them to a different page.

CTAs

Only navigation items within the sub-navigation may use “cta”: true. Items identified as CTAs should be grouped together at the end of a sub-navigation group. See component example context for illustration.

{% if items.length %}
<nav class="uol-header-local-navigation-wrapper uol-content-container" aria-label="Site navigation">
  <ul class="uol-header-local-navigation">
    {% for item in items %}
      <li class="uol-header-local-navigation__item {{ 'uol-header-local-navigation__item--parent' if item.items.length }}" data-label="{{ item.title }}">
        {% if item.url %}
          <a class="uol-header-local-navigation__link" href="{{ item.url }}" {% if item.current %}aria-current="page"{% endif %}>
        {% endif %}
        {{ item.title }}
        {% if item.url %}
          </a>
        {% endif %}

        {% if item.items.length %}
          <ul class="uol-header-local-navigation__sub-nav" data-title="{{ item.title }}">
            {% for item in item.items %}
              <li class="uol-header-local-navigation__item {{ 'uol-header-local-navigation__item--cta' if item.cta }}">
                {% if item.url %}
                  <a class="uol-header-local-navigation__link uol-header-local-navigation__link--sub-nav" href="{{ item.url }}"  {% if item.current %}aria-current="page"{% endif %}>
                {% endif %}
                {{ item.title | safe }}
                {% if item.url %}
                  </a>
                {% endif %}
              </li>
            {% endfor %}
          </ul>
        {% endif %}
      </li>
    {% endfor %}
  </ul>
</nav>
{% endif %}
<nav class="uol-header-local-navigation-wrapper uol-content-container" aria-label="Site navigation">
    <ul class="uol-header-local-navigation">

        <li class="uol-header-local-navigation__item " data-label="Home">

            <a class="uol-header-local-navigation__link" href="/" aria-current="page">

                Home

            </a>

        </li>

        <li class="uol-header-local-navigation__item uol-header-local-navigation__item--parent" data-label="Study">

            Study

            <ul class="uol-header-local-navigation__sub-nav" data-title="Study">

                <li class="uol-header-local-navigation__item ">

                    <a class="uol-header-local-navigation__link uol-header-local-navigation__link--sub-nav" href="/study/undergraduate">

                        Undergraduate

                    </a>

                </li>

                <li class="uol-header-local-navigation__item ">

                    <a class="uol-header-local-navigation__link uol-header-local-navigation__link--sub-nav" href="/study/masters">

                        Masters courses

                    </a>

                </li>

                <li class="uol-header-local-navigation__item ">

                    <a class="uol-header-local-navigation__link uol-header-local-navigation__link--sub-nav" href="/study/research">

                        Research degrees

                    </a>

                </li>

                <li class="uol-header-local-navigation__item ">

                    <a class="uol-header-local-navigation__link uol-header-local-navigation__link--sub-nav" href="/study/international-students">

                        International students

                    </a>

                </li>

                <li class="uol-header-local-navigation__item ">

                    <a class="uol-header-local-navigation__link uol-header-local-navigation__link--sub-nav" href="/study/online-courses">

                        Online courses

                    </a>

                </li>

                <li class="uol-header-local-navigation__item uol-header-local-navigation__item--cta">

                    <a class="uol-header-local-navigation__link uol-header-local-navigation__link--sub-nav" href="/study/courses-search">

                        Search courses

                    </a>

                </li>

                <li class="uol-header-local-navigation__item uol-header-local-navigation__item--cta">

                    <a class="uol-header-local-navigation__link uol-header-local-navigation__link--sub-nav" href="/study/coronavirus-faqs">

                        Coronavirus FAQs

                    </a>

                </li>

                <li class="uol-header-local-navigation__item uol-header-local-navigation__item--cta">

                    <a class="uol-header-local-navigation__link uol-header-local-navigation__link--sub-nav" href="/study/ug-virtual-open-days">

                        Undergraduate virtual open days

                    </a>

                </li>

            </ul>

        </li>

        <li class="uol-header-local-navigation__item " data-label="Research and innovation">

            <a class="uol-header-local-navigation__link" href="/research-innovation">

                Research and innovation

            </a>

        </li>

        <li class="uol-header-local-navigation__item " data-label="Working with business">

            <a class="uol-header-local-navigation__link" href="/working-with-business">

                Working with business

            </a>

        </li>

        <li class="uol-header-local-navigation__item " data-label="Global">

            <a class="uol-header-local-navigation__link" href="/global">

                Global

            </a>

        </li>

        <li class="uol-header-local-navigation__item " data-label="Around campus">

            <a class="uol-header-local-navigation__link" href="/ariund-campus">

                Around campus

            </a>

        </li>

        <li class="uol-header-local-navigation__item " data-label="About">

            <a class="uol-header-local-navigation__link" href="/about">

                About

            </a>

        </li>

    </ul>
</nav>
  • Content:
    // Utility
    .no-wrap {
      white-space: nowrap;
    }
    
    @mixin local-navigation-link-accent {
      &::after {
        content: "";
        position: absolute;
        bottom: 0;
        left: calc(#{$spacing-4} - 2px);
        right: calc(100% - #{$spacing-4} + 2px);
        height: $spacing-2;
        background-color: $color-white;
        transition: right 0.4s ease 0.1s;
      }
    
      &:focus {
        outline: 2px dotted transparent;
      }
    
      &:hover,
      &:focus {
        &::after {
          right: calc(#{$spacing-4} - 2px);
          background-color: $color-brand;
    
          @media (-ms-high-contrast: active),
          (forced-colors: active) {
            background-color: WindowText;
            background-color: CanvasText;
          }
        }
      }
    }
    
    .uol-header-local-navigation-wrapper {
      max-width: 101.75rem;
    
      .no-js & {
        margin: $spacing-4 0;
        padding-bottom: $spacing-4;
      }
    
      .js & {
        position: relative;
        padding-top: $spacing-2;
        padding-bottom: $spacing-2;
        margin-top: 0;
    
        @include media(">=uol-media-l") {
          margin-top: $spacing-6;
          padding-left: $spacing-2;
        }
    
        @include media(">=uol-media-xl") {
          padding-left: $spacing-4;
        }
    
        @include media(">=uol-media-xxl") {
          padding-left: 0;
        }
      }
    }
    
      .uol-header-local-navigation-wrapper--scrollable {
        border-top: 1px solid $color-border--light;
      }
    
      .uol-header-local-navigation-wrapper--sub-expanded {
        @include media("<uol-media-m") {
          padding-bottom: 0;
        }
      }
    
    .uol-header-local-navigation {
    
      .js & {
        margin: 0;
        padding: 0;
        list-style: none;
        display: flex;
        flex-wrap: nowrap;
        overflow-x: auto;
        scroll-snap-type: x proximity;
        -ms-overflow-style: none;
        scrollbar-width: none;
    
        &::-webkit-scrollbar {
            display: none;
        }
      }
    }
    
      .uol-header-local-navigation--scrollable {
        .js & {
          margin-left: $spacing-6;
          margin-right: $spacing-6;
        }
    
        .uol-header-local-navigation-wrapper--sub-expanded & {
          @include media("<uol-media-m") {
            margin-left: 0;
            margin-right: 0;
          }
        }
      }
    
      .uol-header-local-navigation__button-scroll {
        position: absolute;
        top: 0;
        z-index: 1;
        width: $spacing-7;
        height: 100%;
        background: rgba($color-white, 0.96);
        border: none;
        transition: opacity 0.3s ease;
    
        &::after {
          content: "";
          display: block;
          position: absolute;
          top: 50%;
          transform: translateY(-50%);
          width: 0;
          height: 0;
          border: 7px solid transparent;
    
          @media (-ms-high-contrast: active), (forced-colors: active) {
            -ms-high-contrast-adjust: none;
            forced-color-adjust: CanvasText;
          }
        }
    
        &[disabled] {
          // background: none;
          opacity: 0;
          cursor: default;
          z-index: -1;
        }
    
        .uol-header-local-navigation-wrapper--sub-expanded & {
          @include media("<uol-media-m") {
            display: none;
          }
        }
      }
    
        .uol-header-local-navigation__button-scroll--left {
          left: 0;
          border-right: 1px solid $color-border--light;
    
          &::after {
            left: $spacing-3;
            border-right-color: $color-brand--bright;
          }
        }
    
        .uol-header-local-navigation__button-scroll--right {
          right: 0;
          border-left: 1px solid $color-border--light;
    
          &::after {
            right: $spacing-3;
            border-left-color: $color-brand--bright;
          }
        }
    
      .uol-header-local-navigation__item {
        font-weight: $font-weight-bold--sans-serif;
    
        @include media("<uol-media-m") {
          font-weight: 500; // TODO: May need to update font weights
          -webkit-box-sizing: border-box;
          box-sizing: border-box;
        }
    
        .js .uol-header-local-navigation__sub-nav & {
          padding: $spacing-2 $spacing-4;
        }
      }
    
        .uol-header-local-navigation__item--sibling-open {
          @include media("<uol-media-m") {
            position: absolute;
            clip: rect(1px, 1px, 1px, 1px);
            height: 1px;
            width: 1px;
            overflow: hidden;
            left: -9999px;
          }
        }
    
        .uol-header-local-navigation__item--cta {
          .js & {
            background: $color-black;
            margin-left: -1px;
            margin-right: -1px;
            margin-bottom: -1px;
            border: 1px solid $color-black;
    
            @include media(">=uol-media-m") {
              &:last-of-type {
                border-radius: 0 0 $spacing-3 $spacing-3;
              }
            }
          }
    
          .js .uol-header-local-navigation__sub-nav & {
    
            // Add extra spacing to first and last cta (assuming cta is last item)
            margin-top: $spacing-4;
            padding-top: $spacing-5;
            padding-bottom: $spacing-2;
    
            ~ .uol-header-local-navigation__item--cta {
              margin-top: 0;
              padding-top: 0;
            }
    
            &:last-of-type {
              padding-bottom: $spacing-6;
            }
          }
        }
    
      .uol-header-local-navigation__link {
    
        .no-js & {
          // padding: $spacing-1 $spacing-2 $spacing-2;
          &:hover,
          &:focus {
            text-decoration: underline;
          }
        }
    
        .js & {
          @extend %text-size-paragraph;
          @include local-navigation-link-accent();
    
          position: relative;
          display: block;
          color: $color-font--light;
          text-decoration: none;
          white-space: nowrap;
          padding: $spacing-2 $spacing-4 $spacing-3;
          transition: color 0.4s ease 0.1s;
    
          &:hover,
          &:focus {
            color: $color-font--dark;
          }
    
          &[aria-current] {
            color: $color-brand;
          }
        }
    
        .js .uol-header-local-navigation__sub-nav & {
          background: $color-white;
          color: $color-font--light;
          white-space: normal;
          transition: background 0.5s ease;
          border-radius: 6px;
          -webkit-box-sizing: border-box;
          box-sizing: border-box;
    
          &:hover,
          &:focus {
            background-color: $colour-warmgrey—faded;
            color: $color-font;
            text-decoration: underline;
          }
    
          &[aria-current] {
            color: $color-brand;
          }
    
          &::after {
            content: none;
          }
    
          svg {
            position: relative;
            top: 0.35em;
            left: 0;
            margin-left: 0.5em;
            fill: rgba($color-brand, 0);
            transition: all 0.3s ease 0.2s;
          }
    
          &:hover,
          &:focus {
            svg {
              left: 0.4em;
              fill: $color-brand;
    
              @media (-ms-high-contrast: active) {
                fill: windowText;
              }
            }
          }
        }
    
        .js .uol-header-local-navigation__item--cta & {
          background: inherit;
          color: $color-white;
          padding-top: $spacing-1;
          padding-bottom: $spacing-1;
    
          @include media(">=uol-media-m") {
            font-size: 18px;
          }
    
          &:hover,
          &:focus {
            background-color: $color-black--dark;
            color: $color-white;
          }
    
          &[aria-current] {
            color: $color-brand--bright;
          }
    
          svg {
            fill: $color-brand--bright;
    
            @media (-ms-high-contrast: active) {
              fill: windowText;
            }
          }
    
          &:hover,
          &:focus {
            svg {
              left: 0.4em;
              fill: $color-brand--bright;
    
              @media (-ms-high-contrast: active) {
                fill: windowText;
              }
            }
          }
        }
      }
    
      .uol-header-local-navigation__subnav-button {
        @extend %text-size-paragraph;
        @include local-navigation-link-accent();
    
        position: relative;
        font-weight: inherit;
        white-space: nowrap;
        background: transparent;
        border: none;
        margin: 0;
        padding: $spacing-2 $spacing-4 $spacing-3;
        appearance: none;
        color: $color-font--light;
        transition: color 0.4s ease 0.1s;
    
        &[aria-expanded="true"] {
          @include media("<=uol-media-m") {
    
            &:focus {
              text-decoration: underline;
            }
    
            &:focus:not(:focus-visible) {
              text-decoration: none;
    
            }
    
            &:focus-visible {
              outline-color: transparent;
              text-decoration: underline;
              text-underline-offset: 4px;
              text-decoration-thickness: $spacing-2;
              text-decoration-color: $color-brand--bright;
            }
          }
        }
    
        &:focus {
          outline-offset: -4px;
        }
    
        &:hover,
        &:focus {
          color: $color-font--dark;
        }
    
        &[aria-expanded="true"] {
          color: $color-font--dark;
    
          @include media(">=uol-media-m") {
            &::before {
              content: "";
              position: absolute;
              right: 0;
              transform: translateX(-70%);
              bottom: ($spacing-2 - $spacing-1 / 2);
              width: 0;
              height: 0;
              border: ($spacing-3 - $spacing-1 / 2) solid transparent;
              border-top: none;
              border-bottom-color: $color-white;
              filter: drop-shadow(0 -0.05rem 0.05rem rgba($color-black, 0.1));
              z-index: 4;
            }
          }
        }
    
        // TODO: Un-nest icon
        .uol-header-local-navigation__button__icon {
          position: relative;
          display: inline-block;
          width: $spacing-5;
          height: $spacing-4;
          margin-left: 0.2em;
          margin-right: -0.2em;
    
          &::before,
          &::after {
            content: "";
            display: block;
            position: absolute;
            width: 0.5em;
            height: 0.13em;
            background: $color-black;
            bottom: 20%;
    
            @media (-ms-high-contrast: active) {
              background: ButtonText;
            }
          }
    
          &::before {
            left: 50%;
            transform: translateX(-76%) rotate(45deg);
          }
    
          &::after {
            right: 50%;
            transform: translateX(76%) rotate(-45deg);
          }
        }
    
        // TODO: Duplicate selector - refactor
        &[aria-expanded="true"] {
          @include media("<uol-media-m") {
            @include font-size-responsive(1.75rem, 2.25rem, 3rem);
            @include line-height-responsive(2.25rem, 3rem, 3.5rem);
    
            display: block;
            text-align: left;
            width: 100vw;
            border-bottom: 2px solid $color-border--light;
    
            @include media("<uol-media-m") {
              margin-top: -#{$spacing-2};
              padding: 1.312rem $spacing-7 1.312rem $spacing-4;
            }
    
            &::after {
              content: none;
            }
    
            @include media(">=uol-media-m") {
              &::before {
                content: "";
                width: 30px;
                height: 30px;
                background: red;
                position: absolute;
              }
            }
          }
    
          // TODO: Un-nest icon
          .uol-header-local-navigation__button__icon {
    
            &::before {
              transform: translateX(-76%) rotate(315deg);
            }
    
            &::after {
              transform: translateX(76%) rotate(45deg);
            }
    
            @include media("<uol-media-m") {
              position: absolute;
              padding: $spacing-4;
              right: $spacing-3;
              top: 50%;
              transform: translateY(-50%);
    
              &::before {
                bottom: 50%;
              }
    
              &::after {
                bottom: 50%;
              }
            }
          }
        }
      }
    
      .uol-header-local-navigation__sub-nav {
        .js & {
          padding: 0;
          list-style: none;
          display: none;
          box-shadow:
            0 15px 24px 0 rgba(10, 2, 2, 0.15),
            0 5px 10px 0 rgba(33, 33, 33, 0.5),
            0 5px 15px 2px rgba(255, 255, 255, 0.25);
    
          @include media("<uol-media-m") {
            padding-top: $spacing-4;
            background: $color-white;
            width: 100vw;
            overflow-y: auto;
            overflow: hidden;
    
            @media (-ms-high-contrast: active) {
              border-bottom: 1px solid windowText;
            }
          }
    
          @include media(">=uol-media-m") {
            position: absolute;
            top: calc(100% - #{$spacing-4});
            box-sizing: border-box;
            width: 375px;
            background: $color-white;
            border: 1px solid rgba($color-border--light, 0.2);
            border-radius: $spacing-3;
            padding-top: $spacing-1;
            z-index: 3;
            transform: translateX(-#{$spacing-4});
          }
        }
      }
    
  • URL: /components/raw/uol-header-local-navigation/_local-navigation.scss
  • Filesystem Path: src/library/02-components/header-partials/local-navigation/_local-navigation.scss
  • Size: 11.9 KB
  • Content:
    const localNavigations = document.querySelectorAll('.uol-header-local-navigation')
    
    const svgRightArrow = `<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" focusable="false" aria-hidden="true">
      <path d="M0 0h24v24H0z" fill="none"/>
      <path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"/>
    </svg>`
    
    // TODO: Move to utilities
    const getSiblings = (elem) => {
      return Array.prototype.filter.call(elem.parentNode.children, (sibling) => {
        return sibling !== elem
      })
    }
    
    const closestByClass = (elem, classSelector) => {
      // Traverse the DOM up with a while loop
      while (elem.className != classSelector) {
        // Increment the loop to the parent node
        elem = elem.parentNode
        if (!elem) {
          return null
        }
      }
      return elem
    }
    
    export const localNavigationDropdown = () => {
    
      const subNavOpen = (navigation, navBtn, subNav, siblings) => {
        navBtn.setAttribute('aria-expanded', 'true')
        subNav.style.display = 'block'
    
        // Toggle the siblings
        siblings.forEach((sibling) => {
          sibling.classList.add('uol-header-local-navigation__item--sibling-open')
        })
    
        navigation.classList.add('uol-header-local-navigation--sub-expanded')
        navigation.parentNode.classList.add('uol-header-local-navigation-wrapper--sub-expanded')
      }
    
      const subNavClose = (navigation, navBtn, subNav, siblings) => {
        subNav.style.display = 'none'
        navBtn.setAttribute('aria-expanded', 'false')
    
        // Toggle the siblings
        siblings.forEach((sibling) => {
          sibling.classList.remove('uol-header-local-navigation__item--sibling-open')
        })
    
        navigation.classList.remove('uol-header-local-navigation--sub-expanded')
        navigation.parentNode.classList.remove('uol-header-local-navigation-wrapper--sub-expanded')
    
        navigation.dispatchEvent(new CustomEvent('scroll'))
      }
    
      localNavigations.forEach( (navigation) => {
    
        const navItems = navigation.querySelectorAll('.uol-header-local-navigation__item')
    
        navItems.forEach( (navItem) => {
    
          // Scroll items fully into view (exclude sub nav)
          if (!navItem.parentNode.classList.contains('uol-header-local-navigation__sub-nav')) {
            const navLink = navItem.querySelector('.uol-header-local-navigation__link')
            navLink.addEventListener('focus', () => {
              navItem.scrollIntoView({
                behavior: 'smooth',
                block: 'nearest',
                inline: 'start'
              })
            })
          }
    
          const subNav = navItem.querySelector('.uol-header-local-navigation__sub-nav')
          if (subNav) {
    
            const siblings = getSiblings(navItem)
    
            const navLabel = navItem.dataset.label
    
            const subNavItems = subNav.querySelectorAll('.uol-header-local-navigation__item')
            // Hide subNav
            subNav.style.display = 'none'
    
            // Remove text nodes
            navItem.childNodes.forEach( childNode => {
              if (childNode.nodeName === '#text') {
                childNode.remove()
              }
            })
    
            // TODO Add support for top level links
    
            // Add button
            let navBtn = document.createElement('button')
            navBtn.type = 'button'
            navBtn.classList.add('uol-header-local-navigation__subnav-button')
            navBtn.innerHTML = navLabel + '<span class="uol-header-local-navigation__button__icon"></span>'
            navBtn.setAttribute('aria-expanded', false)
    
            navItem.prepend(navBtn)
    
            navBtn.onclick = () => {
              let expanded = navBtn.getAttribute('aria-expanded') === 'true' || false
    
              if (!expanded) {
                subNavOpen(navigation, navBtn, subNav, siblings)
              } else {
                subNavClose(navigation, navBtn, subNav, siblings)
              }
    
            }
    
            // Listen for focusout and close subnav when focus leaves the item's descendants
            navItem.addEventListener('focusout', (event) => {
    
              if (event.relatedTarget) {
                // If the new focused element is not a child of a sub nav
                if (!closestByClass(event.relatedTarget, 'uol-header-local-navigation__sub-nav')) {
    
                  // if not this navigation item's toggle button
                  if(event.relatedTarget.parentNode != navItem) {
                    subNavClose(navigation, navBtn, subNav, siblings)
                  }
    
                }
              }
    
            })
    
            // Close on click outside
    
            document.addEventListener("click", (evt) => {
    
              let targetElement = evt.target; // clicked element
    
              do {
                  if (targetElement == navItem) {
                      // This is a click inside. Do nothing, just return.
                      return;
                  }
                  // Go up the DOM
                  targetElement = targetElement.parentNode;
              } while (targetElement)
    
              // This is a click outside.
              subNavClose(navigation, navBtn, subNav, siblings)
            })
    
            // Close on escape
    
            window.addEventListener("keydown", function(event) {
    
              if (event.key === 'Escape' || event.keyCode === 27) {
                subNavClose(navigation, navBtn, subNav, siblings)
    
                // If focus is on a subnav return focus to parent toggle button
                if (event.target.classList.contains('uol-header-local-navigation__link--sub-nav')) {
                  const parentButton = event.target.closest('.uol-header-local-navigation__item--parent').querySelector('.uol-header-local-navigation__subnav-button')
                  if (parentButton) {
                    parentButton.focus()
                  }
                }
              }
    
            }, true);
    
            // Add arrows to subnav links
            subNavItems.forEach( (item) => {
    
              const itemLink = item.querySelector('.uol-header-local-navigation__link')
    
              // Split text to array
              const innerTextArray = itemLink.innerText.trim().split(' ')
    
              // Wrap last word and svg in no-wrap span to avoid wrapping
              itemLink.innerHTML = innerTextArray.slice(0, -1).join(' ') + ' <span class="no-wrap">' + innerTextArray[innerTextArray.length - 1] + '' + svgRightArrow + '</span>'
            })
    
          }
        })
    
      })
    }
    
    export const localNavigationScrollButtons = () => {
    
      const createScrollableNav = (navigation) => {
        const viewportWidthScroll = window.innerWidth * 0.5
    
        if (!navigation.classList.contains('uol-header-local-navigation--scrollable')) {
          const navParent = navigation.parentNode
    
          // Add class to navigation for JS dependant spacing
          navigation.classList.add('uol-header-local-navigation--scrollable')
          navigation.parentNode.classList.add('uol-header-local-navigation-wrapper--scrollable')
    
          // Create left scroll button
          const btnLeft = document.createElement('button')
          btnLeft.classList.add('uol-header-local-navigation__button-scroll')
          btnLeft.classList.add('uol-header-local-navigation__button-scroll--left')
          btnLeft.disabled = true
          btnLeft.innerHTML = '<span class="hide-accessible">Scroll navigation left</span>'
    
          btnLeft.onclick = () => {
            navigation.scrollBy({
              left: -viewportWidthScroll,
              behavior: 'smooth'
            })
          }
    
          // Create Right scroll button
          const btnRight = document.createElement('button')
          btnRight.classList.add('uol-header-local-navigation__button-scroll')
          btnRight.classList.add('uol-header-local-navigation__button-scroll--right')
          btnRight.innerHTML = '<span class="hide-accessible">Scroll navigation right</span>'
    
          btnRight.onclick = () => {
            navigation.scrollBy({
              left: viewportWidthScroll,
              behavior: 'smooth'
            })
          }
    
          // Prepend/Append scroll buttons
          navParent.prepend(btnLeft)
          navParent.append(btnRight)
    
          // listen for scrolling end and update scroll buttons disabled state
          let navIsScrolling
    
          navigation.addEventListener('scroll', () => {
    
            window.clearTimeout( navIsScrolling )
    
            navIsScrolling = setTimeout(() => {
    
              // The following have a 5px tolerance to support browsers that do not support scroll snapping
    
              // If very near the beginning of scroll
              if (navigation.scrollLeft <= 5) {
                btnLeft.disabled = true
              } else {
                btnLeft.disabled = false
              }
    
              // If very near the end of scroll
              if ((navigation.scrollLeft + navigation.clientWidth) - navigation.scrollWidth >= -5 ) {
                btnRight.disabled = true
              } else {
                btnRight.disabled = false
              }
    
            }, 66)
    
          }, false)
        }
    
    
      }
    
      const destroyScrollableNav = (navigation) => {
    
        // Remove class to navigation for JS dependant spacing
        navigation.classList.remove('uol-header-local-navigation--scrollable')
        navigation.parentNode.classList.remove('uol-header-local-navigation-wrapper--scrollable')
    
        document.querySelectorAll('.uol-header-local-navigation__button-scroll').forEach( (button) => {
          button.remove()
        })
      }
    
      const initiateScrollableNav = () => {
        localNavigations.forEach((navigation) => {
    
          if (navigation.scrollWidth - 10 > navigation.clientWidth) { // TODO fix ipad landscape showing scroller
            createScrollableNav(navigation)
          } else {
            destroyScrollableNav(navigation)
          }
    
        })
      }
    
      // Initialise
    
      document.addEventListener('DOMContentLoaded', function() {
        initiateScrollableNav()
      });
    
      // Fire again on resize
      window.addEventListener('resize', initiateScrollableNav)
    
      // TODO: Hack fix of nav that is just too wide while webfonts load. Need a better solution
      setTimeout(() => {
        if (typeof(Event) === 'function') {
          // modern browsers
          window.dispatchEvent(new Event('resize'));
        } else {
            // for IE and other old browsers
            // causes deprecation warning on modern browsers
            var evt = window.document.createEvent('UIEvents');
            evt.initUIEvent('resize', true, false, window, 0);
            window.dispatchEvent(evt);
        }
      }, 300)
    
    }
    
  • URL: /components/raw/uol-header-local-navigation/local-navigation.module.js
  • Filesystem Path: src/library/02-components/header-partials/local-navigation/local-navigation.module.js
  • Size: 10 KB
{
  "items": [
    {
      "title": "Home",
      "url": "/",
      "current": true
    },
    {
      "title": "Study",
      "items": [
        {
          "title": "Undergraduate",
          "url": "/study/undergraduate"
        },
        {
          "title": "Masters courses",
          "url": "/study/masters"
        },
        {
          "title": "Research degrees",
          "url": "/study/research"
        },
        {
          "title": "International students",
          "url": "/study/international-students"
        },
        {
          "title": "Online courses",
          "url": "/study/online-courses"
        },
        {
          "cta": true,
          "title": "Search courses",
          "url": "/study/courses-search"
        },
        {
          "cta": true,
          "title": "Coronavirus FAQs",
          "url": "/study/coronavirus-faqs"
        },
        {
          "cta": true,
          "title": "Undergraduate virtual open days",
          "url": "/study/ug-virtual-open-days"
        }
      ]
    },
    {
      "title": "Research and innovation",
      "url": "/research-innovation"
    },
    {
      "title": "Working with business",
      "url": "/working-with-business"
    },
    {
      "title": "Global",
      "url": "/global"
    },
    {
      "title": "Around campus",
      "url": "/ariund-campus"
    },
    {
      "title": "About",
      "url": "/about"
    }
  ]
}