Merge remote-tracking branch 'origin/master' into angular-14
This commit is contained in:
commit
f1618b92e8
|
@ -11,6 +11,8 @@ import {IconsModule} from "../../utils/icons/icons.module";
|
|||
import {IconsService} from "../../utils/icons/icons.service";
|
||||
import {graph} from "../../utils/icons/icons";
|
||||
import {BreadcrumbsModule} from "../../utils/breadcrumbs/breadcrumbs.module";
|
||||
import {SliderTabsModule} from "../../sharedComponents/tabs/slider-tabs.module";
|
||||
import {HelperModule} from "../../utils/helper/helper.module";
|
||||
|
||||
@NgModule({
|
||||
declarations: [TerminologyComponent, SeeHowItWorksComponent],
|
||||
|
@ -31,7 +33,7 @@ import {BreadcrumbsModule} from "../../utils/breadcrumbs/breadcrumbs.module";
|
|||
component: SeeHowItWorksComponent,
|
||||
canDeactivate: [PreviousRouteRecorder]
|
||||
},
|
||||
]), PageContentModule, HowModule, TabsModule, IconsModule, BreadcrumbsModule],
|
||||
]), PageContentModule, HowModule, SliderTabsModule, IconsModule, BreadcrumbsModule, SliderTabsModule, HelperModule],
|
||||
exports: [TerminologyComponent, SeeHowItWorksComponent]
|
||||
})
|
||||
export class MethodologyModule {
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
import {ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild} from "@angular/core";
|
||||
import {
|
||||
AfterContentChecked,
|
||||
AfterViewInit,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
ViewChild
|
||||
} from "@angular/core";
|
||||
import {Subscription} from "rxjs";
|
||||
import {Meta, Title} from "@angular/platform-browser";
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
|
@ -6,7 +14,8 @@ import {OpenaireEntities} from "../../utils/properties/searchFields";
|
|||
import {SEOService} from "../../sharedComponents/SEO/SEO.service";
|
||||
import {properties} from "../../../../environments/environment";
|
||||
import {Breadcrumb} from "../../utils/breadcrumbs/breadcrumbs.component";
|
||||
import Timeout = NodeJS.Timeout;
|
||||
import {HelperService} from "../../utils/helper/helper.service";
|
||||
|
||||
|
||||
declare var ResizeObserver;
|
||||
|
||||
|
@ -31,217 +40,37 @@ declare var ResizeObserver;
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-fade; delay: 250">
|
||||
<div *ngIf="divContents" class="uk-section" uk-scrollspy="target: [uk-scrollspy-class]; cls: uk-animation-fade; delay: 250">
|
||||
<div class="uk-section uk-container uk-container-large" uk-scrollspy-class>
|
||||
<div id="parentContainer" class="uk-grid uk-grid-large" uk-grid>
|
||||
<div class="uk-width-1-4@m uk-visible@m">
|
||||
<div class="uk-sticky" uk-sticky="bottom: !#parentContainer; offset: 100;">
|
||||
<ul class="uk-tab uk-tab-left">
|
||||
<li class="uk-margin-small-bottom" [class.uk-active]="activeSection === 'entities'">
|
||||
<a routerLink="./" fragment="entities">1. Entities</a>
|
||||
</li>
|
||||
<li class="uk-margin-small-bottom" [class.uk-active]="activeSection === 'inherited-and-inferred-attributes'">
|
||||
<a routerLink="./" fragment="inherited-and-inferred-attributes">2. Inherited and Inferred Attributes</a>
|
||||
</li>
|
||||
<li class="uk-margin-small-bottom" [class.uk-active]="activeSection === 'constructed-attributes'">
|
||||
<a routerLink="./" fragment="constructed-attributes">3. Constructed Attributes</a>
|
||||
</li>
|
||||
</ul>
|
||||
<slider-tabs type="scrollable" position="left">
|
||||
<slider-tab tabId="entities" tabTitle="1. Entities"></slider-tab>
|
||||
<slider-tab tabId="inherited-and-inferred-attributes" tabTitle="2. Inherited and Inferred Attributes"></slider-tab>
|
||||
<slider-tab tabId="constructed-attributes" tabTitle="3. Constructed Attributes"></slider-tab>
|
||||
</slider-tabs>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-width-1-1 uk-hidden@m">
|
||||
<div class="uk-sticky uk-background-default" uk-sticky>
|
||||
<ul class="uk-tab">
|
||||
<li [class.uk-active]="activeSection === 'entities'">
|
||||
<a routerLink="./" fragment="entities">1. Entities</a>
|
||||
</li>
|
||||
<li [class.uk-active]="activeSection === 'inherited-and-inferred-attributes'">
|
||||
<a routerLink="./" fragment="inherited-and-inferred-attributes">2. Inherited and Inferred Attributes</a>
|
||||
</li>
|
||||
<li [class.uk-active]="activeSection === 'constructed-attributes'">
|
||||
<a routerLink="./" fragment="constructed-attributes">3. Constructed Attributes</a>
|
||||
</li>
|
||||
</ul>
|
||||
<slider-tabs type="scrollable" position="horizontal">
|
||||
<slider-tab tabId="entities" tabTitle="1. Entities"></slider-tab>
|
||||
<slider-tab tabId="inherited-and-inferred-attributes" tabTitle="2. Inherited and Inferred Attributes"></slider-tab>
|
||||
<slider-tab tabId="constructed-attributes" tabTitle="3. Constructed Attributes"></slider-tab>
|
||||
</slider-tabs>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-width-expand@m uk-margin-left">
|
||||
<div class="uk-width-expand@m">
|
||||
<div id="entities" class="uk-margin-large-bottom">
|
||||
<!-- Helptext below here -->
|
||||
<div>
|
||||
<h4>1. Entities</h4>
|
||||
<h6 class="uk-text-primary">Research Products</h6>
|
||||
<div>
|
||||
There are four different types of research products in the
|
||||
OpenAIRE Research Graph:
|
||||
</div>
|
||||
<ul class="uk-list uk-list-bullet uk-list-primary">
|
||||
<li>Publications</li>
|
||||
<li>Research data</li>
|
||||
<li>Research software</li>
|
||||
<li>Other research products.</li>
|
||||
</ul>
|
||||
<div class="uk-margin-small-top">
|
||||
We deduplicate (merge) different records of research products and keep the metadata of all instances.
|
||||
</div>
|
||||
<h6>Publication</h6>
|
||||
<div>
|
||||
Research products intended for human reading (published articles, pre-prints, conference
|
||||
papers, presentations, technical reports, etc.)
|
||||
</div>
|
||||
<h6>Research data</h6>
|
||||
<div>
|
||||
The sources from which the description of the research data has been collected reflect and support their own granularity, we do not define it.
|
||||
</div>
|
||||
<h6>Research software</h6>
|
||||
<div>
|
||||
Source code or software package developed and/or used in a research context
|
||||
</div>
|
||||
<h6>Other research product</h6>
|
||||
<div>
|
||||
Anything that does not fall in the previous categories (e.g. workflow, methods, protocols)
|
||||
</div>
|
||||
</div>
|
||||
<helper [texts]="divContents.entities"></helper>
|
||||
</div>
|
||||
<div id="inherited-and-inferred-attributes" class="uk-margin-large-bottom">
|
||||
<!-- Helptext below here -->
|
||||
<div>
|
||||
<h4>2. Inherited and Inferred Attributes</h4>
|
||||
<div class="uk-margin-medium-top">
|
||||
We either inherit the attributes of entities via entries in the harvested metadata records or automatically generate them using our inference system (text and data mining algorithms).
|
||||
</div>
|
||||
<h6>Organization</h6>
|
||||
<div>
|
||||
<p><span class="uk-text-bold">For research products,</span> this refers to the
|
||||
affiliated organizations of its authors</p>
|
||||
<p><span class="uk-text-bold">For projects:</span>
|
||||
the organizations participating in
|
||||
the project
|
||||
(i.e. beneficiaries of the grant)</p>
|
||||
<p>
|
||||
We are improving the organization database with the use of our <a href="https://orgs.openaire.eu/" target="_blank">OpenOrgs</a> tool. It allows curators to disambiguate organizations (merge different names of the same organization) and identify parent-child relationships (schools, departments, etc.).
|
||||
</p>
|
||||
</div>
|
||||
<h6>Country</h6>
|
||||
<div>
|
||||
<p>The country of the organization.</p>
|
||||
<p>
|
||||
<span class="uk-text-bold">Country code mapping: </span>
|
||||
<a href="https://api.openaire.eu/vocabularies/dnet:countries" target="_blank">
|
||||
https://api.openaire.eu/vocabularies/dnet:countries</a>
|
||||
</p>
|
||||
</div>
|
||||
<h6>Funder</h6>
|
||||
<div>
|
||||
<p>Funders that have joined OpenAIRE, i.e. their project data have
|
||||
gone through a validation process.</p>
|
||||
<p>You can visit <a class="https://explore.openaire.eu/search/find" target="_blank">https://explore.openaire.eu/search/find</a>
|
||||
if you would like to explore the research products
|
||||
and projects of all funders in OpenAIRE (the list of funders can be
|
||||
seen under the "Funder" Filter shown on the left side of the page).</p>
|
||||
<p><span class="uk-text-bold">For funder who want to join OpenAIRE: </span><a
|
||||
href="https://www.openaire.eu/funders-how-to-join-guide" target="_blank">https://www.openaire.eu/funders-how-to-join-guide</a>
|
||||
</p>
|
||||
</div>
|
||||
<h6>Type</h6>
|
||||
<div>
|
||||
<p>The sub-type of a research outcome (e.g.,
|
||||
a publication can be a pre-print, conference proceeding,
|
||||
article,
|
||||
etc.)</p>
|
||||
<p><span class="uk-text-bold">Resource type mapping: </span>
|
||||
<a href="https://api.openaire.eu/vocabularies/dnet:result_typologies" target="_blank">https://api.openaire.eu/vocabularies/dnet:result_typologies</a>
|
||||
(click on the code to see the specific types for each result type)
|
||||
</p>
|
||||
</div>
|
||||
<h6>Access mode or access rights</h6>
|
||||
<div>
|
||||
<p>The best available (across all instances) access rights of
|
||||
a research product</p>
|
||||
<p>Types (by best available):</p>
|
||||
<p><span class="uk-text-bold">Open:</span> Open Access</p>
|
||||
<p><span class="uk-text-bold">Embargo:</span> Closed for a specific period of time, then open.</p>
|
||||
<p><span class="uk-text-bold">Restricted:</span> Definition of restricted may vary by data source, it may refer to access rights being given to registered users, potentially behind a paywall.</p>
|
||||
<p><span class="uk-text-bold">Closed:</span> Closed access</p>
|
||||
</div>
|
||||
<h6>CC license</h6>
|
||||
<div>
|
||||
<p>A Creative Commons copyright license <a href="(https://creativecommons.org/)" target="_blank">(https://creativecommons.org/)</a>
|
||||
</p>
|
||||
</div>
|
||||
<h6>PID (persistent identifier)</h6>
|
||||
<div>
|
||||
<p>A long-lasting reference to a resource</p>
|
||||
<p><span class="uk-text-bold">Types: </span> <a
|
||||
href="http://api.openaire.eu/vocabularies/dnet:pid_types" target="_blank">http://api.openaire.eu/vocabularies/dnet:pid_types</a>
|
||||
</p>
|
||||
</div>
|
||||
<h6>Context</h6>
|
||||
<div>
|
||||
<p>Related research community, initiative or infrastructure.</p>
|
||||
</div>
|
||||
<h6>Journal</h6>
|
||||
<div>
|
||||
<p>The scientific journal an article is published in.</p>
|
||||
</div>
|
||||
<h6>Publisher</h6>
|
||||
<div>
|
||||
<p>The publisher of the venue (journal, book, etc.) of a research product.</p>
|
||||
</div>
|
||||
<h6>Data sources (content providers)</h6>
|
||||
<div>
|
||||
<p>The different data sources ingested in the OpenAIRE Research Graph.</p>
|
||||
<div class="uk-text-bold">Data Source Types:</div>
|
||||
<ul class="uk-list uk-list-disc">
|
||||
<li>Repositories</li>
|
||||
<li>Open Access Publishers & Journals</li>
|
||||
<li>Aggregators</li>
|
||||
<li>Entity Registries</li>
|
||||
<li>Journal Aggregators</li>
|
||||
<li>CRIS (Current Research Information System)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<h6>Repositories</h6>
|
||||
<div>
|
||||
<p>Information systems where scientists upload the bibliographic metadata and payloads of their
|
||||
research products (e.g. PDFs of their scientific articles, CSVs of their data,
|
||||
archive with their
|
||||
software), due to obligations from their organizations, their
|
||||
funders, or due to community practices
|
||||
(e.g. ArXiv, Europe PMC, Zenodo).</p>
|
||||
</div>
|
||||
<h6>Open Access Publishers & Journals</h6>
|
||||
<div>
|
||||
<p>Information systems of open access publishers or relative journals, which offer bibliographic
|
||||
metadata and PDFs of their published articles.</p>
|
||||
</div>
|
||||
<h6>Aggregators</h6>
|
||||
<div>
|
||||
<p>Information systems that collect descriptive metadata about research products
|
||||
from multiple sources
|
||||
in order to enable cross-data source discovery of given research products (e,g,
|
||||
DataCite,
|
||||
BASE, DOAJ).</p>
|
||||
</div>
|
||||
<h6>Entity Registries</h6>
|
||||
<div>
|
||||
<p>Information systems created with the intent of maintaining authoritative registries of given
|
||||
entities in the scholarly communication, such as OpenDOAR for the institutional repositories, re3data
|
||||
for the data repositories, CORDA and other funder databases
|
||||
for projects and funding information.</p>
|
||||
</div>
|
||||
<h6>CRIS (Current Research Information System)</h6>
|
||||
<div>
|
||||
<p>Information systems adopted by research and academic organizations to
|
||||
keep track of their research
|
||||
administration records and relative results; examples of CRIS content are articles
|
||||
or research data funded
|
||||
by projects, their principal investigators, facilities acquired
|
||||
thanks to funding, etc.</p>
|
||||
</div>
|
||||
</div>
|
||||
<helper [texts]="divContents['inherited-and-inferred-attributes']"></helper>
|
||||
</div>
|
||||
<div id="constructed-attributes" class="uk-margin-large-bottom">
|
||||
<!-- Helptext below here -->
|
||||
<helper [texts]="divContents['constructed-attributes']"></helper>
|
||||
<div>
|
||||
<h4>3. Constructed Attributes</h4>
|
||||
<div class="uk-margin-medium-top">
|
||||
|
@ -403,25 +232,26 @@ declare var ResizeObserver;
|
|||
</div>
|
||||
`
|
||||
})
|
||||
export class TerminologyComponent implements OnInit, OnDestroy {
|
||||
export class TerminologyComponent implements OnInit, OnDestroy, AfterViewInit, AfterContentChecked {
|
||||
public tab: 'entities' | 'attributes' = 'entities';
|
||||
private subscriptions: any[] = [];
|
||||
public openaireEntities = OpenaireEntities;
|
||||
public breadcrumbs: Breadcrumb[] = [{name: 'home', route: '/'}, {name: 'Resources - Terminology and construction', keepFormat: true}];
|
||||
public graph_offset: number = 0;
|
||||
public graph_height: number = 0;
|
||||
public graph_offset: number = 0;
|
||||
public graph_height: number = 0;
|
||||
@ViewChild("graph_element") graph_element;
|
||||
public contentSections: string[] = ['entities', 'inherited-and-inferred-attributes', 'constructed-attributes'];
|
||||
public activeSection: string;
|
||||
private observer: IntersectionObserver;
|
||||
private timeout: Timeout;
|
||||
public contentSections: string[] = ['entities', 'inherited-and-inferred-attributes', 'constructed-attributes'];
|
||||
public activeSection: string;
|
||||
public properties = properties;
|
||||
public divContents: any;
|
||||
|
||||
constructor(private seoService: SEOService,
|
||||
private meta: Meta,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private title: Title,
|
||||
private cdr: ChangeDetectorRef) {
|
||||
private cdr: ChangeDetectorRef,
|
||||
private helper: HelperService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@ -432,27 +262,25 @@ export class TerminologyComponent implements OnInit, OnDestroy {
|
|||
this.breadcrumbs[0].route = '/' + (params['stakeholder']?params['stakeholder']:'');
|
||||
this.breadcrumbs[0].name = (params['stakeholder']?'dashboard':'home');
|
||||
}));
|
||||
this.subscriptions.push(this.route.fragment.subscribe(fragment => {
|
||||
if(fragment) {
|
||||
this.activeSection = fragment;
|
||||
} else {
|
||||
this.activeSection = 'entities';
|
||||
}
|
||||
}));
|
||||
this.subscriptions.push(this.route.fragment.subscribe(fragment => {
|
||||
if(fragment) {
|
||||
this.activeSection = fragment;
|
||||
} else {
|
||||
this.activeSection = 'entities';
|
||||
}
|
||||
}));
|
||||
this.getDivContents();
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (typeof document !== 'undefined') {
|
||||
if(this.graph_element) {
|
||||
this.observeGraphElement();
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.setObserver();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterContentChecked() {
|
||||
|
||||
ngAfterContentChecked() {
|
||||
if(this.graph_element && typeof document !== 'undefined') {
|
||||
this.graph_offset = this.calcGraphOffset(this.graph_element.nativeElement);
|
||||
}
|
||||
|
@ -464,37 +292,16 @@ export class TerminologyComponent implements OnInit, OnDestroy {
|
|||
subscription.unsubscribe();
|
||||
}
|
||||
});
|
||||
if(this.observer) {
|
||||
this.observer.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private setObserver() {
|
||||
if(this.observer) {
|
||||
this.observer.disconnect();
|
||||
}
|
||||
this.observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if(entry.isIntersecting) {
|
||||
if(this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
this.timeout = setTimeout(() => {
|
||||
this.router.navigate(['./'], {fragment: entry.target.id, relativeTo: this.route, state: {disableScroll: true}});
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
}, {threshold: 0.25});
|
||||
this.contentSections.forEach(section => {
|
||||
let element = document.getElementById(section);
|
||||
if(element) {
|
||||
this.observer.observe(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public observeGraphElement() {
|
||||
let resizeObs = new ResizeObserver(entries => {
|
||||
|
||||
private getDivContents() {
|
||||
this.subscriptions.push(this.helper.getDivHelpContents(this.properties, 'monitor', this.router.url).subscribe(contents => {
|
||||
this.divContents = contents;
|
||||
}));
|
||||
}
|
||||
|
||||
public observeGraphElement() {
|
||||
let resizeObs = new ResizeObserver(entries => {
|
||||
entries.forEach(entry => {
|
||||
setTimeout(() => {
|
||||
this.graph_offset = this.calcGraphOffset(entry.target);
|
||||
|
@ -504,9 +311,9 @@ export class TerminologyComponent implements OnInit, OnDestroy {
|
|||
});
|
||||
this.subscriptions.push(resizeObs);
|
||||
resizeObs.observe(this.graph_element.nativeElement);
|
||||
}
|
||||
|
||||
calcGraphOffset(element) {
|
||||
}
|
||||
|
||||
calcGraphOffset(element) {
|
||||
this.graph_height = element.offsetHeight;
|
||||
return window.innerHeight-this.graph_height;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import {Component, Input} from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: 'slider-tab',
|
||||
template: ``
|
||||
})
|
||||
export class SliderTabComponent {
|
||||
@Input("tabTitle")
|
||||
public title: string;
|
||||
@Input("tabId")
|
||||
public id: string;
|
||||
@Input()
|
||||
public active: boolean = false;
|
||||
@Input()
|
||||
public disabled: boolean = false;
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ContentChildren,
|
||||
ElementRef, EventEmitter,
|
||||
Input, OnDestroy, Output,
|
||||
QueryList,
|
||||
ViewChild
|
||||
} from "@angular/core";
|
||||
import {SliderTabComponent} from "./slider-tab.component";
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {Subscription} from "rxjs";
|
||||
import Timeout = NodeJS.Timeout;
|
||||
|
||||
declare var UIkit;
|
||||
|
||||
@Component({
|
||||
selector: 'slider-tabs',
|
||||
template: `
|
||||
<div #tabsElement class="uk-position-relative" [class.uk-slider]="position === 'horizontal'"
|
||||
[ngClass]="background">
|
||||
<div [class.uk-slider-container-tabs]="position === 'horizontal'">
|
||||
<ul class="uk-tab" [class.uk-flex-nowrap]="position === 'horizontal'"
|
||||
[class.uk-slider-items]="position === 'horizontal'"
|
||||
[class.uk-tab-left]="position === 'left'" [class.uk-tab-right]="position === 'right'"
|
||||
[attr.uk-tab]="type === 'static'?('connect: .' + connect):null">
|
||||
<ng-container *ngIf="type === 'scrollable'">
|
||||
<li *ngFor="let tab of tabs.toArray()" class="uk-text-capitalize" [class.uk-active]="tab.active">
|
||||
<a routerLink="./" [fragment]="tab.id">{{tab.title}}</a>
|
||||
</li>
|
||||
</ng-container>
|
||||
</ul>
|
||||
</div>
|
||||
<a *ngIf="position === 'horizontal'" class="uk-position-center-left uk-blur-background" uk-slider-item="previous"><span
|
||||
uk-icon="chevron-left"></span></a>
|
||||
<a *ngIf="position === 'horizontal'" class="uk-position-center-right uk-blur-background" uk-slider-item="next"><span
|
||||
uk-icon="chevron-right"></span></a>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class SliderTabsComponent implements AfterViewInit, OnDestroy {
|
||||
//TODO now it works only for scrollable, to be extended
|
||||
/**
|
||||
* Type of tabs: Static = Uikit tabs with @connect class, Dynamic = Active is defined by tabComponent.active input,
|
||||
* Scrollable = Active is defined by the active fragment of URL and position of scroll
|
||||
* */
|
||||
@Input()
|
||||
public type: 'static' | 'dynamic' | 'scrollable' = 'static';
|
||||
/**
|
||||
* Connect class in static type. Default: uk-switcher
|
||||
* */
|
||||
@Input()
|
||||
public connect = 'uk-switcher';
|
||||
/**
|
||||
* Threshold between 0.0 to 1.0 for Intersection Observer
|
||||
* */
|
||||
@Input()
|
||||
public scrollThreshold = 0.1;
|
||||
/**
|
||||
* Tabs view: Horizontal is the default.
|
||||
* */
|
||||
@Input()
|
||||
public position: 'horizontal' | 'left' | 'right' = 'horizontal';
|
||||
/**
|
||||
* Tabs background
|
||||
* */
|
||||
@Input()
|
||||
public background: string;
|
||||
@ContentChildren(SliderTabComponent) tabs: QueryList<SliderTabComponent>;
|
||||
@ViewChild('tabsElement') tabsElement: ElementRef;
|
||||
/**
|
||||
* Notify regarding new active element
|
||||
* */
|
||||
@Output() activeEmitter: EventEmitter<string> = new EventEmitter<string>();
|
||||
public init: boolean = false;
|
||||
private subscriptions: any[] = [];
|
||||
private observer: IntersectionObserver;
|
||||
private timeout: Timeout;
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private cdr: ChangeDetectorRef) {
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (typeof document !== 'undefined' && this.tabs.length > 0) {
|
||||
setTimeout(() => {
|
||||
if(this.position === 'horizontal') {
|
||||
let slider = UIkit.slider(this.tabsElement.nativeElement, {finite: true});
|
||||
slider.clsActive = 'uk-slider-active';
|
||||
slider.updateActiveClasses();
|
||||
this.init = true;
|
||||
slider.slides.forEach(item => {
|
||||
item.classList.remove('uk-active');
|
||||
});
|
||||
if (this.type === 'scrollable') {
|
||||
this.scrollable(slider);
|
||||
}
|
||||
} else {
|
||||
this.scrollable();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private scrollable(slider = null) {
|
||||
this.activeFragment(this.route.snapshot.fragment, slider);
|
||||
this.subscriptions.push(this.route.fragment.subscribe(fragment => {
|
||||
this.activeFragment(fragment,slider);
|
||||
}));
|
||||
this.setObserver();
|
||||
}
|
||||
|
||||
private setObserver() {
|
||||
if (this.observer) {
|
||||
this.observer.disconnect();
|
||||
}
|
||||
this.observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
this.timeout = setTimeout(() => {
|
||||
this.router.navigate(['./'], {
|
||||
fragment: entry.target.id,
|
||||
relativeTo: this.route,
|
||||
state: {disableScroll: true}
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
}, {threshold: 0.1});
|
||||
this.tabs.forEach(tab => {
|
||||
let element = document.getElementById(tab.id);
|
||||
if (element) {
|
||||
this.observer.observe(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private activeFragment(fragment, slider) {
|
||||
let index = 0;
|
||||
if (fragment) {
|
||||
index = this.tabs.toArray().findIndex(item => item.id == fragment);
|
||||
}
|
||||
if(slider) {
|
||||
slider.show(index);
|
||||
}
|
||||
this.tabs.forEach((tab, i) => {
|
||||
if (index === i) {
|
||||
tab.active = true;
|
||||
this.activeEmitter.emit(tab.id);
|
||||
} else {
|
||||
tab.active = false;
|
||||
}
|
||||
});
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach(subscription => {
|
||||
if (subscription instanceof Subscription) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
});
|
||||
if (this.observer) {
|
||||
this.observer.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {SliderTabsComponent} from "./slider-tabs.component";
|
||||
import {SliderTabComponent} from "./slider-tab.component";
|
||||
import {RouterModule} from "@angular/router";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, RouterModule],
|
||||
declarations: [SliderTabsComponent, SliderTabComponent],
|
||||
exports: [SliderTabsComponent, SliderTabComponent]
|
||||
})
|
||||
export class SliderTabsModule {}
|
||||
|
Loading…
Reference in New Issue