UNPKG

@zohodesk/popups

Version:

popups popupover modal dialog alert notifications popup handling for whole app

330 lines (272 loc) 10.8 kB
let viewPort = { frameRelativeRects: (el, customFrame) => { if (!el) {return;} var rect = el.getBoundingClientRect(); //Target Element let documentEle = document.documentElement; //Body&HTML var customFrameRect = { top : 0, left : 0 , right : documentEle.clientWidth, bottom : documentEle.clientHeight, height : documentEle.clientHeight, width : documentEle.clientWidth, x : 0 , y : 0 } if( customFrame ){ customFrameRect = customFrame.getBoundingClientRect(); } let newReact = { top: rect.top - customFrameRect.top, left: rect.left - customFrameRect.left, height: rect.height, width: rect.width }; newReact.bottom = newReact.top + newReact.height; newReact.right = newReact.left + newReact.width; newReact.x = newReact.left; newReact.y = newReact.top; let rectGap = { top: newReact.top, left: newReact.left, bottom: customFrameRect.height - newReact.bottom, right: customFrameRect.width - newReact.right }; rectGap.center = { top: rectGap.top + newReact.height / 2, left: rectGap.left + newReact.width / 2, bottom: rectGap.bottom + newReact.height / 2, right: rectGap.right + newReact.width / 2 }; let adjustments = {}; if (newReact.top < 0) { adjustments.top = Math.abs(newReact.top); } if (newReact.left < 0) { adjustments.left = Math.abs(newReact.left); } if (newReact.bottom > customFrameRect.height) { adjustments.bottom = newReact.bottom - customFrameRect.height; } if (newReact.right > customFrameRect.width) { adjustments.right = newReact.right - customFrameRect.width; } return { frameRect: customFrameRect, rect: newReact, rectGap, adjustments }; }, isInViewPort: (el, customFrame) => { if (!el) {return;} let elRects = viewPort.frameRelativeRects(el, customFrame); let react = elRects.rect; let frameReact = elRects.frameRect; return rect.top >= 0 && rect.left >= 0 && rect.bottom <= frameReact.height && rect.right <= frameReact.width; }, possibilities: ( el, relativeBox, customFrame, ) => { if (!el) {return;} let elRects = viewPort.frameRelativeRects(el, customFrame); let rect = elRects.rect; let adjustments = elRects.adjustments; let relativeBoxReacts = viewPort.frameRelativeRects(relativeBox, customFrame); let relativeBoxRect = relativeBoxReacts.rect; let relativeBoxGap = relativeBoxReacts.rectGap; let relativeBoxDocumentRects = viewPort.frameRelativeRects( relativeBox, customFrame ); let { rectGap: documentGap } = relativeBoxDocumentRects; adjustments.left? adjustments.left=adjustments.left+(relativeBoxReacts.rect.width*2/3):null adjustments.right?adjustments.right=adjustments.right+(relativeBoxReacts.rect.width*2/3):null adjustments.top?adjustments.top=adjustments.top+(relativeBoxReacts.rect.width*2/3):null adjustments.bottom?adjustments.bottom=adjustments.bottom+(relativeBoxReacts.rect.width*2/3):null let views = {}; //bottomCenter let bottomOverFlow = rect.height >= relativeBoxGap.bottom; let bottomRightOverFlow = rect.width / 2 >= relativeBoxGap.center.right; let bottomLeftOverFlow = rect.width / 2 >= relativeBoxGap.center.left; //bottomRight let bottomLeftOnlyOverFlow = rect.width >= relativeBoxGap.center.left; views.bottomRight = !(bottomOverFlow || bottomLeftOnlyOverFlow); //bottomLeft let bottomRightOnlyOverFlow = rect.width >= relativeBoxGap.center.right; views.bottomLeft = !(bottomOverFlow || bottomRightOnlyOverFlow); views.bottomCenter = !(bottomOverFlow || bottomRightOverFlow || bottomLeftOverFlow ); //topCenter let topOverFlow = rect.height >= relativeBoxGap.top; let topRightOverFlow = rect.width / 2 >= relativeBoxGap.center.right; let topLeftOverFlow = rect.width / 2 >= relativeBoxGap.center.left; //topRight let topLeftOnlyOverFlow = rect.width >= relativeBoxGap.center.left; views.topRight = !(topOverFlow || topLeftOnlyOverFlow); //topLeft let topRightOnlyOverFlow = rect.width >= relativeBoxGap.center.right; views.topLeft = !(topOverFlow || topRightOnlyOverFlow); views.topCenter = !(topOverFlow || topRightOverFlow || topLeftOverFlow ); //|| topLeftOnlyOverFlow || topRightOnlyOverFlow); //leftCenter let leftOverFlow = rect.width >= relativeBoxGap.left; let leftTopOverFlow = rect.height / 2 >= relativeBoxGap.center.top; let leftBottomOverFlow = rect.height / 2 >= relativeBoxGap.center.bottom; //leftTop let leftTopOnlyOverFlow = rect.height >= relativeBoxGap.center.bottom; views.leftTop = !(leftOverFlow || leftTopOnlyOverFlow); //leftBottom let leftBottomOnlyOverFlow = rect.height >= relativeBoxGap.center.top; views.leftBottom = !(leftOverFlow || leftBottomOnlyOverFlow); views.leftCenter = !(leftOverFlow || leftTopOverFlow || leftBottomOverFlow); // || leftTopOnlyOverFlow || leftBottomOnlyOverFlow); //rightCenter let rightOverFlow = rect.width >= relativeBoxGap.right; let rightTopOverFlow = rect.height / 2 >= relativeBoxGap.center.top; let rightBottomOverFlow = rect.height / 2 >= relativeBoxGap.center.bottom; //rightTop let rightTopOnlyOverFlow = rect.height >= relativeBoxGap.center.bottom; views.rightTop = !(rightOverFlow || rightTopOnlyOverFlow); //rightBottom let rightBottomOnlyOverFlow = rect.height >= relativeBoxGap.center.top; views.rightBottom = !(rightOverFlow || rightBottomOnlyOverFlow); views.rightCenter = !(rightOverFlow || rightTopOverFlow || rightBottomOverFlow); // || rightTopOnlyOverFlow || rightBottomOnlyOverFlow); let horizontalCenter = relativeBoxGap.left + relativeBoxRect.width / 2; let horizontalLeft = relativeBoxGap.left; let horizontalRight = relativeBoxGap.left + relativeBoxRect.width; let verticalBottom = relativeBoxGap.top + relativeBoxRect.height; let verticalTop = relativeBoxGap.top; let verticalCenter = relativeBoxGap.top + relativeBoxRect.height / 2; let horizontalTop = documentGap.bottom + relativeBoxRect.height; let needArrow = false; let paddingSpace = 5; // space between target and relative element let arrowSize = needArrow ? 10 : 5; rect.height = rect.height + (needArrow ? arrowSize : paddingSpace); rect.width = rect.width + (needArrow ? arrowSize : paddingSpace); let viewsOffset = { // Code Copy frm DOT ViewPort.js qa bottomCenter: { left: horizontalCenter - rect.width / 2, top: verticalBottom + arrowSize }, bottomRight:{ left: horizontalRight - rect.width, top: verticalBottom + arrowSize }, bottomLeft:{ left: horizontalLeft, top: verticalBottom + arrowSize }, topCenter: { left: horizontalCenter - rect.width / 2, bottom: horizontalTop + arrowSize }, topRight: { left: horizontalRight - rect.width, bottom: horizontalTop + arrowSize }, topLeft: { left: horizontalLeft, bottom: horizontalTop + arrowSize }, rightCenter: { left: horizontalRight + arrowSize, top: verticalCenter - rect.height / 2 }, rightBottom: { left: horizontalRight + arrowSize, bottom: documentGap.bottom }, rightTop: { left: horizontalRight + arrowSize, top: verticalTop }, leftCenter: { left: horizontalLeft - (rect.width + arrowSize), top: verticalCenter - rect.height / 2 }, leftTop: { left: horizontalLeft - (rect.width + arrowSize), top: verticalTop }, leftBottom: { left: horizontalLeft - (rect.width + arrowSize), bottom: documentGap.bottom } }; return { views, adjustments, positionOffset:viewsOffset }; }, getArrowAdjustments : (el, relativeBox, customFrame) => { if (!el) {return;} let elRects = viewPort.frameRelativeRects(el, customFrame); let rect = elRects.rect; let rectGap = elRects.rectGap; let adjustments = elRects.adjustments; let relativeBoxReacts = viewPort.frameRelativeRects(relativeBox, customFrame); let relativeBoxReact = relativeBoxReacts.rect; let relativeBoxGap = relativeBoxReacts.rectGap; return { left : (relativeBoxGap.center.left - rectGap.left) , right : (relativeBoxGap.center.right - rectGap.right), top : (relativeBoxGap.center.top - rectGap.top), bottom : (relativeBoxGap.center.bottom - rectGap.bottom) }; }, betterView: ( popup, relativeBox, defaultView, customFrame ) => { let viewPortPossibilities = viewPort.possibilities(popup, relativeBox, customFrame); if (!viewPortPossibilities) { return; } let views = viewPortPossibilities.views; let adjustments = viewPortPossibilities.adjustments; let viewKeys = Object.keys(views); let isViewFound = false; let positionOffset=viewPortPossibilities.positionOffset; for (let i = 0; i < viewKeys.length; i++) { let viewKey = viewKeys[i]; if (views[viewKey]) { isViewFound = true; break; } } if (!isViewFound) { return { view: null, adjustments, fixedPosition:{} }; } if (views[defaultView]) { return { view: defaultView, adjustments, fixedPosition:positionOffset[defaultView] }; } let defaultPosition = defaultView.replace(/Center|Bottom|Top|Left|Right$/, ''); let viewTypes = { top: ['Center', 'Right', 'Left'], left: ['Center', 'Top', 'Bottom'] }; viewTypes.bottom = viewTypes.top; viewTypes.right = viewTypes.left; let defaultPositions = viewTypes[defaultPosition]; for (let i = 0, len = defaultPositions.length; i < len; i++) { let viewKey = defaultPosition + defaultPositions[i]; if (views[viewKey]) { return { view: viewKey, adjustments, fixedPosition:positionOffset[viewKey] }; } } let oppositePositionsOrder = { bottom: ['top', 'right', 'left'], top: ['bottom', 'right', 'left'], left: ['bottom', 'right', 'top'], right: ['bottom', 'top', 'left'] }; let oppositeViews = oppositePositionsOrder[defaultPosition]; for (let i = 0, len = oppositeViews.length; i < len; i++) { let oppositeView = oppositeViews[i]; let positions = viewTypes[oppositeView]; for (let j = 0, lenx = positions.length; j < lenx; j++) { let viewKey = oppositeView + positions[j]; if (views[viewKey]) { return { view: viewKey, adjustments, fixedPosition:positionOffset[viewKey] }; } } } return { view: null, adjustments, fixedPosition:{} }; } }; export default { betterView : viewPort.betterView, frameRelativeRects : viewPort.frameRelativeRects, getArrowAdjustments : viewPort.getArrowAdjustments };