<div data-behaviour="efl-filter-bar" class="efl-filter-bar--container">
    <div class="efl-filter-bar">
        <div class="efl-filter-bar__inner">
            <div class="efl-filter-bar__inner--show-hide" role="button" tabindex="0" aria-label="show filters" aria-controls="efl-index-left-filter">Show Filters</div>
            <div class="efl-filter-bar__inner__show-more--button-prev" role="button" tabindex="0" aria-label="show previous filters"></div>
            <div class="efl-filter-bar__inner--tags-scroll">
                <ul class="efl-filter-bar__inner--tags">
                </ul>
            </div>
            <div class="efl-filter-bar__inner__show-more">
                <div class="efl-filter-bar__inner__show-more--indicator"></div>
                <div class="efl-filter-bar__inner__show-more--button-next" role="button" tabindex="0" aria-label="show more filters"></div>
            </div>
            <div class="efl-filter-bar__inner--session">
                Showing <span id="how-many-sessions"></span> <span id="filter-bar-type">Courses</span>
            </div>
            <div aria-controls="efl-index-left-filter" class="efl-filter-bar__inner--close" role="button" tabindex="0" aria-label="close filter">+</div>
        </div>
    </div>
</div>

No notes defined.

{
  "courses": true,
  "article": true
}
  • Content:
    const MOBILE_BREAKPOINT = 820;
    
    // Find the position of the given element
    const findPos = obj => {
      // eslint-disable-next-line no-unused-vars
      let curleft = 0;
      let curtop = 0;
    
      if (obj.offsetParent) {
        curleft = obj.offsetLeft;
        curtop = obj.offsetTop;
    
        // eslint-disable-next-line no-param-reassign, no-cond-assign
        while ((obj = obj.offsetParent)) {
          curleft += obj.offsetLeft;
          curtop += obj.offsetTop;
        }
      }
      return curtop;
    };
    
    const detectScrollDirection = () => {
      const footer = document.querySelector('.footer-section');
      const fixedHeaderElement = document.querySelector('.global-fixed-header');
    
      const stopPoint = findPos(footer);
      let scrollingUp = true;
    
      // Make the top adjustments if in range between filter and footer page position,
      // unless in mobile dimensions
      if (window.scrollY < stopPoint || window.innerWidth < MOBILE_BREAKPOINT) {
        // Scrolling down (at least 20px)
        if (
          fixedHeaderElement.style.top === '0px' ||
          fixedHeaderElement.style.top === null
        ) {
          scrollingUp = fixedHeaderElement.offsetHeight;
          // Scroll up (at least 20px)
        } else {
          scrollingUp = undefined;
        }
      }
    
      return scrollingUp;
    };
    
    export default parentElement => {
      let defaultWidth = window.innerWidth;
      const footer = document.querySelector('.footer-section');
      const sideFilter = document.querySelector('.efl-index-left-filter');
      const sideFilterScroll = document.querySelector(
        '.efl-index-left-filter--scroll'
      );
      const sideFilterContainer = document.querySelector(
        '.efl-index-left-filter--container'
      );
      const ctaContainer = sideFilter.querySelector('.efl-index-left-filter--cta');
    
      const toggleFilterButton = parentElement.querySelector(
        '.efl-filter-bar__inner--show-hide'
      );
      const closeFilterButton = parentElement.querySelector(
        '.efl-filter-bar__inner--close'
      );
      const howManyIndicator = parentElement.querySelector(
        '.efl-filter-bar__inner--session'
      );
      const container = parentElement;
      const self = parentElement.firstElementChild;
      // const filterTags = parentElement.querySelectorAll('ul li');
      const fixedHeaderElement = document.querySelector('.global-fixed-header');
      const { filterType } = document.querySelector(
        '[data-behaviour="efl-index-left-filter"]'
      ).dataset;
    
      let headerIsHidden = false;
    
      if (MOBILE_BREAKPOINT <= window.innerWidth) {
        headerIsHidden = true;
      }
    
      function selectedcardcount() {
        const divselectedcount = document.querySelectorAll('.efl-card');
        const cardCount = document.querySelector('#how-many-sessions');
        const filterBarType = document.querySelector('#filter-bar-type');
        const cardselectedCount = [].slice.call(divselectedcount);
        const cardactiveCount = cardselectedCount.filter(el => {
          return !el.classList.contains('hidden');
        });
    
        cardCount.innerText = cardactiveCount.length;
        filterBarType.innerText = filterType;
      }
    
      selectedcardcount();
    
      const calibrateFilterBarSize = () => {
        container.style.minHeight = `${self.clientHeight}px`;
      };
    
      const formatFilterButtonText = () => {
        if (window.innerWidth < MOBILE_BREAKPOINT) {
          toggleFilterButton.textContent = 'Filters';
          toggleFilterButton.setAttribute('aria-label', 'Filters');
        } else {
          // eslint-disable-next-line no-lonely-if
          if (toggleFilterButton.getAttribute('aria-expanded') === 'true') {
            toggleFilterButton.textContent = 'Hide Filters';
          } else {
            toggleFilterButton.textContent = 'Show Filters';
          }
    
          if (toggleFilterButton.getAttribute('aria-expanded') === 'true') {
            toggleFilterButton.setAttribute('aria-label', 'Hide Filters');
          } else {
            toggleFilterButton.setAttribute('aria-label', 'Show Filters');
          }
        }
      };
    
      // let { pageYOffset: prevScrollPos } = window;
      //   const { offsetHeight: headerEleHt } = fixedHeaderElement;
      //   const headerEleHeight =
      //     window.innerWidth <= MOBILE_BREAKPOINT ? 105 : headerEleHt;
      //     const minScrollDistance = window.innerWidth <= MOBILE_BREAKPOINT ? 10 : 20;
    
      const footerScreenHeight = () => {
        const pageHeight = document.body.offsetHeight + 115;
        const footerHeight = footer.offsetHeight;
    
        let calculatedValue =
          window.scrollY + window.innerHeight - (pageHeight - footerHeight);
    
        if (calculatedValue < 0) {
          calculatedValue = 0;
        }
    
        return calculatedValue;
      };
    
      const adjustFilterTopPosition = () => {
        headerIsHidden = detectScrollDirection();
    
        // Mobile filter to always cover full screen, scroll rules dont apply
        if (
          MOBILE_BREAKPOINT > window.innerWidth &&
          toggleFilterButton.getAttribute('aria-expanded') === 'true'
        ) {
          self.style.top = null;
          sideFilter.style.top = `${self.offsetHeight - 1}px`;
          return null;
        }
    
        if (!headerIsHidden) {
          self.style.top = null;
          if (window.innerWidth >= MOBILE_BREAKPOINT) {
            sideFilter.style.top = `${self.offsetHeight}px`;
            sideFilterScroll.style.maxHeight = `${window.innerHeight -
              (ctaContainer.offsetHeight +
                self.offsetHeight +
                footerScreenHeight()) -
              22}px`;
            ctaContainer.style.top = `${self.offsetHeight +
              sideFilterScroll.offsetHeight +
              20}px`;
          }
        } else if (window.innerWidth >= MOBILE_BREAKPOINT) {
          sideFilter.style.top = `${fixedHeaderElement.offsetHeight +
            self.offsetHeight}px`;
          sideFilterScroll.style.maxHeight = `${window.innerHeight -
            (fixedHeaderElement.offsetHeight +
              self.offsetHeight +
              ctaContainer.offsetHeight +
              footerScreenHeight()) -
            26}px`;
          ctaContainer.style.top = `${fixedHeaderElement.offsetHeight +
            self.offsetHeight +
            sideFilter.offsetHeight -
            2}px`;
          self.style.top = `${fixedHeaderElement.offsetHeight}px`;
        } else {
          self.style.top = `${fixedHeaderElement.offsetHeight}px`;
        }
    
        return null;
      };
    
      // Initialise the behaviour
      const init = () => {
        // Set maximum width of the filter bar
        self.style.maxWidth = `${window.innerWidth}px`;
    
        // Cancel out styles when resizing
        sideFilter.removeAttribute('style');
        if (window.innerWidth >= MOBILE_BREAKPOINT) {
          toggleFilterButton.setAttribute('aria-expanded', 'true');
        } else {
          toggleFilterButton.setAttribute('aria-expanded', 'false');
          sideFilter.style.display = 'none';
        }
        calibrateFilterBarSize();
        formatFilterButtonText();
        setTimeout(adjustFilterTopPosition, 300);
      };
    
      // Hide filter bar when open navigation
      const hamburger = document.querySelector('[aria-controls="main-nav"]');
    
      hamburger.addEventListener('click', () => {
        const stickyFilterBar = document.querySelector('.efl-filter-bar.sticky');
        const openNavigation = document.querySelector(
          '.global-site-header .hamburger'
        );
    
        if (stickyFilterBar) {
          setTimeout(() => {
            if (openNavigation.getAttribute('aria-expanded') === 'true') {
              stickyFilterBar.style.zIndex = '99';
            } else if (openNavigation.getAttribute('aria-expanded') === 'false') {
              stickyFilterBar.style.zIndex = '';
            }
          }, 100);
        }
      });
    
      if (MOBILE_BREAKPOINT <= window.innerWidth) {
        init();
      } else {
        window.addEventListener('load', init);
      }
    
      window.addEventListener('resize', () => {
        if (defaultWidth !== window.innerWidth) {
          init();
          defaultWidth = window.innerWidth;
        }
      });
    
      closeFilterButton.addEventListener('click', event => {
        const selfButton = event.target;
    
        event.preventDefault();
    
        if (window.scrollY < findPos(container)) {
          self.classList.remove('sticky');
        }
        document.body.style.overflow = null;
        toggleFilterButton.setAttribute('aria-expanded', 'false');
        self.classList.remove('opened');
        selfButton.setAttribute('aria-expanded', 'false');
        sideFilter.style.display = null;
        setTimeout(() => {
          sideFilter.style.top = null;
        }, 300);
        closeFilterButton.style.display = null;
        howManyIndicator.style.display = null;
        // Re-enable scroll for the background when filter is up.
        document.body.style.overflow = null;
        setTimeout(adjustFilterTopPosition, 300);
      });
    
      toggleFilterButton.addEventListener('click', event => {
        event.preventDefault();
    
        const selfButton = event.target;
    
        if (window.innerWidth >= MOBILE_BREAKPOINT) {
          if (selfButton.getAttribute('aria-expanded') === 'true') {
            selfButton.setAttribute('aria-expanded', 'false');
            // tagCloud.style.display = 'none';
            sideFilter.style.maxWidth = '0px';
            sideFilter.tabIndex = '-1';
            sideFilter.style.marginLeft = null;
            sideFilterContainer.style.maxWidth = '0';
            ctaContainer.style.display = 'none';
            setTimeout(() => {
              sideFilter.style.display = 'none';
            }, 300);
          } else {
            sideFilter.style.display = null;
            setTimeout(() => {
              if (window.scrollY > findPos(container) + self.clientHeight) {
                sideFilterContainer.style.maxWidth = null;
              }
              selfButton.setAttribute('aria-expanded', 'true');
              // tagCloud.style.display = null;
              sideFilter.style.maxWidth = null;
              sideFilterContainer.style.maxWidth = null;
              sideFilter.tabIndex = '0';
              formatFilterButtonText();
            }, 100);
            // delay the cta after animation
            setTimeout(() => {
              ctaContainer.style.display = null;
            }, 300);
          }
        } else {
          // eslint-disable-next-line no-lonely-if
          if (selfButton.getAttribute('aria-expanded') === 'true') {
            if (window.scrollY < findPos(container)) {
              self.classList.remove('sticky');
            }
            self.classList.remove('opened');
            selfButton.setAttribute('aria-expanded', 'false');
            sideFilter.style.display = null;
            setTimeout(() => {
              sideFilter.style.top = null;
            }, 300);
            closeFilterButton.style.display = null;
            howManyIndicator.style.display = null;
            // Re-enable scroll for the background when filter is up.
            document.body.style.overflow = null;
          } else {
            self.classList.add('sticky');
            self.classList.add('opened');
            selfButton.setAttribute('aria-expanded', 'true');
            sideFilter.style.display = 'block';
    
            self.style.transition = `none`;
            self.style.top = `${window.innerHeight - self.clientHeight}px`;
            setTimeout(() => {
              self.style.transition = null;
              if (headerIsHidden) {
                self.style.top = `${fixedHeaderElement.clientHeight}px`;
                sideFilter.style.top = `${self.clientHeight +
                  fixedHeaderElement.clientHeight}px`;
              } else {
                self.style.top = null;
                sideFilter.style.top = `${self.clientHeight}px`;
              }
            }, 300);
            closeFilterButton.style.display = 'flex';
            howManyIndicator.style.display = 'none';
            // Disable scroll for the background when filter is up.
            document.body.style.overflow = 'hidden';
          }
        }
        formatFilterButtonText();
        // Run function after animation
        setTimeout(adjustFilterTopPosition, 300);
      });
    
      // eslint-disable-next-line complexity
      const stickyBehaviourOnScroll = () => {
        if (window.innerWidth >= MOBILE_BREAKPOINT) {
          if (
            (window.scrollY > findPos(container) && !headerIsHidden) ||
            (window.scrollY + 114 > findPos(container) && headerIsHidden)
          ) {
            self.classList.add('sticky');
    
            // // hide the left filter when scrolling down to footer
            // if (window.scrollY + window.innerHeight > findPos(footer)) {
            //   sideFilter.classList.add('hidden');
            // } else {
            //   sideFilter.classList.remove('hidden');
            // }
    
            // undo expanding side filter and shrink index
            sideFilter.classList.add('sticky');
            if (toggleFilterButton.getAttribute('aria-expanded') === 'true') {
              sideFilterContainer.style.maxWidth = null;
            }
          } else {
            self.classList.remove('sticky');
    
            // expand side filter and shrink index
            sideFilter.classList.remove('sticky');
            if (toggleFilterButton.getAttribute('aria-expanded') === 'true') {
              sideFilterContainer.style.maxWidth = null;
            } else {
              sideFilterContainer.style.maxWidth = '0px';
            }
          }
        } else {
          // eslint-disable-next-line no-lonely-if
          if (
            window.scrollY > findPos(container) ||
            toggleFilterButton.getAttribute('aria-expanded') === 'true'
          ) {
            self.classList.add('sticky');
          } else {
            self.classList.remove('sticky');
          }
        }
      };
    
      window.addEventListener('scroll', () => {
        stickyBehaviourOnScroll();
        detectScrollDirection();
        setTimeout(adjustFilterTopPosition, 300);
      });
    };
    
    export { detectScrollDirection, findPos };
    
  • URL: /components/raw/efl-filter-bar/efl-filter-bar.js
  • Filesystem Path: src/library/components/efl-filter-bar/efl-filter-bar.js
  • Size: 13.1 KB
  • Content:
    .efl-filter-bar {
      display: flex;
      align-items: center;
      justify-content: space-between;
      background-color: $white;
      transition: top 0.4s ease-in-out 0s;
      min-height: 8.2rem;
    
      &--container {
        background-color: $white;
    
        + .efl-index-layout {
          margin-top: 0 !important;
        }
      }
    
      &.sticky {
        border-top: 0.1rem solid $grey-light;
        box-shadow: 0 0.8rem 0.8rem rgba(91, 104, 133, 0.36);
        position: fixed;
        background-color: white;
        z-index: 117;
        top: 0;
        left: 0;
        width: 100%;
      }
    
      &__inner {
        display: grid;
        grid-template-columns: 1fr 1fr;
        grid-auto-rows: auto;
        grid-template-areas:
          'a c'
          'b b';
        padding: 1.6rem 0;
        width: 100%;
    
        &--show-hide {
          display: flex;
          align-items: center;
          grid-area: a;
          font-family: $text-font-ef;
          font-style: normal;
          font-weight: 700;
          font-size: 1.6rem;
          line-height: 2rem;
          letter-spacing: 0.06em;
          text-transform: uppercase;
          text-decoration: none;
          margin-left: 3.2rem;
          color: $blue;
          flex-shrink: 0;
          cursor: pointer;
          &::before {
            content: '';
            display: inline-block;
            background-image: url('./assets/images/show-filters.svg');
            width: 2.4rem;
            height: 1.573rem;
            margin-right: 1rem;
          }
        }
        &--tags-scroll {
          margin-top: 1.6rem;
          overflow-x: auto;
          height: 3.8rem;
          overflow-y: hidden;
          grid-area: b;
          ::-webkit-scrollbar {
            width: 1px;
          }
        }
    
        &__show-more {
          display: none;
          padding: 0 1.6rem;
          gap: 1.6rem;
    
          &--indicator {
            display: flex;
            font-family: $text-font-ef;
            font-size: 1.6rem;
            line-height: 2.4rem;
            letter-spacing: -0.01em;
            background-color: $grey-light;
            color: $color-interface-light;
            justify-content: center;
            align-items: center;
            padding: 0.7rem 1.6rem;
            border-radius: 5rem;
            gap: 1rem;
            white-space: nowrap;
            text-transform: uppercase;
          }
          &--button-next,
          &--button-prev {
            display: flex;
            justify-content: center;
            align-items: center;
            width: 3.4rem;
            height: 3.4rem;
            min-width: 3.4rem;
            background: url('./assets/images/filterbar-tag-arrow.svg') center center
              no-repeat;
            border-radius: 50%;
            text-decoration: none;
            cursor: pointer;
          }
          &--button-prev {
            transform: rotate(180deg);
          }
        }
    
        &--tags {
          display: flex;
          gap: 1.6rem;
          overflow-x: auto;
          text-decoration: none;
          list-style-type: none;
          white-space: nowrap;
          padding: 0;
          margin: 0;
          overflow-y: hidden;
          min-height: 3.8rem;
          scroll-snap-type: x mandatory;
    
          li {
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: $text-font-ef;
            font-size: 1.6rem;
            line-height: 2.4rem;
            letter-spacing: -0.01em;
            background-color: $grey-light;
            color: $color-interface-light;
            padding: 0.7rem 1.6rem;
            border-radius: 5rem;
            gap: 1rem;
            padding-right: 1rem;
            scroll-snap-align: start;
    
            &:first-child {
              margin-left: 3.2rem;
            }
    
            &:last-child {
              margin-right: 3.2rem;
            }
    
            .close-tag {
              display: flex;
              font-size: 3rem;
              justify-content: center;
              align-items: center;
              transform: rotate(45deg);
              text-decoration: none;
              color: white;
              width: 2.4rem;
              height: 2.4rem;
              background-color: $color-interface-light;
              padding-bottom: 0.2rem;
              border-radius: 50%;
              overflow: hidden;
              cursor: pointer;
            }
          }
        }
    
        &--session {
          display: flex;
          justify-content: end;
          color: $blue;
          text-align: right;
          grid-area: c;
          text-transform: uppercase;
          font-family: $text-font-ef;
          font-size: 1.2rem;
          font-weight: 400;
          line-height: 2rem;
          letter-spacing: 0.06em;
          margin-right: 3.2rem;
          flex-shrink: 0;
    
          span {
            line-height: 2rem;
    
            &:nth-of-type(1) {
              margin: 0 0.5rem;
            }
          }
        }
    
        &--close {
          top: 2.4rem;
          right: 0;
          position: absolute;
          display: none;
          margin-left: auto;
          margin-right: 3.2rem;
          text-decoration: none;
          border-radius: 100%;
          font-size: 3rem;
          font-weight: 700;
          transform: rotate(45deg);
          color: black;
          justify-content: center;
          align-items: center;
          border: 0.2rem solid $light-blue;
          width: 3.2rem;
          height: 3.2rem;
          overflow: hidden;
          cursor: pointer;
        }
      }
    
      &.opened {
        box-shadow: none;
        .efl-filter-bar__inner--show-hide {
          margin-top: 2rem;
        }
        .efl-filter-bar__inner--tags-scroll {
          display: none;
        }
        .efl-filter-bar__inner--close {
          display: flex;
        }
        &::after {
          content: '';
          display: block;
          padding: 0 3.2rem;
          position: absolute;
          bottom: 0;
          left: 3.2rem;
          width: calc(100% - 6.4rem);
          height: auto;
          border-bottom: 0.1rem solid $grey-light;
        }
      }
    
      @media screen and (min-width: $mq-medium) {
        display: flex;
        padding: 2.2rem calc(50vw - 63.7rem);
    
        &__inner {
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding: 0 3.2rem;
    
          &--tags {
            li {
              &:first-child {
                margin-left: 0;
              }
            }
          }
    
          &--tags-scroll {
            max-width: calc(100% - 503px);
            margin-top: 0;
          }
    
          &__show-more {
            display: flex;
          }
    
          &--show-hide {
            padding-right: 4rem;
            &[aria-expanded='true'] {
              min-width: 25rem;
            }
    
            margin-left: 0;
          }
    
          &--close {
            display: none;
          }
    
          &--session {
            display: flex;
            justify-content: end;
            margin-right: 0;
            font-size: 1.6rem;
            flex-grow: 1;
    
            span {
              &:nth-of-type(1) {
                margin: 0 0.2rem;
              }
            }
          }
        }
    
        &.sticky {
          border-top: none;
          z-index: 17;
        }
      }
    }
    
  • URL: /components/raw/efl-filter-bar/efl-filter-bar.scss
  • Filesystem Path: src/library/components/efl-filter-bar/efl-filter-bar.scss
  • Size: 6.4 KB
<div data-behaviour="efl-filter-bar" class="efl-filter-bar--container">
  <div class="efl-filter-bar">
    <div class="efl-filter-bar__inner">
      <div class="efl-filter-bar__inner--show-hide" role="button" tabindex="0" aria-label="show filters" aria-controls="efl-index-left-filter">Show Filters</div>
      <div class="efl-filter-bar__inner__show-more--button-prev" role="button" tabindex="0" aria-label="show previous filters"></div>
      <div class="efl-filter-bar__inner--tags-scroll">
        <ul class="efl-filter-bar__inner--tags">
        </ul>
      </div>
      <div class="efl-filter-bar__inner__show-more">
        <div class="efl-filter-bar__inner__show-more--indicator"></div>
        <div class="efl-filter-bar__inner__show-more--button-next" role="button" tabindex="0" aria-label="show more filters"></div>
      </div>
      <div class="efl-filter-bar__inner--session">
        Showing <span id="how-many-sessions"></span> <span id="filter-bar-type">{{#if sessions}}Sessions{{/if}}{{#if articles}}Articles{{/if}}{{#if courses}}Courses{{/if}}</span>
      </div>
      <div aria-controls="efl-index-left-filter" class="efl-filter-bar__inner--close" role="button" tabindex="0" aria-label="close filter">+</div>
    </div>
  </div>
</div>