ng-scroll-spy
Version:
Angular directive that tracking the scrolling of the document and highlight the navigation link
122 lines (117 loc) • 4.93 kB
JavaScript
import * as i0 from '@angular/core';
import { Directive, Inject, HostListener, NgModule } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { extractElementPosition } from 'ng-html-util';
import { polyfill } from 'smoothscroll-polyfill';
class ScrollSpyDirective {
constructor(document, el, renderer) {
this.document = document;
this.el = el;
this.renderer = renderer;
this.elements = [];
this.directNavigation = false;
}
ngAfterContentInit() {
this.collectIds();
}
collectIds() {
this.elements = [];
let elements = this.el.nativeElement.querySelectorAll('a');
for (let i = 0; i < elements.length; i++) {
let elem = elements.item(i);
let id = ScrollSpyDirective.getId(elem);
if (!id)
continue;
let destination = this._getPeerElement(id);
if (!destination)
continue;
elem.addEventListener('click', this._onLinkClicked.bind(this));
this.elements.push({
id,
link: elem,
destination
});
}
}
_onLinkClicked(event) {
event.preventDefault();
let target = event.currentTarget;
let id = ScrollSpyDirective.getId(target);
let destination = this._getPeerElement(id);
this.directNavigation = true;
let position = extractElementPosition(this.document, destination);
window.scrollTo({ top: position.top - 25, left: 0, behavior: 'smooth' });
this._cleanCurrentLink();
this._setCurrentLink(target);
this.directNavigation = false;
}
_getPeerElement(id) {
let destination = this.document.getElementById(id);
if (!destination)
return null;
return destination;
}
static getId(elem) {
let href = elem.getAttribute('href');
if (!href)
return null;
return href.replace('#', '');
}
onWindowScroll(event) {
if (this.directNavigation)
return;
for (let elem of this.elements) {
let top = elem.destination.getBoundingClientRect().top;
if (top > 0 && top < 25) {
this._cleanCurrentLink();
this._setCurrentLink(elem.link);
break;
}
}
}
_cleanCurrentLink() {
if (!this.currentActiveLink)
return;
this.renderer.removeClass(this.currentActiveLink, 'active');
}
_setCurrentLink(elem) {
this.currentActiveLink = elem;
this.renderer.addClass(this.currentActiveLink, 'active');
}
}
ScrollSpyDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: ScrollSpyDirective, deps: [{ token: DOCUMENT }, { token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
ScrollSpyDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.0", type: ScrollSpyDirective, selector: "[scroll-spy]", host: { listeners: { "window:scroll": "onWindowScroll($event)" } }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: ScrollSpyDirective, decorators: [{
type: Directive,
args: [{
selector: '[scroll-spy]'
}]
}], ctorParameters: function () {
return [{ type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: i0.ElementRef }, { type: i0.Renderer2 }];
}, propDecorators: { onWindowScroll: [{
type: HostListener,
args: ["window:scroll", ['$event']]
}] } });
class ScrollSpyModule {
constructor() {
polyfill();
}
}
ScrollSpyModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: ScrollSpyModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
ScrollSpyModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: ScrollSpyModule, declarations: [ScrollSpyDirective], exports: [ScrollSpyDirective] });
ScrollSpyModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: ScrollSpyModule });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: ScrollSpyModule, decorators: [{
type: NgModule,
args: [{
declarations: [ScrollSpyDirective],
exports: [ScrollSpyDirective]
}]
}], ctorParameters: function () { return []; } });
/**
* Generated bundle index. Do not edit.
*/
export { ScrollSpyDirective, ScrollSpyModule };
//# sourceMappingURL=ng-scroll-spy.mjs.map