File size: 4,031 Bytes
22c7264 8755ee2 0c119f7 8755ee2 0c119f7 22c7264 0c119f7 ede8cb9 22c7264 8755ee2 22c7264 0c119f7 22c7264 8755ee2 22c7264 0c119f7 22c7264 0c119f7 22c7264 b1c5f8c ede8cb9 b1c5f8c ede8cb9 ec45071 ede8cb9 ec45071 ede8cb9 b1c5f8c ec45071 22c7264 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
import Position from './position';
export default class Element {
/**
* DOM element object
* @param node
* @param options
*/
constructor(node, options) {
this.node = node;
this.document = document;
this.window = window;
this.options = options;
this.popover = this.getPopover();
}
/**
* Gets the screen co-ordinates (x,y) for the current dom element
* @returns {{x: number, y: number}}
*/
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 };
}
/**
* Gets the calculated position on screen, around which
* we need to draw
*/
getCalculatedPosition() {
const coordinates = this.getScreenCoordinates();
const position = new Position({
left: Number.MAX_VALUE,
top: Number.MAX_VALUE,
right: 0,
bottom: 0,
});
// If we have the position for this element
// and the element is visible on screen (has some height)
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() {
// Will be called when element is about to be deselected
this.hidePopover();
}
onHighlightStarted() {
// Will be triggered when the element is about to be highlighted
// i.e. overlay has started transitioning towards this element
this.showPopover();
}
onHighlighted() {
this.showPopover();
}
showPopover() {
this.resetPopover();
// Position at which the element is
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`;
// Calculate different dimensions after attaching popover
const documentHeightAfterPopOver = position.bottom + popoverHeight + popoverMargin;
// If adding popover would go out of the window height, then show it to the top
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() {
// @todo: Create if not there
const popover = this.document.getElementById('sholo-popover-item');
popover.style.position = 'absolute';
return popover;
}
hidePopover() {
this.popover.style.display = 'none';
}
getDocumentHeight() {
// eslint-disable-next-line prefer-destructuring
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 = '';
// Remove the positional classes from tip
this.popover
.querySelector('.sholo-popover-tip')
.className = 'sholo-popover-tip';
}
}
|