You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Components/TScripts/mudScrollSpy.js

110 lines
3.4 KiB

2 years ago
// Copyright (c) MudBlazor 2021
// MudBlazor licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//Functions related to the scroll spy
class MudScrollSpy {
constructor() {
this.scrollToSectionRequested = null;
this.lastKnowElement = null;
//needed as variable to remove the event listeners
this.handlerRef = null;
}
// subscribe to relevant events
spying(dotnetReference, selector) {
this.scrollToSectionRequested = null;
this.lastKnowElement = null;
this.handlerRef = this.handleScroll.bind(this, selector, dotnetReference);
// add the event for scroll. In case of zooming this event is also fired
document.addEventListener('scroll', this.handlerRef, true);
// a window resize could change the size of the relevant viewport
window.addEventListener('resize', this.handlerRef, true);
}
// handle the document scroll event and if needed, fires the .NET event
handleScroll(dotnetReference, selector, event) {
const elements = document.getElementsByClassName(selector);
if (elements.length === 0) {
return;
}
const center = window.innerHeight / 2.0;
let minDifference = Number.MAX_SAFE_INTEGER;
let elementId = '';
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const rect = element.getBoundingClientRect();
const diff = Math.abs(rect.top - center);
if (diff < minDifference) {
minDifference = diff;
elementId = element.id;
}
}
if (document.getElementById(elementId).getBoundingClientRect().top < window.innerHeight * 0.8 === false) {
return;
}
if (this.scrollToSectionRequested != null) {
if (this.scrollToSectionRequested == ' ' && window.scrollY == 0) {
this.scrollToSectionRequested = null;
}
else {
if (elementId === this.scrollToSectionRequested) {
this.scrollToSectionRequested = null;
}
}
return;
}
if (elementId != this.lastKnowElement) {
this.lastKnowElement = elementId;
history.replaceState(null, '', window.location.pathname + "#" + elementId);
dotnetReference.invokeMethodAsync('SectionChangeOccured', elementId);
}
}
activateSection(sectionId) {
const element = document.getElementById(sectionId);
if (element) {
this.lastKnowElement = sectionId;
history.replaceState(null, '', window.location.pathname + "#" + sectionId);
}
}
scrollToSection(sectionId) {
if (sectionId) {
let element = document.getElementById(sectionId);
if (element) {
this.scrollToSectionRequested = sectionId;
element.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'start' });
}
}
else {
window.scrollTo({ top: 0, behavior: 'smooth' });
this.scrollToSectionRequested = ' ';
}
}
//remove event listeners
unspy() {
document.removeEventListener('scroll', this.handlerRef, true);
window.removeEventListener('resize', this.handlerRef, true);
}
};
window.mudScrollSpy = new MudScrollSpy();