Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix inpage navigation #88

Merged
merged 3 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 41 additions & 32 deletions blocks/v2-inpage-navigation/v2-inpage-navigation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getMetadata } from '../../scripts/lib-franklin.js';
import { createElement } from '../../scripts/common.js';
import { createElement, debounce } from '../../scripts/common.js';

const blockName = 'v2-inpage-navigation';

Expand Down Expand Up @@ -52,6 +52,29 @@ const inpageNavigationRedButton = () => {
return null;
};

// Retrieve an array of sections with its corresponding intersectionRatio
const wrapSectionItems = (elements) => {
const elementsData = [];
const viewportHeight = window.innerHeight;
elements.forEach((item) => {
const elementRect = item.getBoundingClientRect();

// Calculate the vertical space occupied by the element within the viewport
const verticalSpace = Math.min(elementRect.bottom, viewportHeight)
- Math.max(elementRect.top, 0);

// Calculate the ratio of vertical space to the viewport height
const spaceRatio = verticalSpace / viewportHeight;

elementsData.push({
element: item,
intersectionRatio: Math.max(0, Math.min(1, spaceRatio)),
});
});

return elementsData;
};

const gotoSection = (event) => {
const { target } = event;
const button = target.closest('button');
Expand Down Expand Up @@ -90,35 +113,6 @@ const updateActive = (id) => {
}
};

const listenScroll = () => {
let timeout;
const elements = document.querySelectorAll('main .section');

const io = new IntersectionObserver((entries) => {
// Reduce entries to the one with higher intersectionRatio
const intersectedEntry = entries.reduce((prev, current) => (
prev.intersectionRatio > current.intersectionRatio ? prev : current
));

if (intersectedEntry.isIntersecting && intersectedEntry.target.dataset?.inpageid) {
clearTimeout(timeout);

// wait to update the active item
timeout = setTimeout(() => {
updateActive(intersectedEntry.target.dataset.inpageid);
}, 500);
} else {
updateActive();
}
}, {
threshold: [0.2, 0.5, 0.7, 1],
});

elements.forEach((el) => {
io.observe(el);
});
};

export default async function decorate(block) {
const redButton = inpageNavigationRedButton();

Expand Down Expand Up @@ -180,6 +174,21 @@ export default async function decorate(block) {
}
});

// listen scroll to change the url
listenScroll();
const sectionsList = document.querySelectorAll('main .section');
// listen scroll to change the url + navigation item
window.addEventListener('scroll', debounce(() => {
// Calculate intersectionRatio from all section items
const elementsData = wrapSectionItems(sectionsList);

// Get intersected item that occupies most of the space in the viewport
const intersectedItem = elementsData.reduce((prev, current) => (
prev.intersectionRatio > current.intersectionRatio ? prev : current
));

if (intersectedItem.element.dataset?.inpageid) {
updateActive(intersectedItem.element.dataset.inpageid);
} else {
updateActive();
}
}));
}
14 changes: 14 additions & 0 deletions scripts/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,17 @@ export function checkOneTruckGroup(groupName) {
export function isEloquaFormAllowed() {
return checkOneTruckGroup('C0004');
}

/**
* Helper for delaying a function
* @param {function} func callback function
* @param {number} timeout time to debouce in ms, default 200
*/
export function debounce(func, timeout = 200) {
let timer;
return (...args) => {
clearTimeout(timer);

timer = setTimeout(() => { func.apply(this, args); }, timeout);
};
}
7 changes: 7 additions & 0 deletions styles/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,13 @@ main .section.responsive-title h1 {
/* ICONS STYLES - END */

/* REDESIGN Buttons */
/* stylelint-disable-next-line no-descending-specificity */
.redesign-v2 a.button:any-link,
.redesign-v2 button {
font-weight: normal;
}

/* stylelint-disable-next-line no-descending-specificity */
.redesign-v2 a.button,
.redesign-v2 button.button {
align-items: center;
Expand Down