|
import { ANIMATION_DURATION_MS, ID_OVERLAY, OVERLAY_HTML } from '../common/constants'; |
|
import { createNodeFromString } from '../common/utils'; |
|
|
|
|
|
|
|
|
|
|
|
export default class Overlay { |
|
|
|
|
|
|
|
|
|
|
|
constructor(options, window, document) { |
|
this.options = options; |
|
|
|
this.highlightedElement = null; |
|
this.lastHighlightedElement = null; |
|
this.hideTimer = null; |
|
|
|
this.window = window; |
|
this.document = document; |
|
|
|
this.removeNode = this.removeNode.bind(this); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
attachNode() { |
|
let pageOverlay = this.document.getElementById(ID_OVERLAY); |
|
if (!pageOverlay) { |
|
pageOverlay = createNodeFromString(OVERLAY_HTML); |
|
document.body.appendChild(pageOverlay); |
|
} |
|
|
|
this.node = pageOverlay; |
|
this.node.style.opacity = '0'; |
|
|
|
if (!this.options.animate) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.node.parentElement) { |
|
this.node.parentElement.removeChild(this.node); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
highlight(element) { |
|
if (!element || !element.node) { |
|
console.warn('Invalid element to highlight. Must be an instance of `Element`'); |
|
return; |
|
} |
|
|
|
|
|
if (element.isSame(this.highlightedElement)) { |
|
return; |
|
} |
|
|
|
|
|
|
|
this.window.clearTimeout(this.hideTimer); |
|
|
|
|
|
element.onHighlightStarted(); |
|
|
|
|
|
if (this.highlightedElement && !this.highlightedElement.isSame(this.lastHighlightedElement)) { |
|
this.highlightedElement.onDeselected(); |
|
} |
|
|
|
|
|
const position = element.getCalculatedPosition(); |
|
if (!position.canHighlight()) { |
|
return; |
|
} |
|
|
|
this.lastHighlightedElement = this.highlightedElement; |
|
this.highlightedElement = element; |
|
|
|
this.show(); |
|
|
|
|
|
this.highlightedElement.onHighlighted(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
show() { |
|
if (this.node && this.node.parentElement) { |
|
return; |
|
} |
|
|
|
this.attachNode(); |
|
|
|
window.setTimeout(() => { |
|
this.node.style.opacity = `${this.options.opacity}`; |
|
this.node.style.position = 'fixed'; |
|
this.node.style.left = '0'; |
|
this.node.style.top = '0'; |
|
this.node.style.bottom = '0'; |
|
this.node.style.right = '0'; |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
getHighlightedElement() { |
|
return this.highlightedElement; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
getLastHighlightedElement() { |
|
return this.lastHighlightedElement; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
clear(immediate = false) { |
|
|
|
if (this.options.onReset) { |
|
this.options.onReset(this.highlightedElement); |
|
} |
|
|
|
|
|
if (this.highlightedElement) { |
|
const hideStage = true; |
|
this.highlightedElement.onDeselected(hideStage); |
|
} |
|
|
|
this.highlightedElement = null; |
|
this.lastHighlightedElement = null; |
|
|
|
if (!this.node) { |
|
return; |
|
} |
|
|
|
|
|
this.window.clearTimeout(this.hideTimer); |
|
|
|
if (this.options.animate && !immediate) { |
|
this.node.style.opacity = '0'; |
|
this.hideTimer = this.window.setTimeout(this.removeNode, ANIMATION_DURATION_MS); |
|
} else { |
|
this.removeNode(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
removeNode() { |
|
if (this.node && this.node.parentElement) { |
|
this.node.parentElement.removeChild(this.node); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
refresh() { |
|
|
|
if (!this.highlightedElement) { |
|
return; |
|
} |
|
|
|
|
|
this.highlightedElement.showPopover(); |
|
this.highlightedElement.showStage(); |
|
} |
|
} |
|
|