diff options
author | 2017-06-09 03:19:04 +0300 | |
---|---|---|
committer | 2017-06-09 03:19:04 +0300 | |
commit | ed64b5edff15e702493df21aa3230b81593e6133 (patch) | |
tree | a4cb01fdaccc34930a8db403a3097c0d1e40914b /catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.ts | |
parent | 280f8015d06af1f41a3ef12e8300801c7a5e0d54 (diff) |
[SDC-29] catalog 1707 rebase commit.
Change-Id: I43c3dc5cf44abf5da817649bc738938a3e8388c1
Signed-off-by: Michael Lando <ml636r@att.com>
Diffstat (limited to 'catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.ts')
-rw-r--r-- | catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.ts | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.ts b/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.ts new file mode 100644 index 0000000000..6e3e8065bb --- /dev/null +++ b/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.ts @@ -0,0 +1,195 @@ +import {Component, AfterViewInit, Input, ElementRef, ChangeDetectorRef} from "@angular/core"; + +@Component +({ + selector: "tooltip-content", + templateUrl: "./tooltip-content.component.html", + styleUrls: ["./tooltip-content.component.less"] +}) + +export class TooltipContentComponent implements AfterViewInit { + + // ------------------------------------------------------------------------- + // Inputs / Outputs + // ------------------------------------------------------------------------- + + @Input() hostElement: HTMLElement; + @Input() content: string; + @Input() placement: "top"|"bottom"|"left"|"right" = "bottom"; + @Input() animation: boolean = true; + + // ------------------------------------------------------------------------- + // Properties + // ------------------------------------------------------------------------- + + top: number = -100000; + left: number = -100000; + isIn: boolean = false; + isFade: boolean = false; + + // ------------------------------------------------------------------------- + // Constructor + // ------------------------------------------------------------------------- + + constructor(private element: ElementRef, + private cdr: ChangeDetectorRef) { + } + + // ------------------------------------------------------------------------- + // Lifecycle callbacks + // ------------------------------------------------------------------------- + + ngAfterViewInit(): void { + this.show(); + this.cdr.detectChanges(); + } + + // ------------------------------------------------------------------------- + // Public Methods + // ------------------------------------------------------------------------- + + show(): void { + if(!this.hostElement) { + return; + } + + const position = this.positionElement(this.hostElement, this.element.nativeElement.children[0], this.placement); + this.top = position.top; + this.left = position.left; + this.isIn = true; + if (this.animation) { + this.isFade = true; + } + } + + hide(): void { + this.top = -100000; + this.left = -100000; + this.isIn = true; + if(this.animation) { + this.isFade = false; + } + } + + // ------------------------------------------------------------------------- + // Private Methods + // ------------------------------------------------------------------------- + + private positionElement(hostElem: HTMLElement, targetElem: HTMLElement, positionStr: string, appendToBody: boolean = false): {top: number, left: number} { + let positionStrParts = positionStr.split("-"); + let pos0 = positionStrParts[0]; + let pos1 = positionStrParts[1] || "center"; + let hostElemPosition = appendToBody ? this.offset(hostElem) : this.position(hostElem); + let targetElemWidth = targetElem.offsetWidth; + let targetElemHeight = targetElem.offsetHeight; + let shiftWidth: any = { + center(): number { + return hostElemPosition.left + hostElemPosition.width / 2 - targetElemWidth / 2; + }, + left(): number { + return hostElemPosition.left; + }, + right(): number { + return hostElemPosition.left + hostElemPosition.width; + } + }; + + let shiftHeight: any = { + center: function (): number { + return hostElemPosition.top + hostElemPosition.height / 2 - targetElemHeight / 2; + }, + top: function (): number { + return hostElemPosition.top; + }, + bottom: function (): number { + return hostElemPosition.top + hostElemPosition.height; + } + } + + let targetElemPosition: {top: number, left: number}; + + switch (pos0) { + case "right": + targetElemPosition = { + top: shiftHeight[pos1](), + left: shiftWidth[pos0]() + }; + break; + + case "left": + targetElemPosition = { + top: shiftHeight[pos1](), + left: hostElemPosition.left - targetElemWidth + }; + break; + + case "bottom": + targetElemPosition = { + top: shiftHeight[pos0](), + left: shiftWidth[pos1]() + }; + break; + + default: + targetElemPosition = { + top: hostElemPosition.top - targetElemHeight, + left: shiftWidth[pos1]() + }; + break; + } + + return targetElemPosition; + } + + + private position(nativeElem: HTMLElement): {width: number, height: number, top: number, left: number} { + let offsetParentCBR = {top: 0, left: 0}; + const elemBCR = this.offset(nativeElem); + const offsetParentElem = this.parentOffsetElem(nativeElem); + if(offsetParentElem !== window.document) { + offsetParentCBR = this.offset(offsetParentElem); + offsetParentCBR.top += offsetParentElem.clientTop - offsetParentElem.scrollTop; + offsetParentCBR.left += offsetParentElem.clientLeft - offsetParentElem.scrollTop; + } + + const boundingClientRect = nativeElem.getBoundingClientRect(); + + return { + width: boundingClientRect.width || nativeElem.offsetWidth, + height: boundingClientRect.height || nativeElem.offsetHeight, + top: elemBCR.top - offsetParentCBR.top, + left: elemBCR.left - offsetParentCBR.left + }; + } + + private offset(nativeElem:any): {width: number, height: number, top: number, left: number} { + const boundingClientRect = nativeElem.getBoundingClientRect(); + return { + width: boundingClientRect.width || nativeElem.offsetWidth, + height: boundingClientRect.height || nativeElem.offsetHeight, + top: boundingClientRect.top + (window.pageYOffset || window.document.documentElement.scrollTop), + left: boundingClientRect.left + (window.pageXOffset || window.document.documentElement.scrollLeft) + }; + } + + private getStyle(nativeElem: HTMLElement, cssProperty: string): string { + if(window.getComputedStyle) { + return (window.getComputedStyle(nativeElem) as any)[cssProperty]; + } + + return (nativeElem.style as any)[cssProperty]; + } + + private isStaticPositioned(nativeElem: HTMLElement): boolean { + return (this.getStyle(nativeElem, "position") || "static") === "static"; + } + + private parentOffsetElem(nativeElem: HTMLElement): any { + let offsetParent: any = nativeElem.offsetParent || window.document; + while (offsetParent && offsetParent !== window.document && this.isStaticPositioned(offsetParent)) { + offsetParent = offsetParent.offsetParent; + } + + return offsetParent || window.document; + } +} |