import { DOCUMENT } from '@angular/common'; import { Component, EventEmitter, Inject, OnInit, Output, Input } from '@angular/core'; import { BaseComponent } from '@common/base/base.component'; import { interval, Subject, Subscription } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; import { type } from 'os'; import { SimpleChanges } from '@angular/core'; export interface Link { /* id of the section*/ id: string; /* header type h3/h4 */ type: string; /* If the anchor is in view of the page */ active: boolean; /* name of the anchor */ name: string; /* top offset px of the anchor */ top: number; page: number; section: number; show: boolean; selected: boolean; } @Component({ selector: 'table-of-contents', styleUrls: ['./table-of-contents.scss'], templateUrl: './table-of-contents.html' }) export class TableOfContents extends BaseComponent implements OnInit { @Input() links: Link[]; container: string; headerSelectors = '.toc-page-header, .toc-section-header, .toc-compositeField-header'; @Output() stepFound = new EventEmitter(); @Output() currentLinks = new EventEmitter(); subscription: Subscription; linksSubject: Subject = new Subject(); @Input() isActive: boolean; show: boolean = false; constructor( @Inject(DOCUMENT) private _document: Document) { super(); } ngOnInit(): void { //emit value every 500ms const source = interval(500); this.subscription = source.subscribe(val => { const headers = Array.from(this._document.querySelectorAll(this.headerSelectors)) as HTMLElement[]; this.linksSubject.next(headers); }); if (!this.links || this.links.length === 0) { this.linksSubject.asObservable() .pipe(distinctUntilChanged((p: HTMLElement[], q: HTMLElement[]) => JSON.stringify(p) == JSON.stringify(q))) .subscribe(headers => { const links: Array = []; if (headers.length) { let page; let section; let show for (const header of headers) { let name; let id; if (header.classList.contains('toc-page-header')) { // deprecated after removing stepper name = header.innerText.trim().replace(/^link/, ''); id = header.id; page = header.id.split('_')[1]; section = undefined; show = true; } else if (header.classList.contains('toc-section-header')) { name = header.childNodes[0].childNodes[0].childNodes[0].childNodes[0].childNodes[0].nodeValue.trim().replace(/^link/, ''); id = header.id; page = header.id.split('.')[1]; section = header.id; if (header.id.split('.')[4]) { show = false; } else { show = true; } } else if (header.classList.contains('toc-compositeField-header')) { name = (header.childNodes[0]).nodeValue.trim().replace(/^link/, ''); id = header.id; // id = header.parentElement.parentElement.parentElement.id; show = false; } const { top } = header.getBoundingClientRect(); links.push({ name, id, type: header.tagName.toLowerCase(), top: top, active: false, page: page, section: section, show: show, selected: false }); } } this.links = links; // Initialize selected for button next on dataset wizard component editor this.links.length > 0 ? this.links[0].selected = true : null; }) } } ngOnChanges(changes: SimpleChanges) { // if (!this.isActive && this.links && this.links.length > 0) { // this.links.forEach(link => { // link.selected = false; // }) // this.links[0].selected = true; // } } goToStep(link: Link) { this.stepFound.emit({ page: link.page, section: link.section }); this.currentLinks.emit(this.links); setTimeout(() => { const target = document.getElementById(link.id); target.scrollIntoView(true); var scrolledY = window.scrollY; if (scrolledY) { window.scroll(0, scrolledY - 70); } }, 500); } toggle(headerLink: Link) { const headerPage = +headerLink.name.split(" ", 1); let innerPage; for (const link of this.links) { link.selected = false; if (link.type === 'mat-expansion-panel') { innerPage = +link.name.split(".", 1)[0]; if (isNaN(innerPage)) { innerPage = +link.name.split(" ", 1) } } else if (link.type === 'h5') { innerPage = +link.name.split(".", 1)[0]; } if (headerPage === innerPage && (link.type !== 'mat-expansion-panel' || (link.type === 'mat-expansion-panel' && link.id.split(".")[4]))) { link.show = !link.show; } } headerLink.selected = true; } // getIndex(link: Link): number { // return +link.id.split("_", 2)[1]; // } } export interface LinkToScroll { page: number; section: number; }