kamrify commited on
Commit
ec183be
·
1 Parent(s): e9a1e79

Add example for asynchronous tour

Browse files
Files changed (3) hide show
  1. index.html +114 -0
  2. src/driver.ts +43 -10
  3. 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("currentStepIndex");
30
  if (typeof currentStepIndex === "undefined") {
31
  return;
32
  }
@@ -38,18 +68,19 @@ export function driver(options: Config = {}) {
38
  }
39
 
40
  function handleArrowRight() {
41
- const steps = getConfig("steps") || [];
42
- const currentStepIndex = getState("currentStepIndex");
43
- if (typeof currentStepIndex === "undefined") {
 
44
  return;
45
  }
46
 
47
- const nextStepIndex = currentStepIndex + 1;
48
- if (steps[nextStepIndex]) {
49
- drive(nextStepIndex);
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("currentStepIndex", stepIndex);
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
- currentStepIndex?: number;
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;