argos/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.ts

151 lines
4.0 KiB
TypeScript

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';
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 {
links: Link[] = [];
container: string;
headerSelectors = '.toc-page-header, .toc-section-header, .toc-copositeField-header';
@Output() stepFound = new EventEmitter<LinkToScroll>();
subscription: Subscription;
linksSubject: Subject<HTMLElement[]> = new Subject<HTMLElement[]>();
@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);
});
this.linksSubject.asObservable()
.pipe(distinctUntilChanged((p: HTMLElement[], q: HTMLElement[]) => JSON.stringify(p) == JSON.stringify(q)))
.subscribe(headers => {
const links: Array<Link> = [];
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')) {
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;
show = false;
} else if (header.classList.contains('toc-copositeField-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;
})
}
goToStep(link: Link) {
// this.selectedLinkId = link.id;
this.stepFound.emit({
page: link.page,
section: link.section
});
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 page = +headerLink.id.split("_", 2)[1];
let innerPage;
for (const link of this.links) {
link.selected = false;
if (link.type === 'mat-expansion-panel') {
innerPage = +link.name.split(" ",1)[0];
} else if (link.type === 'h5') {
innerPage = +link.name.split(".",1)[0];
}
if (page + 1 === innerPage && link.type !== 'span') {
link.show = !link.show;
}
}
headerLink.selected = true;
}
getIndex(link: Link): number {
return +link.id.split("_", 2)[1];
}
}
export interface LinkToScroll {
page: number;
section: number;
}