|
import Element from './element'; |
|
import { |
|
CLASS_BTN_DISABLED, |
|
CLASS_CLOSE_BTN, |
|
CLASS_NEXT_STEP_BTN, |
|
CLASS_POPOVER_DESCRIPTION, |
|
CLASS_POPOVER_FOOTER, |
|
CLASS_POPOVER_TIP, |
|
CLASS_POPOVER_TITLE, |
|
CLASS_PREV_STEP_BTN, |
|
ID_POPOVER, |
|
POPOVER_HTML, |
|
} from '../common/constants'; |
|
import { createNodeFromString } from '../common/utils'; |
|
|
|
|
|
|
|
|
|
export default class Popover extends Element { |
|
|
|
|
|
|
|
|
|
|
|
constructor(options, window, document) { |
|
super(); |
|
|
|
this.options = { |
|
isFirst: true, |
|
isLast: true, |
|
totalCount: 1, |
|
currentIndex: 0, |
|
offset: 0, |
|
showButtons: true, |
|
closeBtnText: 'Close', |
|
doneBtnText: 'Done', |
|
startBtnText: 'Next →', |
|
nextBtnText: 'Next →', |
|
prevBtnText: '← Previous', |
|
...options, |
|
}; |
|
|
|
this.window = window; |
|
this.document = document; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
attachNode() { |
|
let popover = this.document.getElementById(ID_POPOVER); |
|
if (popover) { |
|
popover.parentElement.removeChild(popover); |
|
} |
|
|
|
popover = createNodeFromString(POPOVER_HTML(this.options.className)); |
|
document.body.appendChild(popover); |
|
|
|
this.node = popover; |
|
this.tipNode = popover.querySelector(`.${CLASS_POPOVER_TIP}`); |
|
this.titleNode = popover.querySelector(`.${CLASS_POPOVER_TITLE}`); |
|
this.descriptionNode = popover.querySelector(`.${CLASS_POPOVER_DESCRIPTION}`); |
|
this.footerNode = popover.querySelector(`.${CLASS_POPOVER_FOOTER}`); |
|
this.nextBtnNode = popover.querySelector(`.${CLASS_NEXT_STEP_BTN}`); |
|
this.prevBtnNode = popover.querySelector(`.${CLASS_PREV_STEP_BTN}`); |
|
this.closeBtnNode = popover.querySelector(`.${CLASS_CLOSE_BTN}`); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
getTitleNode() { |
|
return this.titleNode; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
getDescriptionNode() { |
|
return this.descriptionNode; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
hide() { |
|
this.node.style.display = 'none'; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
setInitialState() { |
|
this.node.style.display = 'block'; |
|
this.node.style.left = '0'; |
|
this.node.style.top = '0'; |
|
this.node.style.bottom = ''; |
|
this.node.style.right = ''; |
|
|
|
|
|
this.node |
|
.querySelector(`.${CLASS_POPOVER_TIP}`) |
|
.className = CLASS_POPOVER_TIP; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
show(position) { |
|
this.attachNode(); |
|
this.setInitialState(); |
|
|
|
|
|
this.titleNode.innerHTML = this.options.title; |
|
this.descriptionNode.innerHTML = this.options.description || ''; |
|
|
|
this.renderFooter(); |
|
|
|
|
|
switch (this.options.position) { |
|
case 'left': |
|
case 'left-top': |
|
this.positionOnLeft(position); |
|
break; |
|
case 'left-center': |
|
this.positionOnLeftCenter(position); |
|
break; |
|
case 'left-bottom': |
|
this.positionOnLeftBottom(position); |
|
break; |
|
case 'right': |
|
case 'right-top': |
|
this.positionOnRight(position); |
|
break; |
|
case 'right-center': |
|
this.positionOnRightCenter(position); |
|
break; |
|
case 'right-bottom': |
|
this.positionOnRightBottom(position); |
|
break; |
|
case 'top': |
|
case 'top-left': |
|
this.positionOnTop(position); |
|
break; |
|
case 'top-center': |
|
this.positionOnTopCenter(position); |
|
break; |
|
case 'top-right': |
|
this.positionOnTopRight(position); |
|
break; |
|
case 'bottom': |
|
case 'bottom-left': |
|
this.positionOnBottom(position); |
|
break; |
|
case 'bottom-center': |
|
this.positionOnBottomCenter(position); |
|
break; |
|
case 'bottom-right': |
|
this.positionOnBottomRight(position); |
|
break; |
|
case 'mid-center': |
|
this.positionOnMidCenter(position); |
|
break; |
|
case 'auto': |
|
default: |
|
this.autoPosition(position); |
|
break; |
|
} |
|
|
|
|
|
this.bringInView(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
renderFooter() { |
|
this.nextBtnNode.innerHTML = this.options.nextBtnText; |
|
this.prevBtnNode.innerHTML = this.options.prevBtnText; |
|
this.closeBtnNode.innerHTML = this.options.closeBtnText; |
|
|
|
|
|
if (!this.options.showButtons || !this.options.totalCount || this.options.totalCount === 1) { |
|
this.footerNode.style.display = 'none'; |
|
return; |
|
} |
|
|
|
this.footerNode.style.display = 'block'; |
|
if (this.options.isFirst) { |
|
this.prevBtnNode.classList.add(CLASS_BTN_DISABLED); |
|
this.nextBtnNode.innerHTML = this.options.startBtnText; |
|
} else { |
|
this.prevBtnNode.classList.remove(CLASS_BTN_DISABLED); |
|
} |
|
|
|
if (this.options.isLast) { |
|
this.nextBtnNode.innerHTML = this.options.doneBtnText; |
|
} else { |
|
this.nextBtnNode.innerHTML = this.options.nextBtnText; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnLeft(elementPosition) { |
|
const popoverWidth = this.getSize().width; |
|
const popoverMargin = this.options.padding + 10; |
|
|
|
this.node.style.left = `${elementPosition.left - popoverWidth - popoverMargin}px`; |
|
this.node.style.top = `${(elementPosition.top + this.options.offset) - this.options.padding}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
this.tipNode.classList.add('right'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnLeftBottom(elementPosition) { |
|
const popoverDimensions = this.getSize(); |
|
|
|
const popoverWidth = popoverDimensions.width; |
|
const popoverMargin = this.options.padding + 10; |
|
|
|
this.node.style.left = `${elementPosition.left - popoverWidth - popoverMargin}px`; |
|
this.node.style.top = `${(elementPosition.bottom + this.options.padding + this.options.offset) - popoverDimensions.height}px`; |
|
this.node.style.bottom = ''; |
|
this.node.style.right = ''; |
|
|
|
this.tipNode.classList.add('right', 'position-bottom'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnLeftCenter(elementPosition) { |
|
const popoverDimensions = this.getSize(); |
|
|
|
const popoverWidth = popoverDimensions.width; |
|
const popoverHeight = popoverDimensions.height; |
|
const popoverCenter = popoverHeight / 2; |
|
|
|
const popoverMargin = this.options.padding + 10; |
|
const elementCenter = (elementPosition.bottom - elementPosition.top) / 2; |
|
const topCenterPosition = (elementPosition.top - popoverCenter) + elementCenter + this.options.offset; |
|
|
|
this.node.style.left = `${elementPosition.left - popoverWidth - popoverMargin}px`; |
|
this.node.style.top = `${topCenterPosition}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
this.tipNode.classList.add('right', 'position-center'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnRight(elementPosition) { |
|
const popoverMargin = this.options.padding + 10; |
|
|
|
this.node.style.left = `${elementPosition.right + popoverMargin}px`; |
|
this.node.style.top = `${(elementPosition.top + this.options.offset) - this.options.padding}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
this.tipNode.classList.add('left'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnRightCenter(elementPosition) { |
|
const popoverDimensions = this.getSize(); |
|
const popoverMargin = this.options.padding + 10; |
|
|
|
const popoverHeight = popoverDimensions.height; |
|
const popoverCenter = popoverHeight / 2; |
|
const elementCenter = (elementPosition.bottom - elementPosition.top) / 2; |
|
const topCenterPosition = (elementPosition.top - popoverCenter) + elementCenter + this.options.offset; |
|
|
|
this.node.style.left = `${elementPosition.right + popoverMargin}px`; |
|
this.node.style.top = `${topCenterPosition}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
this.tipNode.classList.add('left', 'position-center'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnRightBottom(elementPosition) { |
|
const popoverMargin = this.options.padding + 10; |
|
const popoverDimensions = this.getSize(); |
|
|
|
this.node.style.left = `${elementPosition.right + popoverMargin}px`; |
|
this.node.style.top = `${(elementPosition.bottom + this.options.padding + this.options.offset) - popoverDimensions.height}px`; |
|
this.node.style.bottom = ''; |
|
this.node.style.right = ''; |
|
|
|
this.tipNode.classList.add('left', 'position-bottom'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnTop(elementPosition) { |
|
const popoverHeight = this.getSize().height; |
|
const popoverMargin = this.options.padding + 10; |
|
|
|
this.node.style.top = `${elementPosition.top - popoverHeight - popoverMargin}px`; |
|
this.node.style.left = `${(elementPosition.left - this.options.padding) + this.options.offset}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
this.tipNode.classList.add('bottom'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnTopCenter(elementPosition) { |
|
const dimensions = this.getSize(); |
|
const popoverHeight = dimensions.height; |
|
const popoverWidth = dimensions.width / 2; |
|
|
|
const popoverMargin = this.options.padding + 10; |
|
const nodeCenter = this.options.offset + elementPosition.left + ((elementPosition.right - elementPosition.left) / 2); |
|
|
|
this.node.style.top = `${elementPosition.top - popoverHeight - popoverMargin}px`; |
|
this.node.style.left = `${nodeCenter - popoverWidth - this.options.padding}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
|
|
this.tipNode.classList.add('bottom', 'position-center'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnTopRight(elementPosition) { |
|
const dimensions = this.getSize(); |
|
const popoverHeight = dimensions.height; |
|
const popoverMargin = this.options.padding + 10; |
|
|
|
this.node.style.top = `${elementPosition.top - popoverHeight - popoverMargin}px`; |
|
this.node.style.left = `${(elementPosition.right + this.options.padding + this.options.offset) - dimensions.width}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
|
|
this.tipNode.classList.add('bottom', 'position-right'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnBottom(elementPosition) { |
|
const popoverMargin = this.options.padding + 10; |
|
|
|
this.node.style.top = `${elementPosition.bottom + popoverMargin}px`; |
|
this.node.style.left = `${(elementPosition.left - this.options.padding) + this.options.offset}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
this.tipNode.classList.add('top'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnBottomCenter(elementPosition) { |
|
const popoverWidth = this.getSize().width / 2; |
|
const popoverMargin = this.options.padding + 10; |
|
const nodeCenter = this.options.offset + elementPosition.left + ((elementPosition.right - elementPosition.left) / 2); |
|
|
|
this.node.style.top = `${elementPosition.bottom + popoverMargin}px`; |
|
this.node.style.left = `${nodeCenter - popoverWidth - this.options.padding}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
|
|
this.tipNode.classList.add('top', 'position-center'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnBottomRight(elementPosition) { |
|
const dimensions = this.getSize(); |
|
const popoverMargin = this.options.padding + 10; |
|
|
|
this.node.style.top = `${elementPosition.bottom + popoverMargin}px`; |
|
this.node.style.left = `${(elementPosition.right + this.options.padding + this.options.offset) - dimensions.width}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
|
|
this.tipNode.classList.add('top', 'position-right'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
positionOnMidCenter(elementPosition) { |
|
const popoverDimensions = this.getSize(); |
|
const popoverHeight = popoverDimensions.height; |
|
const popoverWidth = popoverDimensions.width / 2; |
|
const popoverCenter = popoverHeight / 2; |
|
|
|
const elementCenter = (elementPosition.bottom - elementPosition.top) / 2; |
|
const topCenterPosition = (elementPosition.top - popoverCenter) + elementCenter + this.options.offset; |
|
const nodeCenter = this.options.offset + elementPosition.left + ((elementPosition.right - elementPosition.left) / 2); |
|
|
|
this.node.style.top = `${topCenterPosition}px`; |
|
this.node.style.left = `${nodeCenter - popoverWidth - this.options.padding}px`; |
|
this.node.style.right = ''; |
|
this.node.style.bottom = ''; |
|
|
|
|
|
this.tipNode.classList.add('mid-center'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
autoPosition(elementPosition) { |
|
const pageSize = this.getFullPageSize(); |
|
const popoverSize = this.getSize(); |
|
|
|
const pageHeight = pageSize.height; |
|
const popoverHeight = popoverSize.height; |
|
const popoverMargin = this.options.padding + 10; |
|
|
|
const pageHeightAfterPopOver = elementPosition.bottom + popoverHeight + popoverMargin; |
|
|
|
|
|
if (pageHeightAfterPopOver >= pageHeight) { |
|
this.positionOnTop(elementPosition); |
|
} else { |
|
this.positionOnBottom(elementPosition); |
|
} |
|
} |
|
} |
|
|