<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
}
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 };
.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;
}
}
}
<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>