|
import Position from './position'; |
|
|
|
export default class Element { |
|
|
|
|
|
|
|
|
|
|
|
constructor(node, options) { |
|
this.node = node; |
|
this.document = document; |
|
this.window = window; |
|
this.options = options; |
|
this.popover = this.getPopover(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
getScreenCoordinates() { |
|
let tempNode = this.node; |
|
|
|
let x = this.document.documentElement.offsetLeft; |
|
let y = this.document.documentElement.offsetTop; |
|
|
|
if (tempNode.offsetParent) { |
|
do { |
|
x += tempNode.offsetLeft; |
|
y += tempNode.offsetTop; |
|
} while (tempNode = tempNode.offsetParent); |
|
} |
|
|
|
return { x, y }; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
getCalculatedPosition() { |
|
const coordinates = this.getScreenCoordinates(); |
|
const position = new Position({ |
|
left: Number.MAX_VALUE, |
|
top: Number.MAX_VALUE, |
|
right: 0, |
|
bottom: 0, |
|
}); |
|
|
|
|
|
|
|
if (typeof coordinates.x === 'number' && typeof coordinates.y === 'number' && (this.node.offsetWidth > 0 || this.node.offsetHeight > 0)) { |
|
position.left = Math.min(position.left, coordinates.x); |
|
position.top = Math.min(position.top, coordinates.y); |
|
position.right = Math.max(position.right, coordinates.x + this.node.offsetWidth); |
|
position.bottom = Math.max(position.bottom, coordinates.y + this.node.offsetHeight); |
|
} |
|
|
|
return position; |
|
} |
|
|
|
onDeselected() { |
|
|
|
this.hidePopover(); |
|
} |
|
|
|
onHighlightStarted() { |
|
|
|
|
|
this.showPopover(); |
|
} |
|
|
|
onHighlighted() { |
|
this.showPopover(); |
|
} |
|
|
|
showPopover() { |
|
this.resetPopover(); |
|
|
|
|
|
const position = this.getCalculatedPosition(); |
|
|
|
const popoverTip = this.popover.querySelector('.sholo-popover-tip'); |
|
|
|
const documentHeight = this.getDocumentHeight(); |
|
const popoverHeight = this.getPopoverHeight(); |
|
const popoverMargin = this.options.padding + 10; |
|
|
|
this.popover.style.left = `${position.left - this.options.padding}px`; |
|
|
|
|
|
const documentHeightAfterPopOver = position.bottom + popoverHeight + popoverMargin; |
|
|
|
|
|
if (documentHeightAfterPopOver >= documentHeight) { |
|
this.popover.style.top = `${position.top - popoverHeight - popoverMargin}px`; |
|
popoverTip.classList.add('bottom'); |
|
} else { |
|
this.popover.style.top = `${position.bottom + popoverMargin}px`; |
|
popoverTip.classList.add('top'); |
|
} |
|
} |
|
|
|
getPopover() { |
|
|
|
const popover = this.document.getElementById('sholo-popover-item'); |
|
popover.style.position = 'absolute'; |
|
|
|
return popover; |
|
} |
|
|
|
hidePopover() { |
|
this.popover.style.display = 'none'; |
|
} |
|
|
|
getDocumentHeight() { |
|
|
|
const body = this.document.body; |
|
const html = this.document.documentElement; |
|
|
|
return Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight); |
|
} |
|
|
|
getPopoverHeight() { |
|
return Math.max(this.popover.scrollHeight, this.popover.offsetHeight); |
|
} |
|
|
|
resetPopover() { |
|
this.popover.style.display = 'block'; |
|
this.popover.style.left = ''; |
|
this.popover.style.top = ''; |
|
this.popover.style.bottom = ''; |
|
this.popover.style.right = ''; |
|
|
|
|
|
this.popover |
|
.querySelector('.sholo-popover-tip') |
|
.className = 'sholo-popover-tip'; |
|
} |
|
} |
|
|