Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup public/private API #430

Merged
merged 1 commit into from
Jul 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 62 additions & 59 deletions src/js/step.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,17 @@ export class Step extends Evented {
super(tour, options);
this.tour = tour;
bindMethods.call(this, [
'_scrollTo',
'_setupElements',
'_show',
'cancel',
'complete',
'destroy',
'hide',
'isOpen',
'scrollTo',
'setupElements',
'show'
]);
this.setOptions(options);
this._setOptions(options);
this.bindAdvance = bindAdvance.bind(this);
this.bindButtonEvents = bindButtonEvents.bind(this);
this.bindCancelLink = bindCancelLink.bind(this);
Expand Down Expand Up @@ -209,60 +209,6 @@ export class Step extends Evented {
);
}

/**
* Create the element and set up the tippy instance
*/
setupElements() {
if (!isUndefined(this.el)) {
this.destroy();
}

this.el = this._createTooltipContent();

this._addKeyDownHandler(this.el);

if (this.options.advanceOn) {
this.bindAdvance();
}

this.setupTooltip();
}

/**
* If a custom scrollToHandler is defined, call that, otherwise do the generic
* scrollIntoView call.
*
* @param {boolean|Object} scrollToOptions If true, uses the default `scrollIntoView`,
* if an object, passes that object as the params to `scrollIntoView` i.e. `{ behavior: 'smooth', block: 'center' }`
*/
scrollTo(scrollToOptions) {
const { element } = this.parseAttachTo();

if (isFunction(this.options.scrollToHandler)) {
this.options.scrollToHandler(element);
} else if (isElement(element)) {
element.scrollIntoView(scrollToOptions);
}
}

/**
* Sets the options for the step, maps `when` to events, sets up buttons
* @param {Object} options The options for the step
*/
setOptions(options = {}) {
this.options = options;
const { when } = this.options;

this.destroy();
this.id = this.options.id || `step-${uniqueId()}`;

if (when) {
Object.entries(when).forEach(([event, handler]) => {
this.on(event, handler, this);
});
}
}

/**
* Wraps `_show` and ensures `beforeShowPromise` resolves before calling show
* @return {*|Promise}
Expand Down Expand Up @@ -450,6 +396,63 @@ export class Step extends Evented {
return element;
}

/**
* If a custom scrollToHandler is defined, call that, otherwise do the generic
* scrollIntoView call.
*
* @param {boolean|Object} scrollToOptions If true, uses the default `scrollIntoView`,
* if an object, passes that object as the params to `scrollIntoView` i.e. `{ behavior: 'smooth', block: 'center' }`
* @private
*/
_scrollTo(scrollToOptions) {
const { element } = this.parseAttachTo();

if (isFunction(this.options.scrollToHandler)) {
this.options.scrollToHandler(element);
} else if (isElement(element)) {
element.scrollIntoView(scrollToOptions);
}
}

/**
* Sets the options for the step, maps `when` to events, sets up buttons
* @param {Object} options The options for the step
* @private
*/
_setOptions(options = {}) {
this.options = options;
const { when } = this.options;

this.destroy();
this.id = this.options.id || `step-${uniqueId()}`;

if (when) {
Object.entries(when).forEach(([event, handler]) => {
this.on(event, handler, this);
});
}
}

/**
* Create the element and set up the tippy instance
* @private
*/
_setupElements() {
if (!isUndefined(this.el)) {
this.destroy();
}

this.el = this._createTooltipContent();

this._addKeyDownHandler(this.el);

if (this.options.advanceOn) {
this.bindAdvance();
}

this.setupTooltip();
}

/**
* Triggers `before-show`, generates the tooltip DOM content,
* sets up a tippy instance for the tooltip, then triggers `show`.
Expand All @@ -460,7 +463,7 @@ export class Step extends Evented {
this.trigger('before-show');

if (!this.el) {
this.setupElements();
this._setupElements();
}

this.target.classList.add('shepherd-enabled', 'shepherd-target');
Expand All @@ -469,7 +472,7 @@ export class Step extends Evented {

if (this.options.scrollTo) {
setTimeout(() => {
this.scrollTo(this.options.scrollTo);
this._scrollTo(this.options.scrollTo);
});
}

Expand Down
96 changes: 49 additions & 47 deletions src/js/tour.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class Tour extends Evented {
}

if (!(step instanceof Step)) {
step = this.setupStep(step, name);
step = this._setupStep(step, name);
} else {
step.tour = this;
}
Expand All @@ -115,51 +115,26 @@ export class Tour extends Evented {
}

/**
* Calls done() triggering the 'cancel' event
* Calls _done() triggering the 'cancel' event
* If `confirmCancel` is true, will show a window.confirm before cancelling
*/
cancel() {
if (this.options.confirmCancel) {
const cancelMessage = this.options.confirmCancelMessage || 'Are you sure you want to stop the tour?';
const stopTour = window.confirm(cancelMessage);
if (stopTour) {
this.done('cancel');
this._done('cancel');
}
} else {
this.done('cancel');
this._done('cancel');
}
}

/**
* Calls done() triggering the `complete` event
* Calls _done() triggering the `complete` event
*/
complete() {
this.done('complete');
}

/**
* Called whenever the tour is cancelled or completed, basically anytime we exit the tour
* @param {String} event The event name to trigger
*/
done(event) {
if (Array.isArray(this.steps)) {
this.steps.forEach((step) => step.destroy());
}

cleanupStepEventListeners.call(this);
cleanupSteps(this.tourObject);

this.trigger(event);

Shepherd.activeTour = null;
this._removeBodyAttrs();
this.trigger('inactive', { tour: this });

if (this.options.disableScroll) {
clearAllBodyScrollLocks();
}

this.modal.cleanup();
this._done('complete');
}

/**
Expand Down Expand Up @@ -243,22 +218,6 @@ export class Tour extends Evented {
}
}

/**
* Setup a new step object
* @param {Object} stepOptions The object describing the options for the step
* @param {String|Number} name The string or number to use as the `id` for the step
* @return {Step} The step instance
*/
setupStep(stepOptions, name) {
if (isString(name) || isNumber(name)) {
stepOptions.id = name.toString();
}

stepOptions = Object.assign({}, this.options.defaultStepOptions, stepOptions);

return new Step(this, stepOptions);
}

beforeShowStep(step) {
this.modal.setupForStep(step);
this._styleTargetElementForStep(step);
Expand Down Expand Up @@ -307,6 +266,32 @@ export class Tour extends Evented {
this.next();
}

/**
* Called whenever the tour is cancelled or completed, basically anytime we exit the tour
* @param {String} event The event name to trigger
* @private
*/
_done(event) {
if (Array.isArray(this.steps)) {
this.steps.forEach((step) => step.destroy());
}

cleanupStepEventListeners.call(this);
cleanupSteps(this.tourObject);

this.trigger(event);

Shepherd.activeTour = null;
this._removeBodyAttrs();
this.trigger('inactive', { tour: this });

if (this.options.disableScroll) {
clearAllBodyScrollLocks();
}

this.modal.cleanup();
}

/**
* Make this tour "active"
* @private
Expand All @@ -319,6 +304,23 @@ export class Tour extends Evented {
Shepherd.activeTour = this;
}

/**
* Setup a new step object
* @param {Object} stepOptions The object describing the options for the step
* @param {String|Number} name The string or number to use as the `id` for the step
* @return {Step} The step instance
* @private
*/
_setupStep(stepOptions, name) {
if (isString(name) || isNumber(name)) {
stepOptions.id = name.toString();
}

stepOptions = Object.assign({}, this.options.defaultStepOptions, stepOptions);

return new Step(this, stepOptions);
}

/**
* Modulates the styles of the passed step's target element, based on the step's options and
* the tour's `modal` option, to visually emphasize the element
Expand Down
22 changes: 11 additions & 11 deletions test/unit/step.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,14 +274,14 @@ describe('Tour | Step', () => {
it('binds the expected methods', () => {
const step = new Step();
const methods = [
'_scrollTo',
'_setupElements',
'_show',
'cancel',
'complete',
'destroy',
'hide',
'isOpen',
'scrollTo',
'setupElements',
'show'
];
methods.forEach((method) => {
Expand Down Expand Up @@ -369,14 +369,14 @@ describe('Tour | Step', () => {
});
});

describe('setupElements()', () => {
describe('_setupElements()', () => {
it('calls destroy on the step if the content element is already set', () => {
const step = new Step();
let destroyCalled = false;
step.el = document.createElement('a');
step.destroy = () => destroyCalled = true;
step.setupElements();
expect(destroyCalled, 'setupElements method called destroy with element set').toBeTruthy();
step._setupElements();
expect(destroyCalled, '_setupElements method called destroy with element set').toBeTruthy();
});

it('calls destroy on the tooltip if it already exists', () => {
Expand All @@ -385,8 +385,8 @@ describe('Tour | Step', () => {
step.tooltip = {
destroy() { destroyCalled = true; }
};
step.setupElements();
expect(destroyCalled, 'setupElements method called destroy on the existing tooltip').toBe(true);
step._setupElements();
expect(destroyCalled, '_setupElements method called destroy on the existing tooltip').toBe(true);
});

it('calls bindAdvance() if advanceOn passed', () => {
Expand All @@ -396,13 +396,13 @@ describe('Tour | Step', () => {
advanceOn: { selector: '.click-test', event: 'test' }
});
const bindFunction = spy(step, 'bindAdvance');
step.setupElements();
step._setupElements();

expect(bindFunction.called).toBeTruthy();
});
});

describe('scrollTo()', () => {
describe('_scrollTo()', () => {
it('calls the scroll native method', () => {
const div = document.createElement('div');
let handlerCalled = false;
Expand All @@ -413,7 +413,7 @@ describe('Tour | Step', () => {
});
div.scrollIntoView = () => handlerCalled = true;

step.scrollTo();
step._scrollTo();
expect(handlerCalled).toBeTruthy();
});

Expand All @@ -423,7 +423,7 @@ describe('Tour | Step', () => {
scrollToHandler: () => handlerAdded = true
});

step.scrollTo();
step._scrollTo();
expect(handlerAdded).toBeTruthy();
});
});
Expand Down
Loading