|
import Position from './position'; |
|
|
|
|
|
|
|
|
|
|
|
export default class Element { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor(node, options, popover, overlay, window, document) { |
|
this.node = node; |
|
this.document = document; |
|
this.window = window; |
|
this.options = options; |
|
this.overlay = overlay; |
|
this.popover = popover; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
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 }; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
isInView() { |
|
let top = this.node.offsetTop; |
|
let left = this.node.offsetLeft; |
|
const width = this.node.offsetWidth; |
|
const height = this.node.offsetHeight; |
|
|
|
let el = this.node; |
|
|
|
while (el.offsetParent) { |
|
el = el.offsetParent; |
|
top += el.offsetTop; |
|
left += el.offsetLeft; |
|
} |
|
|
|
return ( |
|
top >= this.window.pageYOffset && |
|
left >= this.window.pageXOffset && |
|
(top + height) <= (this.window.pageYOffset + this.window.innerHeight) && |
|
(left + width) <= (this.window.pageXOffset + this.window.innerWidth) |
|
); |
|
} |
|
|
|
|
|
|
|
|
|
bringInView() { |
|
if (this.isInView()) { |
|
return; |
|
} |
|
|
|
const elementRect = this.node.getBoundingClientRect(); |
|
const absoluteElementTop = elementRect.top + this.window.pageYOffset; |
|
const middle = absoluteElementTop - (this.window.innerHeight / 2); |
|
|
|
this.window.scrollTo(0, middle); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
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() { |
|
if (!this.popover) { |
|
return; |
|
} |
|
|
|
this.popover.hide(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
onHighlightStarted() { |
|
if (!this.popover) { |
|
return; |
|
} |
|
|
|
this.showPopover(); |
|
} |
|
|
|
|
|
|
|
|
|
onHighlighted() { |
|
if (this.popover) { |
|
this.showPopover(); |
|
} |
|
|
|
const highlightedElement = this; |
|
const lastHighlightedElement = this.overlay.getLastHighlightedElement(); |
|
const popoverElement = this.popover; |
|
|
|
const highlightedNode = this.node; |
|
const lastHighlightedNode = lastHighlightedElement && lastHighlightedElement.node; |
|
|
|
|
|
|
|
if (highlightedNode !== lastHighlightedNode) { |
|
if (popoverElement && !popoverElement.isInView()) { |
|
popoverElement.bringInView(); |
|
} |
|
|
|
if (!highlightedElement.isInView()) { |
|
highlightedElement.bringInView(); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
showPopover() { |
|
const position = this.getCalculatedPosition(); |
|
|
|
this.popover.show(position); |
|
} |
|
|
|
|
|
|
|
|
|
getFullPageSize() { |
|
|
|
const body = this.document.body; |
|
const html = this.document.documentElement; |
|
|
|
return { |
|
height: Math.max(body.scrollHeight, body.offsetHeight, html.scrollHeight, html.offsetHeight), |
|
width: Math.max(body.scrollWidth, body.offsetWidth, html.scrollWidth, html.offsetWidth), |
|
}; |
|
} |
|
} |
|
|