Change smooth-scroll to check last component instead of Route. Page content sticky base on new uikit version

This commit is contained in:
Konstantinos Triantafyllou 2022-03-14 18:35:00 +02:00
parent c49a79c798
commit 4ccabced6d
3 changed files with 163 additions and 160 deletions

View File

@ -6,26 +6,27 @@ declare var UIkit;
@Component({
selector: '[page-content]',
template: `
<div id="page_content" [class.sticky]="sticky">
<div #header id="page_content_header">
<div class="uk-container uk-container-large uk-padding-remove-vertical">
<ng-content select="[header]"></ng-content>
<div id="page_content">
<div id="header">
<div #header id="page_content_header" uk-sticky="top: #header; media: @m" [attr.offset]="offset">
<div class="uk-container uk-container-large uk-padding-remove-vertical">
<ng-content select="[header]"></ng-content>
</div>
</div>
</div>
<div id="page_content_inner" [class.sticky]="sticky" class="uk-section uk-container uk-container-large">
<div id="page_content_inner" class="uk-section uk-container uk-container-large">
<ng-content select="[inner]"></ng-content>
</div>
</div>
`
`,
})
export class PageContentComponent implements OnInit, OnDestroy {
private current;
private shouldSticky: boolean = false;
public offset: number;
public sticky: boolean = false;
@Output()
public stickyEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
@ViewChild("header") public header: ElementRef;
private current;
private subscriptions: any[] = [];
constructor() {
@ -38,35 +39,33 @@ export class PageContentComponent implements OnInit, OnDestroy {
if (scroll > this.current) {
this.offset = 0;
} else {
this.offset = Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--structure-header-height') + 1);
this.offset = Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--structure-header-height'));
}
if (this.offset !== previous) {
UIkit.sticky(this.header.nativeElement, {
offset: this.offset
});
this.initSticky();
}
this.current = scroll;
if(this.current > this.header.nativeElement.offsetTop + this.header.nativeElement.offsetHeight && this.shouldSticky) {
this.sticky = true;
this.stickyEmitter.emit(this.sticky);
}
}
ngOnInit() {
if (typeof window !== "undefined") {
this.current = window.pageYOffset;
}
}
initSticky() {
this.clear();
this.subscriptions.push(UIkit.util.on(document, 'active', '#page_content_header', (): void => {
this.shouldSticky = true;
this.sticky = true;
this.stickyEmitter.emit(this.sticky);
}));
this.subscriptions.push(UIkit.util.on(document, 'inactive', '#page_content_header', (): void => {
this.sticky = false;
this.shouldSticky = false;
this.stickyEmitter.emit(this.sticky);
}));
}
ngOnDestroy() {
clear() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) {
subscription.unsubscribe();
@ -75,4 +74,8 @@ export class PageContentComponent implements OnInit, OnDestroy {
}
});
}
ngOnDestroy() {
this.clear();
}
}

View File

@ -92,148 +92,149 @@
</div>
</div>
</div>
<div class="uk-visible@m">
<div class="uk-navbar-transparent" [ngClass]="portal + '-menu'"
uk-sticky="show-on-up: true" media="@m" cls-active="uk-active uk-navbar-sticky"
cls-inactive="uk-navbar-transparent"
<div id="main-menu" class="uk-visible@m">
<div class="uk-navbar-container" [ngClass]="portal + '-menu'"
uk-sticky="show-on-up: true; top: #main-menu" media="@m" cls-active="uk-active uk-navbar-sticky"
[attr.animation]="(header.stickyAnimation?'uk-animation-slide-top':null)">
<div
*ngIf="(properties.environment =='beta' || properties.environment =='development') && showLogo && header.badge">
<img class="uk-position-top-left"
[src]="'assets/common-assets/'+(properties.environment =='beta'?'beta_flag.svg':'prototype_flag.svg')"
alt="BETA" style="height: 100px; width: 100px; z-index: 1000">
alt="BETA" style="height: 65px; width: 65px; z-index: 1000">
</div>
<nav class="uk-navbar uk-flex uk-navbar-container uk-padding-large uk-padding-remove-vertical" uk-navbar>
<ng-container *ngIf="!onlyTop">
<div class="uk-navbar-left">
<ng-container *ngIf="showLogo && isHeaderLeft">
<ng-container *ngTemplateOutlet="header_template; context: {mobile: false}"></ng-container>
</ng-container>
</div>
<div class="uk-navbar-center">
<ng-container *ngIf="showLogo && !isHeaderLeft">
<ng-container *ngTemplateOutlet="header_template; context: {mobile: false}"></ng-container>
</ng-container>
<ng-container *ngIf="!header.menuPosition || header.menuPosition === 'center'">
<ng-container *ngTemplateOutlet="mainMenu"></ng-container>
</ng-container>
</div>
<div class="uk-navbar-right">
<ng-container *ngIf="header.menuPosition === 'right'">
<ng-container *ngTemplateOutlet="mainMenu"></ng-container>
</ng-container>
<user-mini *ngIf="userMenu" [user]="user" [dark]="dark"
[userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl [logOutUrl]=properties.logoutUrl
[cookieDomain]=properties.cookieDomain></user-mini>
<ng-content select="[extra-m]"></ng-content>
</div>
<ng-template #mainMenu>
<ul class="uk-navbar-nav" [class.uk-margin-right]="!userMenu">
<li class="uk-parent" *ngIf="showHomeMenuItem && currentRoute.route !== '/'">
<a routerLink="/">Home</a>
</li>
<ng-container *ngFor="let menu of menuItems">
<li class="uk-parent" [class.uk-active]="isTheActiveMenu(menu)"
*ngIf="isAtleastOneEnabled(menu.rootItem.entitiesRequired,showEntity) && isAtleastOneEnabled(menu.rootItem.routeRequired, showPage)">
<!--a routerLink="{{menu.rootItem.route}}" [queryParams]=menu.rootItem.params class="" aria-expanded="false">{{menu.rootItem.title}}</a-->
<a *ngIf="menu.rootItem.route.length > 0 && (isEnabled([menu.rootItem.route], showPage) || !menu.rootItem.routeRequired )"
routerLink="{{menu.rootItem.route}}"
[queryParams]="menu.rootItem.params"
[fragment]="menu.rootItem.fragment"> {{menu.rootItem.title}}</a>
<a *ngIf="menu.rootItem.route.length == 0 && menu.rootItem.url.length > 0"
href="{{menu.rootItem.url}}" target="{{menu.rootItem.url.includes('http') ? '_blank' : '_self'}}"
aria-expanded="false">{{menu.rootItem.title}}</a>
<a *ngIf="(menu.rootItem.route.length == 0 && menu.rootItem.url.length == 0) || ( menu.rootItem.route.length >0 && menu.rootItem.routeRequired && !isEnabled([menu.rootItem.route], showPage) && isAtleastOneEnabled(menu.rootItem.routeRequired, showPage))">{{menu.rootItem.title}}</a>
<div *ngIf="menu.items.length > 0" class="uk-navbar-dropdown" uk-drop="pos: bottom-left">
<div class="uk-height-max-medium uk-overflow-auto">
<ul class="uk-nav uk-navbar-dropdown-nav">
<ng-container *ngFor="let submenu of menu.items">
<li *ngIf="isEnabled(submenu.entitiesRequired,showEntity) &&
isEnabled(submenu.routeRequired, showPage) && (submenu.route.length > 0 ||
submenu.url.length > 0)" [class.uk-active]="isTheActiveMenuItem(submenu)"
[class.uk-parent]="submenu.items && submenu.items.length > 0">
<a *ngIf="submenu.route.length > 0"
routerLink="{{submenu.route}}" [queryParams]="submenu.params"
[fragment]="submenu.fragment">{{submenu.title}}</a>
<a *ngIf="submenu.route.length == 0 && submenu.url.length > 0"
href="{{submenu.url}}"
target="{{submenu.url.includes('http') ? '_blank' : '_self'}}">{{submenu.title}}</a>
<ul *ngIf="submenu.items && submenu.items.length > 0" class="uk-nav-sub">
<ng-container *ngFor="let subsubmenu of submenu.items">
<li>
<a *ngIf="subsubmenu.route.length > 0"
routerLink="{{subsubmenu.route}}" [queryParams]="subsubmenu.params"
[fragment]="subsubmenu.fragment">{{subsubmenu.title}}</a>
<a *ngIf="subsubmenu.route.length == 0 && subsubmenu.url.length > 0"
href="{{subsubmenu.url}}" target="_blank">{{subsubmenu.title}}</a>
</li>
</ng-container>
</ul>
<li *ngIf="submenu.route.length == 0 && submenu.url.length == 0 && isEnabled(submenu.entitiesRequired,showEntity) && isEnabled(submenu.routeRequired, showPage)"
class="uk-nav-header">{{submenu.title}}</li>
</ng-container>
</ul>
</div>
</div>
</li>
<div class="uk-container uk-container-expand">
<nav class="uk-navbar" uk-navbar>
<ng-container *ngIf="!onlyTop">
<div class="uk-navbar-left">
<ng-container *ngIf="showLogo && isHeaderLeft">
<ng-container *ngTemplateOutlet="header_template; context: {mobile: false}"></ng-container>
</ng-container>
<!-- Custom menu items -->
<!-- TODO: Add to mobile menu as well! -->
<ng-container *ngIf="additionalMenuItems?.length > 0 && properties.environment == 'development'">
<ng-container *ngFor="let menu of additionalMenuItems">
<li class="uk-parent">
<!-- INTERNAL ROOT-->
<a *ngIf="menu.type == 'internal' && menu.route && isEnabled([menu.route], showPage)"
routerLink="{{menu.route}}"
[queryParams]="menu.params"
[fragment]="menu.fragment">
{{menu.title}}
</a>
<!-- EXTERNAL ROOT-->
<a *ngIf="menu.type == 'external' && menu.url"
href="{{menu.url}}"
target="_blank">
{{menu.title}}
</a>
<!-- NO ACTION ROOT-->
<a *ngIf="menu.type == 'noAction'">
{{menu.title}}
</a>
<div *ngIf="menu.items.length > 0" class="uk-navbar-dropdown uk-navbar-dropdown-bottom-left"
style="top: 80px; left: 0px;" id="{{menu._id}}" uk-toggle>
<div class="uk-navbar-dropdown-grid uk-child-width-1-1 uk-grid uk-grid-stack" uk-grid="">
<div class="uk-first-column uk-height-max-medium uk-overflow-auto">
<ul class="uk-nav uk-navbar-dropdown-nav">
<ng-container *ngFor="let submenu of menu.items">
<li>
<!-- INTERNAL CHILD -->
<a *ngIf="submenu.type == 'internal' && submenu.route && isEnabled([submenu.route], showPage)"
routerLink="{{submenu.route}}"
[queryParams]="submenu.params"
[fragment]="submenu.fragment"
[class.uk-active]="isTheActiveMenuItem(submenu)">
{{submenu.title}}
</a>
<!-- EXTERNAL CHILD -->
<a *ngIf="submenu.type == 'external' && submenu.url"
href="{{submenu.url}}"
target="_blank">
{{submenu.title}}
</a>
</li>
</ng-container>
</ul>
</div>
</div>
<div class="uk-navbar-center">
<ng-container *ngIf="showLogo && !isHeaderLeft">
<ng-container *ngTemplateOutlet="header_template; context: {mobile: false}"></ng-container>
</ng-container>
<ng-container *ngIf="!header.menuPosition || header.menuPosition === 'center'">
<ng-container *ngTemplateOutlet="mainMenu"></ng-container>
</ng-container>
</div>
<div class="uk-navbar-right">
<ng-container *ngIf="header.menuPosition === 'right'">
<ng-container *ngTemplateOutlet="mainMenu"></ng-container>
</ng-container>
<user-mini *ngIf="userMenu" [user]="user" [dark]="dark"
[userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl [logOutUrl]=properties.logoutUrl
[cookieDomain]=properties.cookieDomain></user-mini>
<ng-content select="[extra-m]"></ng-content>
</div>
<ng-template #mainMenu>
<ul class="uk-navbar-nav" [class.uk-margin-right]="!userMenu">
<li class="uk-parent" *ngIf="showHomeMenuItem && currentRoute.route !== '/'">
<a routerLink="/">Home</a>
</li>
<ng-container *ngFor="let menu of menuItems">
<li class="uk-parent" [class.uk-active]="isTheActiveMenu(menu)"
*ngIf="isAtleastOneEnabled(menu.rootItem.entitiesRequired,showEntity) && isAtleastOneEnabled(menu.rootItem.routeRequired, showPage)">
<!--a routerLink="{{menu.rootItem.route}}" [queryParams]=menu.rootItem.params class="" aria-expanded="false">{{menu.rootItem.title}}</a-->
<a *ngIf="menu.rootItem.route.length > 0 && (isEnabled([menu.rootItem.route], showPage) || !menu.rootItem.routeRequired )"
routerLink="{{menu.rootItem.route}}"
[queryParams]="menu.rootItem.params"
[fragment]="menu.rootItem.fragment"> {{menu.rootItem.title}}</a>
<a *ngIf="menu.rootItem.route.length == 0 && menu.rootItem.url.length > 0"
href="{{menu.rootItem.url}}" target="{{menu.rootItem.url.includes('http') ? '_blank' : '_self'}}"
aria-expanded="false">{{menu.rootItem.title}}</a>
<a *ngIf="(menu.rootItem.route.length == 0 && menu.rootItem.url.length == 0) || ( menu.rootItem.route.length >0 && menu.rootItem.routeRequired && !isEnabled([menu.rootItem.route], showPage) && isAtleastOneEnabled(menu.rootItem.routeRequired, showPage))">{{menu.rootItem.title}}</a>
<div *ngIf="menu.items.length > 0" class="uk-navbar-dropdown" uk-drop="pos: bottom-left">
<div class="uk-height-max-medium uk-overflow-auto">
<ul class="uk-nav uk-navbar-dropdown-nav">
<ng-container *ngFor="let submenu of menu.items">
<li *ngIf="isEnabled(submenu.entitiesRequired,showEntity) &&
isEnabled(submenu.routeRequired, showPage) && (submenu.route.length > 0 ||
submenu.url.length > 0)" [class.uk-active]="isTheActiveMenuItem(submenu)"
[class.uk-parent]="submenu.items && submenu.items.length > 0">
<a *ngIf="submenu.route.length > 0"
routerLink="{{submenu.route}}" [queryParams]="submenu.params"
[fragment]="submenu.fragment">{{submenu.title}}</a>
<a *ngIf="submenu.route.length == 0 && submenu.url.length > 0"
href="{{submenu.url}}"
target="{{submenu.url.includes('http') ? '_blank' : '_self'}}">{{submenu.title}}</a>
<ul *ngIf="submenu.items && submenu.items.length > 0" class="uk-nav-sub">
<ng-container *ngFor="let subsubmenu of submenu.items">
<li>
<a *ngIf="subsubmenu.route.length > 0"
routerLink="{{subsubmenu.route}}" [queryParams]="subsubmenu.params"
[fragment]="subsubmenu.fragment">{{subsubmenu.title}}</a>
<a *ngIf="subsubmenu.route.length == 0 && subsubmenu.url.length > 0"
href="{{subsubmenu.url}}" target="_blank">{{subsubmenu.title}}</a>
</li>
</ng-container>
</ul>
<li *ngIf="submenu.route.length == 0 && submenu.url.length == 0 && isEnabled(submenu.entitiesRequired,showEntity) && isEnabled(submenu.routeRequired, showPage)"
class="uk-nav-header">{{submenu.title}}</li>
</ng-container>
</ul>
</div>
</div>
</li>
</ng-container>
</ng-container>
</ul>
</ng-template>
</ng-container>
</nav>
<!-- Custom menu items -->
<!-- TODO: Add to mobile menu as well! -->
<ng-container *ngIf="additionalMenuItems?.length > 0 && properties.environment == 'development'">
<ng-container *ngFor="let menu of additionalMenuItems">
<li class="uk-parent">
<!-- INTERNAL ROOT-->
<a *ngIf="menu.type == 'internal' && menu.route && isEnabled([menu.route], showPage)"
routerLink="{{menu.route}}"
[queryParams]="menu.params"
[fragment]="menu.fragment">
{{menu.title}}
</a>
<!-- EXTERNAL ROOT-->
<a *ngIf="menu.type == 'external' && menu.url"
href="{{menu.url}}"
target="_blank">
{{menu.title}}
</a>
<!-- NO ACTION ROOT-->
<a *ngIf="menu.type == 'noAction'">
{{menu.title}}
</a>
<div *ngIf="menu.items.length > 0" class="uk-navbar-dropdown uk-navbar-dropdown-bottom-left"
style="top: 80px; left: 0px;" id="{{menu._id}}" uk-toggle>
<div class="uk-navbar-dropdown-grid uk-child-width-1-1 uk-grid uk-grid-stack" uk-grid="">
<div class="uk-first-column uk-height-max-medium uk-overflow-auto">
<ul class="uk-nav uk-navbar-dropdown-nav">
<ng-container *ngFor="let submenu of menu.items">
<li>
<!-- INTERNAL CHILD -->
<a *ngIf="submenu.type == 'internal' && submenu.route && isEnabled([submenu.route], showPage)"
routerLink="{{submenu.route}}"
[queryParams]="submenu.params"
[fragment]="submenu.fragment"
[class.uk-active]="isTheActiveMenuItem(submenu)">
{{submenu.title}}
</a>
<!-- EXTERNAL CHILD -->
<a *ngIf="submenu.type == 'external' && submenu.url"
href="{{submenu.url}}"
target="_blank">
{{submenu.title}}
</a>
</li>
</ng-container>
</ul>
</div>
</div>
</div>
</li>
</ng-container>
</ng-container>
</ul>
</ng-template>
</ng-container>
</nav>
</div>
</div>
<!-- New navbar for featured menu items - test only -->
<ng-container *ngIf="featuredMenuItems?.length > 0 && properties.environment == 'development'">

View File

@ -1,4 +1,4 @@
import {NavigationEnd, Router} from '@angular/router';
import {ActivationStart, NavigationEnd, Router} from '@angular/router';
import {Injectable} from '@angular/core';
import {Subscription} from 'rxjs';
@ -8,17 +8,20 @@ import {Subscription} from 'rxjs';
export class SmoothScroll {
private interval;
private readonly sub;
private lastRoute;
private lastComponent;
private currentComponent: any;
constructor(private router: Router) {
if(typeof window !== "undefined") {
if (typeof window !== "undefined") {
this.sub = router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
if (event instanceof ActivationStart) {
this.currentComponent = event.snapshot.component;
} else if (event instanceof NavigationEnd) {
if (this.interval) {
clearInterval(this.interval);
}
const fragment = router.parseUrl(router.url).fragment;
if (this.lastRoute !== this.getUrl(event.url)) {
if (this.lastComponent !== this.currentComponent) {
window.scrollTo({top: 0});
}
if (fragment) {
@ -49,16 +52,12 @@ export class SmoothScroll {
} else {
window.scrollTo({top: 0, behavior: 'smooth'});
}
this.lastRoute = this.getUrl(event.url);
this.lastComponent = this.currentComponent;
}
});
}
}
private getUrl(url: string) {
return url.split('?')[0].split('#')[0];
}
public clearSubscriptions() {
if (this.sub && this.sub instanceof Subscription) {
this.sub.unsubscribe();