Skip to content

Commit

Permalink
Add Hints APIs and the remaining methods
Browse files Browse the repository at this point in the history
  • Loading branch information
binrysearch committed Jun 29, 2024
1 parent a10ec7d commit 3238d9b
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 44 deletions.
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { version } from "../package.json";
import { Hint } from "./packages/hint/hint";
import { Tour } from "./packages/tour";

/**
Expand All @@ -12,6 +13,9 @@ const introJs = {
tour: (elementOrSelector?: string | HTMLElement) =>
new Tour(elementOrSelector),

hint: (elementOrSelector?: string | HTMLElement) =>
new Hint(elementOrSelector),

/**
* Current Intro.js version
*/
Expand Down
226 changes: 207 additions & 19 deletions src/packages/hint/hint.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { Package } from "../package";
import { getDefaultHintOptions, HintOptions } from "./option";
import { HintItem } from "./hintItem";
import { fetchHintItems, HintItem } from "./hintItem";
import { setOption, setOptions } from "src/option";
import isFunction from "../../util/isFunction";
import debounce from "src/util/debounce";
import debounce from "../../util/debounce";
import { reAlignHints } from "./position";
import DOMEvent from "src/util/DOMEvent";
import { getContainerElement } from "src/util/containerElement";
import { renderHints } from "./render";
import { hideHint, hideHints } from "./hide";
import { showHint, showHints } from "./show";
import { removeHint, removeHints } from "./remove";
import { showHintDialog } from "./tooltip";

type hintsAddedCallback = (this: Hint) => void | Promise<void>;
type hintClickCallback = (
Expand All @@ -20,18 +26,35 @@ export class Hint implements Package<HintOptions> {
private _hints: HintItem[] = [];
private readonly _targetElement: HTMLElement;
private _options: HintOptions;

private readonly callbacks: {
hintsAdded?: hintsAddedCallback;
hintClick?: hintClickCallback;
hintClose?: hintCloseCallback;
} = {};

// Event handlers
private _hintsAutoRefreshFunction?: () => void;

public constructor(targetElement: HTMLElement) {
this._targetElement = targetElement;
this._options = getDefaultHintOptions();
/**
* Create a new Hint instance
* @param elementOrSelector Optional target element or CSS query to start the Hint on
* @param options Optional Hint options
*/
public constructor(
elementOrSelector?: string | HTMLElement,
options?: Partial<HintOptions>
) {
this._targetElement = getContainerElement(elementOrSelector);
this._options = options
? setOptions(this._options, options)
: getDefaultHintOptions();
}

/**
* Get the callback function for the provided callback name
* @param callbackName The name of the callback
*/
callback<K extends keyof typeof this.callbacks>(
callbackName: K
): (typeof this.callbacks)[K] | undefined {
Expand All @@ -42,28 +65,141 @@ export class Hint implements Package<HintOptions> {
return undefined;
}

/**
* Get the target element for the Hint
*/
getTargetElement(): HTMLElement {
return this._targetElement;
}

/**
* Get the Hint items
*/
getHints(): HintItem[] {
return this._hints;
}

/**
* Get the Hint item for the provided step ID
* @param stepId The step ID
*/
getHint(stepId: number): HintItem | undefined {
return this._hints[stepId];
}

/**
* Set the Hint items
* @param hints The Hint items
*/
setHints(hints: HintItem[]): this {
this._hints = hints;
return this;
}

/**
* Add a Hint item
* @param hint The Hint item
*/
addHint(hint: HintItem): this {
this._hints.push(hint);
return this;
}

/**
* Render hints on the page
*/
async render(): Promise<this> {
if (!this.isActive()) {
return this;
}

fetchHintItems(this);
await renderHints(this);
return this;
}

/**
* @deprecated renderHints() is deprecated, please use render() instead
*/
async addHints() {
return this.render();
}

/**
* Hide a specific hint on the page
* @param stepId The hint step ID
*/
async hideHint(stepId: number) {
await hideHint(this, stepId);
return this;
}

/**
* Hide all hints on the page
*/
async hideHints() {
await hideHints(this);
return this;
}

/**
* Show a specific hint on the page
* @param stepId The hint step ID
*/
showHint(stepId: number) {
showHint(stepId);
return this;
}

/**
* Show all hints on the page
*/
async showHints() {
await showHints(this);
return this;
}

/**
* Destroys and removes all hint elements on the page
* Useful when you want to destroy the elements and add them again (e.g. a modal or popup)
*/
destroy() {
removeHints(this);
return this;
}

/**
* @deprecated removeHints() is deprecated, please use destroy() instead
*/
removeHints() {
this.destroy();
return this;
}

/**
* Remove one single hint element from the page
* Useful when you want to destroy the element and add them again (e.g. a modal or popup)
* Use removeHints if you want to remove all elements.
*
* @param stepId The hint step ID
*/
removeHint(stepId: number) {
removeHint(stepId);
return this;
}

/**
* Show hint dialog for a specific hint
* @param stepId The hint step ID
*/
async showHintDialog(stepId: number) {
await showHintDialog(this, stepId);
return this;
}

/**
* Enable hint auto refresh on page scroll and resize for hints
*/
enableHintAutoRefresh(): this {
const hintAutoRefreshInterval = this.getOption("hintAutoRefreshInterval");
if (hintAutoRefreshInterval >= 0) {
Expand All @@ -73,71 +209,123 @@ export class Hint implements Package<HintOptions> {
);

DOMEvent.on(window, "scroll", this._hintsAutoRefreshFunction, true);
DOMEvent.on(window, "resize", this._hintsAutoRefreshFunction, true);
}

return this;
}

/**
* Disable hint auto refresh on page scroll and resize for hints
*/
disableHintAutoRefresh(): this {
if (this._hintsAutoRefreshFunction) {
DOMEvent.off(window, "scroll", this._hintsAutoRefreshFunction, true);
DOMEvent.on(window, "resize", this._hintsAutoRefreshFunction, true);

this._hintsAutoRefreshFunction = undefined;
}

return this;
}

/**
* Get specific Hint option
* @param key The option key
*/
getOption<K extends keyof HintOptions>(key: K): HintOptions[K] {
return this._options[key];
}

/**
* Set Hint options
* @param partialOptions Hint options
*/
setOptions(partialOptions: Partial<HintOptions>): this {
this._options = setOptions(this._options, partialOptions);
return this;
}

/**
* Set specific Hint option
* @param key Option key
* @param value Option value
*/
setOption<K extends keyof HintOptions>(key: K, value: HintOptions[K]): this {
this._options = setOption(this._options, key, value);
return this;
}

/**
* Clone the Hint instance
*/
clone(): ThisType<this> {
return new Hint(this._targetElement);
return new Hint(this._targetElement, this._options);
}

/**
* Returns true if the Hint is active
*/
isActive(): boolean {
return this.getOption("isActive");
}

render(): Promise<this> {
throw new Error("Method not implemented.");
}

onhintsadded(providedCallback: hintsAddedCallback) {
if (isFunction(providedCallback)) {
this.callbacks.hintsAdded = providedCallback;
} else {
onHintsAdded(providedCallback: hintsAddedCallback) {
if (!isFunction(providedCallback)) {
throw new Error("Provided callback for onhintsadded was not a function.");
}

this.callbacks.hintsAdded = providedCallback;
return this;
}

onhintclick(providedCallback: hintClickCallback) {
if (isFunction(providedCallback)) {
this.callbacks.hintClick = providedCallback;
} else {
/**
* @deprecated onhintsadded is deprecated, please use onHintsAdded instead
* @param providedCallback callback function
*/
onhintsadded(providedCallback: hintsAddedCallback) {
this.onHintsAdded(providedCallback);
}

/**
* Callback for when hint items are clicked
* @param providedCallback callback function
*/
onHintClick(providedCallback: hintClickCallback) {
if (!isFunction(providedCallback)) {
throw new Error("Provided callback for onhintclick was not a function.");
}

this.callbacks.hintClick = providedCallback;
return this;
}

onhintclose(providedCallback: hintCloseCallback) {
/**
* @deprecated onhintclick is deprecated, please use onHintClick instead
* @param providedCallback
*/
onhintclick(providedCallback: hintClickCallback) {
this.onHintClick(providedCallback);
}

/**
* Callback for when hint items are closed
* @param providedCallback callback function
*/
onHintClose(providedCallback: hintCloseCallback) {
if (isFunction(providedCallback)) {
this.callbacks.hintClose = providedCallback;
} else {
throw new Error("Provided callback for onhintclose was not a function.");
}
return this;
}

/**
* @deprecated onhintclose is deprecated, please use onHintClose instead
* @param providedCallback
*/
onhintclose(providedCallback: hintCloseCallback) {
this.onHintClose(providedCallback);
}
}
6 changes: 0 additions & 6 deletions src/packages/hint/remove.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { Hint } from "./hint";
import { dataStepAttribute } from "./dataAttributes";
import DOMEvent from "src/util/DOMEvent";
import { removeHintTooltip } from "./tooltip";
import { reAlignHints } from "./position";
import { hintElement, hintElements } from "./selector";

/**
Expand All @@ -22,9 +19,6 @@ export function removeHints(hint: Hint) {
removeHint(parseInt(step, 10));
}

DOMEvent.off(document, "click", removeHintTooltip, hint, false);
DOMEvent.off(window, "resize", reAlignHints, hint, true);

hint.disableHintAutoRefresh();
}

Expand Down
Loading

0 comments on commit 3238d9b

Please sign in to comment.