Untitled
unknown
typescript
2 years ago
5.4 kB
17
Indexable
import { ElementRef, Injectable, Renderer2, RendererFactory2 } from '@angular/core';
import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ResponsivityService {
private initState: boolean = false;
private renderer: Renderer2;
originalElement: ElementRef;
children: ElementRef[] = [];
savedChildren: ElementRef[] = [];
savedBurgerChildren: ElementRef[] = [];
noResponsiveElements: ElementRef[] = [];
burgerChildren: ElementRef[] = [];
burgerElement: ElementRef = null;
burgerWidth: number = 0;
burgerHidden: boolean = true;
reserveConstant: number = 15;
constructor(rendererFactory: RendererFactory2) {
this.renderer = rendererFactory.createRenderer(null, null);
}
initResponsivity(headerElement: ElementRef, children: ElementRef[], burgerChildren: ElementRef[], noResponsiveElements: ElementRef[], burgerElement: ElementRef): void {
if (!this.initState) {
this.settingInitialValues(headerElement, children, burgerChildren, noResponsiveElements, burgerElement);
this.saveChildrenReferences();
this.checkElementVisibility();
this.checkWindowResize();
this.initState = true;
}
}
checkElementVisibility(): void {
this.showAllChildren();
this.hideAllBurgerChildren();
const childrenToHide = this.getChildrenToHide();
this.hideChildren(childrenToHide);
this.showBurgerChildren(childrenToHide);
}
private settingInitialValues(headerElement: ElementRef, children: ElementRef[], burgerChildren: ElementRef[], noResponsiveElements: ElementRef[], burgerElement: ElementRef): void {
this.originalElement = headerElement;
this.children = children;
this.burgerChildren = burgerChildren;
this.noResponsiveElements = noResponsiveElements;
this.burgerElement = burgerElement;
}
private checkWindowResize(): void {
fromEvent(window, 'resize').pipe(
debounceTime(300)
).subscribe((event: Event) => {
this.checkElementVisibility();
});
}
private cloneElement(element: ElementRef): ElementRef {
const clonedElement = element.nativeElement.cloneNode(true);
return new ElementRef(clonedElement);
}
private saveChildrenReferences(): void {
this.children.forEach((child: ElementRef) => {
this.savedChildren.push(this.cloneElement(child));
});
this.burgerChildren.forEach((child: ElementRef) => {
this.savedBurgerChildren.push(this.cloneElement(child));
});
}
private getParentWidth(): number {
this.burgerWidth = this.burgerElement.nativeElement.offsetWidth;
let noResponsiveChildrenWidth = 0;
this.noResponsiveElements.forEach((noResponsiveElement: ElementRef) => {
noResponsiveChildrenWidth += noResponsiveElement.nativeElement.offsetWidth;
});
return this.originalElement.nativeElement.getBoundingClientRect().width - noResponsiveChildrenWidth - this.burgerWidth - this.reserveConstant;
}
private getChildrenToHide(): ElementRef[] {
const elementsToHide = [];
const parentWidth = this.getParentWidth();
let totalChildrenWidth = 0;
for (let i = 0; i < this.children.length; i++) {
const child = this.children[i];
totalChildrenWidth += child.nativeElement.offsetWidth;
if (totalChildrenWidth > parentWidth) {
elementsToHide.push(child.nativeElement.nodeName.toLowerCase());
}
}
return elementsToHide;
}
private hideChildren(elementsToHide: ElementRef[]): void {
if (elementsToHide.length > 0) {
elementsToHide.forEach(elementId => {
const element = this.children.find(child => child.nativeElement.nodeName.toLowerCase() === elementId);
if (element) {
element.nativeElement.style.display = 'none';
}
});
this.setVisibilityOfBurger(true);
} else {
this.setVisibilityOfBurger(false);
}
}
private showAllChildren(): void {
this.children.forEach((element: ElementRef) => {
const savedElement = this.savedChildren.find(child => child.nativeElement.nodeName.toLowerCase() === element.nativeElement.nodeName.toLowerCase());
if (element) {
element.nativeElement.style.display = savedElement.nativeElement.style.display;
}
});
}
private hideAllBurgerChildren(): void {
this.burgerChildren.forEach((element: ElementRef) => {
if (element) {
element.nativeElement.style.display = 'none';
}
});
}
private showBurgerChildren(elementsToShow: ElementRef[]): void {
if (elementsToShow.length > 0) {
elementsToShow.forEach(elementId => {
const element = this.burgerChildren.find(child => child.nativeElement.nodeName.toLowerCase() === elementId);
const savedElement = this.savedBurgerChildren.find(child => child.nativeElement.nodeName.toLowerCase() === elementId);
if (element) {
element.nativeElement.style.display = savedElement.nativeElement.style.display;
}
});
}
}
private setVisibilityOfBurger(show: boolean): void {
if (show) {
this.burgerElement.nativeElement.style.setProperty('display', 'flex', 'important');
this.burgerHidden = false;
} else {
this.burgerElement.nativeElement.style.setProperty('display', 'none', 'important');
this.burgerHidden = true;
}
}
}
Editor is loading...
Leave a Comment