projects/rebirth-ng/src/lib/position/positioning.service.ts
Methods |
|
constructor(windowRef: WindowRef, documentRef: DocumentRef)
|
|||||||||
Parameters :
|
Private getStyle | |||||||||
getStyle(element: HTMLElement, prop: string)
|
|||||||||
Parameters :
Returns :
string
|
Private isStaticPositioned | ||||||
isStaticPositioned(element: HTMLElement)
|
||||||
Parameters :
Returns :
boolean
|
offset | ||||||||||||
offset(element: HTMLElement, round: )
|
||||||||||||
Parameters :
Returns :
ClientRect
|
Private offsetParent | ||||||
offsetParent(element: HTMLElement)
|
||||||
Parameters :
Returns :
HTMLElement
|
position | ||||||||||||
position(element: HTMLElement, round: )
|
||||||||||||
Parameters :
Returns :
ClientRect
|
positionElements | |||||||||||||||
positionElements(hostElement: HTMLElement, targetElement: HTMLElement, placement: string, appendToBody?: boolean)
|
|||||||||||||||
Parameters :
Returns :
ClientRect
|
import { Injectable } from '@angular/core';
import { WindowRef } from '../window-ref/window-ref.service';
import { DocumentRef } from '../window-ref/document-ref.service';
@Injectable({ providedIn: 'root' })
export class PositionService {
constructor(private windowRef: WindowRef, private documentRef: DocumentRef) {
}
position(element: HTMLElement, round = true): ClientRect {
let elPosition: ClientRect;
let parentOffset: ClientRect = { width: 0, height: 0, top: 0, bottom: 0, left: 0, right: 0 };
if (this.getStyle(element, 'position') === 'fixed') {
elPosition = element.getBoundingClientRect();
} else {
const offsetParentEl = this.offsetParent(element);
elPosition = this.offset(element, false);
if (offsetParentEl !== this.documentRef.documentElement) {
parentOffset = this.offset(offsetParentEl, false);
}
parentOffset.top += offsetParentEl.clientTop;
parentOffset.left += offsetParentEl.clientLeft;
}
elPosition.top -= parentOffset.top;
elPosition.bottom -= parentOffset.top;
elPosition.left -= parentOffset.left;
elPosition.right -= parentOffset.left;
if (round) {
elPosition.top = Math.round(elPosition.top);
elPosition.bottom = Math.round(elPosition.bottom);
elPosition.left = Math.round(elPosition.left);
elPosition.right = Math.round(elPosition.right);
}
return elPosition;
}
offset(element: HTMLElement, round = true): ClientRect {
const elBcr = element.getBoundingClientRect();
const viewportOffset = {
top: this.windowRef.pageYOffset - this.documentRef.documentElement.clientTop,
left: this.windowRef.pageXOffset - this.documentRef.documentElement.clientLeft
};
const elOffset = {
height: elBcr.height || element.offsetHeight,
width: elBcr.width || element.offsetWidth,
top: elBcr.top + viewportOffset.top,
bottom: elBcr.bottom + viewportOffset.top,
left: elBcr.left + viewportOffset.left,
right: elBcr.right + viewportOffset.left
};
if (round) {
elOffset.height = Math.round(elOffset.height);
elOffset.width = Math.round(elOffset.width);
elOffset.top = Math.round(elOffset.top);
elOffset.bottom = Math.round(elOffset.bottom);
elOffset.left = Math.round(elOffset.left);
elOffset.right = Math.round(elOffset.right);
}
return elOffset;
}
positionElements(hostElement: HTMLElement, targetElement: HTMLElement, placement: string, appendToBody?: boolean): ClientRect {
const hostElPosition = appendToBody ? this.offset(hostElement, false) : this.position(hostElement, false);
const shiftWidth: any = {
left: hostElPosition.left,
center: hostElPosition.left + hostElPosition.width / 2 - targetElement.offsetWidth / 2,
right: hostElPosition.left + hostElPosition.width
};
const shiftHeight: any = {
top: hostElPosition.top,
center: hostElPosition.top + hostElPosition.height / 2 - targetElement.offsetHeight / 2,
bottom: hostElPosition.top + hostElPosition.height
};
const targetElBCR = targetElement.getBoundingClientRect();
const placementPrimary = placement.split('-')[0] || 'top';
const placementSecondary = placement.split('-')[1] || 'center';
const targetElPosition: ClientRect = {
height: targetElBCR.height || targetElement.offsetHeight,
width: targetElBCR.width || targetElement.offsetWidth,
top: 0,
bottom: targetElBCR.height || targetElement.offsetHeight,
left: 0,
right: targetElBCR.width || targetElement.offsetWidth
};
switch (placementPrimary) {
case 'top':
targetElPosition.top = hostElPosition.top - targetElement.offsetHeight;
targetElPosition.bottom += hostElPosition.top - targetElement.offsetHeight;
targetElPosition.left = shiftWidth[placementSecondary];
targetElPosition.right += shiftWidth[placementSecondary];
break;
case 'bottom':
targetElPosition.top = shiftHeight[placementPrimary];
targetElPosition.bottom += shiftHeight[placementPrimary];
targetElPosition.left = shiftWidth[placementSecondary];
targetElPosition.right += shiftWidth[placementSecondary];
break;
case 'left':
targetElPosition.top = shiftHeight[placementSecondary];
targetElPosition.bottom += shiftHeight[placementSecondary];
targetElPosition.left = hostElPosition.left - targetElement.offsetWidth;
targetElPosition.right += hostElPosition.left - targetElement.offsetWidth;
break;
case 'right':
targetElPosition.top = shiftHeight[placementSecondary];
targetElPosition.bottom += shiftHeight[placementSecondary];
targetElPosition.left = shiftWidth[placementPrimary];
targetElPosition.right += shiftWidth[placementPrimary];
break;
}
targetElPosition.top = Math.round(targetElPosition.top);
targetElPosition.bottom = Math.round(targetElPosition.bottom);
targetElPosition.left = Math.round(targetElPosition.left);
targetElPosition.right = Math.round(targetElPosition.right);
return targetElPosition;
}
private getStyle(element: HTMLElement, prop: string): string {
return this.windowRef.getComputedStyle(element)[prop];
}
private isStaticPositioned(element: HTMLElement): boolean {
return (this.getStyle(element, 'position') || 'static') === 'static';
}
private offsetParent(element: HTMLElement): HTMLElement {
let offsetParentEl = <HTMLElement>element.offsetParent || this.documentRef.documentElement;
while (offsetParentEl && offsetParentEl !== this.documentRef.documentElement && this.isStaticPositioned(offsetParentEl)) {
offsetParentEl = <HTMLElement>offsetParentEl.offsetParent;
}
return offsetParentEl || this.documentRef.documentElement;
}
}
// const positionService = new Positioning();
// export function positionElements(hostElement: HTMLElement, targetElement: HTMLElement, placement: string, appendToBody?: boolean): void {
// const pos = positionService.positionElements(hostElement, targetElement, placement, appendToBody);
//
// targetElement.style.top = `${pos.top}px`;
// targetElement.style.left = `${pos.left}px`;
// }