From 309680feb63ec6a49163387cb1e116b721254847 Mon Sep 17 00:00:00 2001 From: YuanHu Date: Tue, 27 Mar 2018 15:50:00 +0800 Subject: Add paletx common & util Add paletx common & util Issue-ID: SDC-1130,SDC-1131 Change-Id: Ibbdd8d4fabf45637be7d44400c18d34efc15d46e Signed-off-by: YuanHu --- .../src/app/paletx/util/positioning.ts | 425 +++++++++++++++++++++ 1 file changed, 425 insertions(+) create mode 100644 sdc-workflow-designer-ui/src/app/paletx/util/positioning.ts (limited to 'sdc-workflow-designer-ui/src/app/paletx/util/positioning.ts') diff --git a/sdc-workflow-designer-ui/src/app/paletx/util/positioning.ts b/sdc-workflow-designer-ui/src/app/paletx/util/positioning.ts new file mode 100644 index 00000000..79399d6d --- /dev/null +++ b/sdc-workflow-designer-ui/src/app/paletx/util/positioning.ts @@ -0,0 +1,425 @@ +// previous version: +// https://github.com/angular-ui/bootstrap/blob/07c31d0731f7cb068a1932b8e01d2312b796b4ec/src/position/position.js +export class Positioning { + private getStyle(element: HTMLElement, prop: string): string { + return window.getComputedStyle(element)[prop]; + } + + private isStaticPositioned(element: HTMLElement): boolean { + return (this.getStyle(element, 'position') || 'static') === 'static'; + } + + private offsetParent(element: HTMLElement): HTMLElement { + let offsetParentEl = element.offsetParent || document.documentElement; + + while (offsetParentEl && offsetParentEl !== document.documentElement && this.isStaticPositioned(offsetParentEl)) { + offsetParentEl = offsetParentEl.offsetParent; + } + + return offsetParentEl || document.documentElement; + } + + public 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 !== document.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; + } + + public offset(element: HTMLElement, round = true): ClientRect { + const elBcr = element.getBoundingClientRect(); + const viewportOffset = { + top: window.pageYOffset - document.documentElement.clientTop, + left: window.pageXOffset - document.documentElement.clientLeft + }; + + let 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; + } + + + public getPlacementPrimary(hostElement: HTMLElement, targetElement: HTMLElement, placement: string): string { + + // let placementPrimaryArray = ['right', 'bottom', 'left', 'top']; + // placementPrimaryArray.splice(placementPrimaryArray.indexOf(placementPrimary), 1); + // placementPrimaryArray.splice(0, 0, placementPrimary); + + let placementPrimaryArray = this.getTotalPlacementArr(placement); + let placementPrimary; + let placementSecondary; + let rect; + + let result = placementPrimaryArray.find(place => { + placementPrimary = place.split('-')[0] || 'top'; + placementSecondary = place.split('-')[1] || 'center'; + rect = this.getBoundingClientRect(placementPrimary, placementSecondary, hostElement, targetElement); + return this.canDisplay(rect); + }); + + if (!result) { + return placement; + } else { + return result; + } + } + + private getTotalPlacementArr(placement: string): any { + let placementPrimary = placement.split('-')[0] || 'top'; + + let placementBasic = ['right', 'bottom', 'left', 'top']; + placementBasic.splice(placementBasic.indexOf(placementPrimary), 1); + placementBasic.splice(0, 0, placementPrimary); + let placeTotal = { + right: [ + 'right', + 'right-top', + 'right-bottom' + ], + bottom: [ + 'bottom', + 'bottom-left', + 'bottom-right' + ], + left: [ + 'left', + 'left-top', + 'left-bottom' + ], + top: [ + 'top', + 'top-left', + 'top-right' + ] + } + let placeArr = []; + placeArr.push(placement); + placementBasic.forEach(placePri => { + placeTotal[placePri].forEach(palce => { + if (placement !== palce) { + placeArr.push(palce); + } + }); + }); + return placeArr; + } + + private canDisplay(rect): boolean { + if(this.isSheltered(rect, window)) { + return false; + } else { + var pElement = this.getParentElement(window); + if(pElement) { + const shelter = this.getShelter(pElement, window.parent, rect); + if(shelter) { + return false; + } else { + return true; + } + } else { + return true; + } + + } + } + + /** + * 判断当前位置在对应的窗口中是否会被遮挡 + * 用于iframe嵌套的场景 + * @param position + * @param currentWindow + */ + private isSheltered(position, currentWindow) { + if(position.left < 0 || position.top < 0 + || position.right > currentWindow.document.documentElement.clientWidth + || position.bottom > currentWindow.document.documentElement.clientHeight) { + return true; + } else { + return false; + } + } + + /** + * 递归判断当前元素是否会被视口遮挡 + * @param element + * @param currentWindow + * @param position + */ + public getShelter(element, currentWindow, position) { + var rect = element.getBoundingClientRect(); + position.left += rect.left; + position.right += rect.left; + position.top += rect.top; + position.bottom += rect.top; + + if(this.isSheltered(position, currentWindow)) { + return element; + } else { + if(currentWindow.parent != currentWindow) { // 判断是否到达最顶级容器 + var pElement = this.getParentElement(currentWindow); + return this.getShelter(pElement, currentWindow.parent, position); + } else { + return null; + } + } + } + + /** + * 查找当前容器在父窗口中的dom元素 + * 如:iframe场景中,则为在子页面中查找父页面中的iframe节点 + * @param currentWindow + */ + public getParentElement(currentWindow) { + if(currentWindow.parent !== currentWindow) { + var parentWindow = currentWindow.parent; + var frames = parentWindow.document.getElementsByTagName("iframe"); + for(var i=0; i