kamrify's picture
Buttons in the popover
5aa283f
raw
history blame
4.1 kB
import Overlay from './overlay';
import Element from './element';
import './polyfill';
/**
* Plugin class that drives the plugin
*/
export default class Sholo {
/**
* @param options
*/
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 = []; // steps to be presented if any
this.currentStep = 0; // index for the currently highlighted step
this.onScroll = this.onScroll.bind(this);
this.onResize = this.onResize.bind(this);
this.onKeyUp = this.onKeyUp.bind(this);
this.onClick = this.onClick.bind(this);
// Event bindings
this.bind();
}
/**
* Binds any DOM events listeners
* @todo: add throttling in all the listeners
*/
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);
}
/**
* Removes the popover if clicked outside the highlighted element
* or outside the
* @param e
*/
onClick(e) {
if (!this.hasHighlightedElement()) {
// Has no highlighted element so ignore the click
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);
// Remove the overlay If clicked outside the highlighted element
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;
}
/**
* Handler for the onScroll event on document
* Refreshes without animation on scroll to make sure
* that the highlighted part travels with the scroll
*/
onScroll() {
this.overlay.refresh(false);
}
/**
* Handler for the onResize DOM event
* Refreshes with animation on scroll to make sure that
* the highlighted part travels with the width change of window
*/
onResize() {
// Refresh with animation
this.overlay.refresh(true);
}
/**
* Clears the overlay on escape key process
* @param event
*/
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]);
}
/**
* Highlights the given selector
* @param selector
*/
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');
}
}