Add example for asynchronous tour
Browse files- index.html +114 -0
- src/driver.ts +43 -10
- src/state.ts +4 -4
index.html
CHANGED
@@ -192,6 +192,7 @@
|
|
192 |
<div class="buttons">
|
193 |
<button id="custom-classes">Custom Classes</button>
|
194 |
<button id="popover-hook">Popover Hook</button>
|
|
|
195 |
</div>
|
196 |
|
197 |
<h2>Tour Feature</h2>
|
@@ -199,6 +200,7 @@
|
|
199 |
<div class="buttons">
|
200 |
<button id="basic-tour">Animated Tour</button>
|
201 |
<button id="non-animated-tour">Non-Animated Tour</button>
|
|
|
202 |
</div>
|
203 |
|
204 |
<ul>
|
@@ -396,6 +398,97 @@ npm install driver.js</pre
|
|
396 |
driverObj.drive();
|
397 |
});
|
398 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
399 |
document.getElementById("basic-tour").addEventListener("click", () => {
|
400 |
const driverObj = driver({
|
401 |
steps: basicTourSteps,
|
@@ -524,6 +617,27 @@ npm install driver.js</pre
|
|
524 |
});
|
525 |
});
|
526 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
527 |
document.getElementById("custom-classes").addEventListener("click", () => {
|
528 |
const driverObj = driver({
|
529 |
popoverClass: "custom-driver-popover",
|
|
|
192 |
<div class="buttons">
|
193 |
<button id="custom-classes">Custom Classes</button>
|
194 |
<button id="popover-hook">Popover Hook</button>
|
195 |
+
<button id="padding-change">Padding Change</button>
|
196 |
</div>
|
197 |
|
198 |
<h2>Tour Feature</h2>
|
|
|
200 |
<div class="buttons">
|
201 |
<button id="basic-tour">Animated Tour</button>
|
202 |
<button id="non-animated-tour">Non-Animated Tour</button>
|
203 |
+
<button id="async-tour">Asynchronous Tour</button>
|
204 |
</div>
|
205 |
|
206 |
<ul>
|
|
|
398 |
driverObj.drive();
|
399 |
});
|
400 |
|
401 |
+
document.getElementById("async-tour").addEventListener("click", () => {
|
402 |
+
const driverObj = driver({
|
403 |
+
animate: true,
|
404 |
+
backdropColor: "blue",
|
405 |
+
opacity: 0.3,
|
406 |
+
onDeselected: (element => {
|
407 |
+
if (element?.classList?.contains('dynamic-el')) {
|
408 |
+
element?.parentElement?.removeChild(element);
|
409 |
+
}
|
410 |
+
}),
|
411 |
+
steps: [
|
412 |
+
{
|
413 |
+
element: ".page-header",
|
414 |
+
popover: {
|
415 |
+
title: "Async Driver.js",
|
416 |
+
description:
|
417 |
+
"Driver.js has been written from the ground up. The new version is more powerful, has less surprises, more customizable and tons of new features.",
|
418 |
+
side: "bottom",
|
419 |
+
align: "start",
|
420 |
+
},
|
421 |
+
},
|
422 |
+
{
|
423 |
+
element: ".page-header h1",
|
424 |
+
popover: {
|
425 |
+
title: "Async Test",
|
426 |
+
description: "By overriding `onNextClick` you get control over the tour.",
|
427 |
+
side: "left",
|
428 |
+
align: "start",
|
429 |
+
onNextClick: () => {
|
430 |
+
const newDiv = document.querySelector('.dynamic-el') || document.createElement('div');
|
431 |
+
|
432 |
+
newDiv.innerHTML = 'This is a new Element';
|
433 |
+
newDiv.style.display = 'block';
|
434 |
+
newDiv.style.padding = '20px';
|
435 |
+
newDiv.style.backgroundColor = 'black';
|
436 |
+
newDiv.style.color = 'white';
|
437 |
+
newDiv.style.fontSize = '14px';
|
438 |
+
newDiv.style.position = 'fixed';
|
439 |
+
newDiv.style.top = `${Math.random() * (500 - 30) + 30}px`;
|
440 |
+
newDiv.style.left = `${Math.random() * (500 - 30) + 30}px`;
|
441 |
+
newDiv.className = 'dynamic-el';
|
442 |
+
|
443 |
+
document.body.appendChild(newDiv);
|
444 |
+
|
445 |
+
driverObj.moveNext();
|
446 |
+
}
|
447 |
+
},
|
448 |
+
},
|
449 |
+
{
|
450 |
+
element: '.dynamic-el',
|
451 |
+
popover: {
|
452 |
+
title: "Dynamic Elements",
|
453 |
+
description: "This was created before we moved here"
|
454 |
+
}
|
455 |
+
},
|
456 |
+
{
|
457 |
+
element: ".page-header sup",
|
458 |
+
popover: {
|
459 |
+
title: "Improved Hooks",
|
460 |
+
description:
|
461 |
+
"Unlike the older version, new version doesn't work with z-indexes so no more positional issues.",
|
462 |
+
side: "bottom",
|
463 |
+
align: "start",
|
464 |
+
},
|
465 |
+
},
|
466 |
+
{
|
467 |
+
popover: {
|
468 |
+
title: "No Element",
|
469 |
+
description: "You can now have popovers without elements as well",
|
470 |
+
},
|
471 |
+
},
|
472 |
+
{
|
473 |
+
element: "#scrollable-area",
|
474 |
+
popover: {
|
475 |
+
title: "Scrollable Areas",
|
476 |
+
description: "There are no issues with scrollable element tours as well.",
|
477 |
+
},
|
478 |
+
},
|
479 |
+
{
|
480 |
+
element: "#third-scroll-paragraph",
|
481 |
+
popover: {
|
482 |
+
title: "Nested Scrolls",
|
483 |
+
description: "Even the nested scrollable elements work now.",
|
484 |
+
},
|
485 |
+
},
|
486 |
+
],
|
487 |
+
});
|
488 |
+
|
489 |
+
driverObj.drive();
|
490 |
+
});
|
491 |
+
|
492 |
document.getElementById("basic-tour").addEventListener("click", () => {
|
493 |
const driverObj = driver({
|
494 |
steps: basicTourSteps,
|
|
|
617 |
});
|
618 |
});
|
619 |
|
620 |
+
document.getElementById("padding-change").addEventListener("click", () => {
|
621 |
+
const driverObj = driver({
|
622 |
+
stagePadding: 0,
|
623 |
+
popoverOffset: 20,
|
624 |
+
stageRadius: 10
|
625 |
+
});
|
626 |
+
|
627 |
+
driverObj.highlight({
|
628 |
+
element: "#padding-change",
|
629 |
+
popover: {
|
630 |
+
title: "Page Title",
|
631 |
+
description: "Body of the popover",
|
632 |
+
side: "bottom",
|
633 |
+
align: "start",
|
634 |
+
onPopoverRendered: popover => {
|
635 |
+
popover.title.innerText = "Modified";
|
636 |
+
},
|
637 |
+
},
|
638 |
+
});
|
639 |
+
});
|
640 |
+
|
641 |
document.getElementById("custom-classes").addEventListener("click", () => {
|
642 |
const driverObj = driver({
|
643 |
popoverClass: "custom-driver-popover",
|
src/driver.ts
CHANGED
@@ -24,9 +24,39 @@ export function driver(options: Config = {}) {
|
|
24 |
destroy();
|
25 |
}
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
function handleArrowLeft() {
|
28 |
const steps = getConfig("steps") || [];
|
29 |
-
const currentStepIndex = getState("
|
30 |
if (typeof currentStepIndex === "undefined") {
|
31 |
return;
|
32 |
}
|
@@ -38,18 +68,19 @@ export function driver(options: Config = {}) {
|
|
38 |
}
|
39 |
|
40 |
function handleArrowRight() {
|
41 |
-
const
|
42 |
-
const
|
43 |
-
|
|
|
44 |
return;
|
45 |
}
|
46 |
|
47 |
-
const
|
48 |
-
if (
|
49 |
-
|
50 |
-
} else {
|
51 |
-
destroy();
|
52 |
}
|
|
|
|
|
53 |
}
|
54 |
|
55 |
function init() {
|
@@ -81,7 +112,7 @@ export function driver(options: Config = {}) {
|
|
81 |
destroy();
|
82 |
}
|
83 |
|
84 |
-
setState("
|
85 |
|
86 |
const currentStep = steps[stepIndex];
|
87 |
const hasNextStep = steps[stepIndex + 1];
|
@@ -152,6 +183,8 @@ export function driver(options: Config = {}) {
|
|
152 |
init();
|
153 |
drive(stepIndex);
|
154 |
},
|
|
|
|
|
155 |
highlight: (step: DriveStep) => {
|
156 |
init();
|
157 |
highlight({
|
|
|
24 |
destroy();
|
25 |
}
|
26 |
|
27 |
+
function moveNext() {
|
28 |
+
const activeIndex = getState('activeIndex');
|
29 |
+
const steps = getConfig('steps') || [];
|
30 |
+
if (typeof activeIndex === 'undefined') {
|
31 |
+
return;
|
32 |
+
}
|
33 |
+
|
34 |
+
const nextStepIndex = activeIndex + 1;
|
35 |
+
if (steps[nextStepIndex]) {
|
36 |
+
drive(nextStepIndex);
|
37 |
+
} else {
|
38 |
+
destroy();
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
function movePrevious() {
|
43 |
+
const activeIndex = getState('activeIndex');
|
44 |
+
const steps = getConfig('steps') || [];
|
45 |
+
if (typeof activeIndex === 'undefined') {
|
46 |
+
return;
|
47 |
+
}
|
48 |
+
|
49 |
+
const previousStepIndex = activeIndex - 1;
|
50 |
+
if (steps[previousStepIndex]) {
|
51 |
+
drive(previousStepIndex);
|
52 |
+
} else {
|
53 |
+
destroy();
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
function handleArrowLeft() {
|
58 |
const steps = getConfig("steps") || [];
|
59 |
+
const currentStepIndex = getState("activeIndex");
|
60 |
if (typeof currentStepIndex === "undefined") {
|
61 |
return;
|
62 |
}
|
|
|
68 |
}
|
69 |
|
70 |
function handleArrowRight() {
|
71 |
+
const activeIndex = getState("activeIndex");
|
72 |
+
const activeStep = getState("activeStep");
|
73 |
+
const activeElement = getState("activeElement");
|
74 |
+
if (typeof activeIndex === "undefined" || typeof activeStep === "undefined") {
|
75 |
return;
|
76 |
}
|
77 |
|
78 |
+
const onNextClick = activeStep.popover?.onNextClick || getConfig("onNextClick");
|
79 |
+
if (onNextClick) {
|
80 |
+
return onNextClick(activeElement, activeStep);
|
|
|
|
|
81 |
}
|
82 |
+
|
83 |
+
moveNext();
|
84 |
}
|
85 |
|
86 |
function init() {
|
|
|
112 |
destroy();
|
113 |
}
|
114 |
|
115 |
+
setState("activeIndex", stepIndex);
|
116 |
|
117 |
const currentStep = steps[stepIndex];
|
118 |
const hasNextStep = steps[stepIndex + 1];
|
|
|
183 |
init();
|
184 |
drive(stepIndex);
|
185 |
},
|
186 |
+
moveNext,
|
187 |
+
movePrevious,
|
188 |
highlight: (step: DriveStep) => {
|
189 |
init();
|
190 |
highlight({
|
src/state.ts
CHANGED
@@ -6,18 +6,18 @@ export type State = {
|
|
6 |
// Whether driver is initialized or not
|
7 |
isInitialized?: boolean;
|
8 |
// Index of the currently active step in driver tour
|
9 |
-
|
10 |
|
11 |
// Used to bounce the resize event
|
12 |
resizeTimeout?: number;
|
13 |
|
14 |
// Used while transitioning between stages
|
15 |
-
previousElement?: Element;
|
16 |
activeElement?: Element;
|
17 |
-
transitionCallback?: () => void;
|
18 |
-
|
19 |
activeStep?: DriveStep;
|
|
|
20 |
previousStep?: DriveStep;
|
|
|
|
|
21 |
|
22 |
activeStagePosition?: StageDefinition;
|
23 |
stageSvg?: SVGSVGElement;
|
|
|
6 |
// Whether driver is initialized or not
|
7 |
isInitialized?: boolean;
|
8 |
// Index of the currently active step in driver tour
|
9 |
+
activeIndex?: number;
|
10 |
|
11 |
// Used to bounce the resize event
|
12 |
resizeTimeout?: number;
|
13 |
|
14 |
// Used while transitioning between stages
|
|
|
15 |
activeElement?: Element;
|
|
|
|
|
16 |
activeStep?: DriveStep;
|
17 |
+
previousElement?: Element;
|
18 |
previousStep?: DriveStep;
|
19 |
+
transitionCallback?: () => void;
|
20 |
+
|
21 |
|
22 |
activeStagePosition?: StageDefinition;
|
23 |
stageSvg?: SVGSVGElement;
|