|
import Overlay from './overlay'; |
|
import Element from './element'; |
|
import './polyfill'; |
|
|
|
|
|
|
|
|
|
export default class Sholo { |
|
|
|
|
|
|
|
constructor(options = {}) { |
|
this.options = Object.assign({ |
|
padding: 10, |
|
animate: true, |
|
opacity: 0.75, |
|
}, options); |
|
|
|
this.overlay = new Overlay(options); |
|
|
|
this.document = document; |
|
this.window = window; |
|
|
|
this.steps = []; |
|
this.currentStep = 0; |
|
|
|
this.onScroll = this.onScroll.bind(this); |
|
this.onResize = this.onResize.bind(this); |
|
this.onKeyUp = this.onKeyUp.bind(this); |
|
this.onClick = this.onClick.bind(this); |
|
|
|
|
|
this.bind(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
bind() { |
|
this.document.addEventListener('scroll', this.onScroll, false); |
|
this.document.addEventListener('DOMMouseScroll', this.onScroll, false); |
|
this.window.addEventListener('resize', this.onResize, false); |
|
this.window.addEventListener('keyup', this.onKeyUp, false); |
|
this.window.addEventListener('click', this.onClick, false); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
onClick(e) { |
|
if (!this.hasHighlightedElement()) { |
|
|
|
return; |
|
} |
|
|
|
const highlightedElement = this.overlay.getHighlightedElement(); |
|
const popover = document.getElementById('sholo-popover-item'); |
|
|
|
const clickedHighlightedElement = highlightedElement.node.contains(e.target); |
|
const clickedPopover = popover && popover.contains(e.target); |
|
|
|
|
|
if (!clickedHighlightedElement && !clickedPopover) { |
|
this.overlay.clear(); |
|
return; |
|
} |
|
|
|
const nextClicked = e.target.classList.contains('sholo-next-btn'); |
|
if (nextClicked) { |
|
this.currentStep += 1; |
|
this.overlay.highlight(this.steps[this.currentStep]); |
|
} |
|
} |
|
|
|
hasHighlightedElement() { |
|
const highlightedElement = this.overlay.getHighlightedElement(); |
|
return highlightedElement && highlightedElement.node; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
onScroll() { |
|
this.overlay.refresh(false); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
onResize() { |
|
|
|
this.overlay.refresh(true); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
onKeyUp(event) { |
|
if (event.keyCode === 27) { |
|
this.overlay.clear(); |
|
} |
|
} |
|
|
|
defineSteps(steps) { |
|
this.steps = []; |
|
|
|
steps.forEach((step, index) => { |
|
if (!step.element) { |
|
throw new Error(`Element (query selector or a dom element) missing in step ${index}`); |
|
} |
|
|
|
const domElement = Sholo.findDomElement(step.element); |
|
const element = new Element(domElement, Object.assign({}, this.options, step)); |
|
|
|
this.steps.push(element); |
|
}); |
|
} |
|
|
|
start() { |
|
if (!this.steps || this.steps.length === 0) { |
|
throw new Error('There are no steps defined to iterate'); |
|
} |
|
|
|
this.currentStep = 0; |
|
this.overlay.highlight(this.steps[0]); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
highlight(selector) { |
|
const domElement = Sholo.findDomElement(selector); |
|
|
|
const element = new Element(domElement, this.options); |
|
this.overlay.highlight(element); |
|
} |
|
|
|
static findDomElement(selector) { |
|
if (typeof selector === 'string') { |
|
return document.querySelector(selector); |
|
} |
|
|
|
if (typeof selector === 'object') { |
|
return selector; |
|
} |
|
|
|
throw new Error('Element can only be string or the dom element'); |
|
} |
|
} |
|
|