2019-10-15 16:25:43 +02:00
|
|
|
import { DOCUMENT } from '@angular/common';
|
2020-09-16 17:19:29 +02:00
|
|
|
import { Component, EventEmitter, Inject, OnInit, Output, Input } from '@angular/core';
|
2019-12-11 15:51:03 +01:00
|
|
|
import { BaseComponent } from '@common/base/base.component';
|
2019-10-22 14:46:48 +02:00
|
|
|
import { interval, Subject, Subscription } from 'rxjs';
|
|
|
|
import { distinctUntilChanged } from 'rxjs/operators';
|
2020-09-16 17:19:29 +02:00
|
|
|
import { type } from 'os';
|
2019-10-15 16:25:43 +02:00
|
|
|
|
|
|
|
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;
|
2020-09-16 17:19:29 +02:00
|
|
|
show: boolean;
|
|
|
|
selected: boolean;
|
2019-10-15 16:25:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
selector: 'table-of-contents',
|
|
|
|
styleUrls: ['./table-of-contents.scss'],
|
|
|
|
templateUrl: './table-of-contents.html'
|
|
|
|
})
|
2019-10-22 14:46:48 +02:00
|
|
|
export class TableOfContents extends BaseComponent implements OnInit {
|
2019-10-15 16:25:43 +02:00
|
|
|
|
2019-10-22 14:46:48 +02:00
|
|
|
links: Link[] = [];
|
|
|
|
container: string;
|
|
|
|
headerSelectors = '.toc-page-header, .toc-section-header, .toc-copositeField-header';
|
2019-10-15 16:25:43 +02:00
|
|
|
@Output() stepFound = new EventEmitter<LinkToScroll>();
|
2019-10-22 14:46:48 +02:00
|
|
|
subscription: Subscription;
|
|
|
|
linksSubject: Subject<HTMLElement[]> = new Subject<HTMLElement[]>();
|
2019-10-15 16:25:43 +02:00
|
|
|
|
2020-09-16 17:19:29 +02:00
|
|
|
@Input() isActive: boolean;
|
|
|
|
show: boolean = false;
|
|
|
|
|
2019-10-22 14:46:48 +02:00
|
|
|
constructor(
|
2019-10-15 16:25:43 +02:00
|
|
|
@Inject(DOCUMENT) private _document: Document) {
|
2019-12-11 15:51:03 +01:00
|
|
|
super();
|
2019-10-15 16:25:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-22 14:46:48 +02:00
|
|
|
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);
|
2019-10-15 16:25:43 +02:00
|
|
|
});
|
|
|
|
|
2019-10-22 14:46:48 +02:00
|
|
|
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;
|
2020-09-16 17:19:29 +02:00
|
|
|
let show
|
2019-10-22 14:46:48 +02:00
|
|
|
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;
|
2020-09-16 17:19:29 +02:00
|
|
|
show = true;
|
2019-10-22 14:46:48 +02:00
|
|
|
} 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;
|
2020-09-16 17:19:29 +02:00
|
|
|
show = false;
|
2019-10-22 14:46:48 +02:00
|
|
|
} 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;
|
2020-09-16 17:19:29 +02:00
|
|
|
show = false;
|
2019-10-22 14:46:48 +02:00
|
|
|
}
|
|
|
|
const { top } = header.getBoundingClientRect();
|
|
|
|
links.push({
|
|
|
|
name,
|
|
|
|
id,
|
|
|
|
type: header.tagName.toLowerCase(),
|
|
|
|
top: top,
|
|
|
|
active: false,
|
|
|
|
page: page,
|
2020-09-16 17:19:29 +02:00
|
|
|
section: section,
|
|
|
|
show: show,
|
|
|
|
selected: false
|
2019-10-22 14:46:48 +02:00
|
|
|
});
|
|
|
|
}
|
2019-10-15 16:25:43 +02:00
|
|
|
}
|
2019-10-22 14:46:48 +02:00
|
|
|
this.links = links;
|
2020-09-16 17:19:29 +02:00
|
|
|
// Initialize selected for button next on dataset wizard component editor
|
2020-09-17 17:48:13 +02:00
|
|
|
this.links.length > 0 ? this.links[0].selected = true : null;
|
2019-10-22 14:46:48 +02:00
|
|
|
})
|
2019-10-15 16:25:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
goToStep(link: Link) {
|
2019-10-22 14:46:48 +02:00
|
|
|
// this.selectedLinkId = link.id;
|
2019-10-15 16:25:43 +02:00
|
|
|
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);
|
|
|
|
}
|
2019-10-22 14:46:48 +02:00
|
|
|
}, 500);
|
2019-10-15 16:25:43 +02:00
|
|
|
}
|
|
|
|
|
2020-09-16 17:19:29 +02:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
2019-10-15 16:25:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface LinkToScroll {
|
|
|
|
page: number;
|
|
|
|
section: number;
|
|
|
|
}
|