@rently-team/shepherd.js
Version:
Guide your users through a tour of your app.
69 lines (60 loc) • 1.9 kB
text/typescript
import type { Step } from '../step.ts';
import { isUndefined } from './type-check.ts';
/**
* Sets up the handler to determine if we should advance the tour
* @param step The step instance
* @param selector
* @private
*/
function _setupAdvanceOnHandler(step: Step, selector?: string) {
return (event: Event) => {
if (step.isOpen()) {
const targetIsEl = step.el && event.currentTarget === step.el;
const targetIsSelector =
!isUndefined(selector) &&
(event.currentTarget as HTMLElement).matches(selector);
if (targetIsSelector || targetIsEl) {
step.tour.next();
}
}
};
}
/**
* Bind the event handler for advanceOn
* @param step The step instance
*/
export function bindAdvance(step: Step) {
// An empty selector matches the step element
const { event, selector } = step.options.advanceOn || {};
if (event) {
const handler = _setupAdvanceOnHandler(step, selector);
// TODO: this should also bind/unbind on show/hide
let el: Element | null = null;
if (!isUndefined(selector)) {
el = document.querySelector(selector);
if (!el) {
return console.error(
`No element was found for the selector supplied to advanceOn: ${selector}`
);
}
step.advanceEl = el as HTMLElement;
}
if (el) {
el.removeEventListener(event, handler);
el.addEventListener(event, handler);
step.on('destroy', () => {
return (el as HTMLElement).removeEventListener(event, handler);
});
} else {
document.body.removeEventListener(event, handler);
document.body.addEventListener(event, handler, true);
step.on('destroy', () => {
return document.body.removeEventListener(event, handler, true);
});
}
} else {
return console.error(
'advanceOn was defined, but no event name was passed.'
);
}
}