kamrify commited on
Commit
4c98241
·
1 Parent(s): 3833190

Add disallow close functionality

Browse files
Files changed (4) hide show
  1. index.html +34 -10
  2. src/config.ts +2 -0
  3. src/driver.ts +19 -5
  4. src/highlight.ts +8 -9
index.html CHANGED
@@ -57,6 +57,8 @@
57
  display: flex;
58
  margin-top: 20px;
59
  gap: 10px;
 
 
60
  }
61
 
62
  button {
@@ -75,7 +77,10 @@
75
  <p>Rewritten and enhanced version of driver.js</p>
76
 
77
  <div class="buttons">
78
- <button id="highlight-btn">Simple Highlight</button>
 
 
 
79
  <button id="tour-btn">Start Tour</button>
80
  <button id="destroy-btn">Destroy</button>
81
  </div>
@@ -90,24 +95,43 @@
90
  <script type="module">
91
  import { driver } from "./src/driver.ts";
92
 
93
- const driverObj = driver({
94
- animate: true,
95
  });
96
 
97
- document.getElementById("highlight-btn").addEventListener("click", () => {
98
- driverObj.highlight({
99
- element: "h1",
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  });
101
 
102
- window.setTimeout(() => {
 
 
 
 
 
 
 
103
  driverObj.highlight({
104
  element: ".buttons",
105
  });
106
- }, 1000);
107
- });
108
 
109
  document.getElementById("destroy-btn").addEventListener("click", () => {
110
- driverObj.destroy();
111
  });
112
  </script>
113
  </body>
 
57
  display: flex;
58
  margin-top: 20px;
59
  gap: 10px;
60
+ max-width: 500px;
61
+ flex-wrap: wrap;
62
  }
63
 
64
  button {
 
77
  <p>Rewritten and enhanced version of driver.js</p>
78
 
79
  <div class="buttons">
80
+ <button id="highlight-btn">Animated Highlight</button>
81
+ <button id="simple-highlight-btn">Simple Highlight</button>
82
+ <button id="transition-highlight-btn">Multiple Highlight Calls</button>
83
+ <button id="disallow-close">Disallow Close</button>
84
  <button id="tour-btn">Start Tour</button>
85
  <button id="destroy-btn">Destroy</button>
86
  </div>
 
95
  <script type="module">
96
  import { driver } from "./src/driver.ts";
97
 
98
+ document.getElementById("highlight-btn").addEventListener("click", () => {
99
+ driver({ animate: true }).highlight({ element: "h1" });
100
  });
101
 
102
+ document
103
+ .getElementById("simple-highlight-btn")
104
+ .addEventListener("click", () => {
105
+ driver({ animate: false }).highlight({ element: "ul" });
106
+ });
107
+
108
+ document
109
+ .getElementById("transition-highlight-btn")
110
+ .addEventListener("click", () => {
111
+ const driverObj = driver({ animate: true });
112
+
113
+ driverObj.highlight({ element: "h1" });
114
+
115
+ window.setTimeout(() => {
116
+ driverObj.highlight({ element: ".buttons" });
117
+ }, 1000);
118
  });
119
 
120
+ document
121
+ .getElementById("disallow-close")
122
+ .addEventListener("click", () => {
123
+ const driverObj = driver({
124
+ animate: true,
125
+ allowClose: false,
126
+ });
127
+
128
  driverObj.highlight({
129
  element: ".buttons",
130
  });
131
+ });
 
132
 
133
  document.getElementById("destroy-btn").addEventListener("click", () => {
134
+ driver().destroy();
135
  });
136
  </script>
137
  </body>
src/config.ts CHANGED
@@ -1,5 +1,6 @@
1
  export type Config = {
2
  animate?: boolean;
 
3
  };
4
 
5
  let currentConfig: Config = {};
@@ -7,6 +8,7 @@ let currentConfig: Config = {};
7
  export function configure(config: Config = {}) {
8
  currentConfig = {
9
  animate: true,
 
10
  ...config,
11
  };
12
  }
 
1
  export type Config = {
2
  animate?: boolean;
3
+ allowClose?: boolean;
4
  };
5
 
6
  let currentConfig: Config = {};
 
8
  export function configure(config: Config = {}) {
9
  currentConfig = {
10
  animate: true,
11
+ allowClose: true,
12
  ...config,
13
  };
14
  }
src/driver.ts CHANGED
@@ -10,26 +10,40 @@ export type DriveStep = {
10
  element?: string | Element;
11
  };
12
 
 
 
13
  export function driver(options: Config = {}) {
14
  configure(options);
15
 
16
- const shouldAnimate = getConfig("animate");
17
-
18
  function init() {
 
 
 
 
 
 
19
  document.body.classList.add(
20
  "driver-active",
21
- shouldAnimate ? "driver-fade" : "driver-simple"
22
  );
23
 
24
  initEvents();
25
 
26
- register("overlayClick", destroy);
 
 
 
 
 
 
 
27
  }
28
 
29
  function destroy() {
 
30
  document.body.classList.remove(
31
  "driver-active",
32
- shouldAnimate ? "driver-fade" : "driver-simple"
33
  );
34
 
35
  destroyEvents();
 
10
  element?: string | Element;
11
  };
12
 
13
+ let isInitialized = false;
14
+
15
  export function driver(options: Config = {}) {
16
  configure(options);
17
 
 
 
18
  function init() {
19
+ // Avoid multiple initialization
20
+ if (isInitialized) {
21
+ return;
22
+ }
23
+
24
+ isInitialized = true;
25
  document.body.classList.add(
26
  "driver-active",
27
+ getConfig("animate") ? "driver-fade" : "driver-simple"
28
  );
29
 
30
  initEvents();
31
 
32
+ // Register hooks
33
+ register("overlayClick", () => {
34
+ if (!getConfig("allowClose")) {
35
+ return;
36
+ }
37
+
38
+ destroy();
39
+ });
40
  }
41
 
42
  function destroy() {
43
+ isInitialized = false;
44
  document.body.classList.remove(
45
  "driver-active",
46
+ getConfig("animate") ? "driver-fade" : "driver-simple"
47
  );
48
 
49
  destroyEvents();
src/highlight.ts CHANGED
@@ -4,7 +4,7 @@ import { getConfig } from "./config";
4
 
5
  let previousHighlight: Element | undefined;
6
  let activeHighlight: Element | undefined;
7
- let isTransitioning = false;
8
 
9
  export function highlight(step: DriveStep) {
10
  const { element } = step;
@@ -34,10 +34,11 @@ function transferHighlight(from: Element, to: Element) {
34
  const duration = 400;
35
  const start = Date.now();
36
 
37
- isTransitioning = true;
38
-
39
  const animate = () => {
40
- if (!isTransitioning) {
 
 
 
41
  return;
42
  }
43
 
@@ -47,25 +48,23 @@ function transferHighlight(from: Element, to: Element) {
47
  transitionStage(elapsed, duration, from, to);
48
  } else {
49
  trackActiveElement(to);
50
-
51
- isTransitioning = false;
52
  }
53
 
54
  refreshStage();
55
  window.requestAnimationFrame(animate);
56
  };
57
 
 
58
  window.requestAnimationFrame(animate);
59
 
60
  from.classList.remove("driver-active-element");
61
  to.classList.add("driver-active-element");
62
-
63
- isTransitioning = true;
64
  }
65
 
66
  export function destroyHighlight() {
67
  activeHighlight = undefined;
68
- isTransitioning = false;
69
  previousHighlight = undefined;
70
  activeHighlight = undefined;
71
 
 
4
 
5
  let previousHighlight: Element | undefined;
6
  let activeHighlight: Element | undefined;
7
+ let currentTransitionCallback: undefined | (() => void);
8
 
9
  export function highlight(step: DriveStep) {
10
  const { element } = step;
 
34
  const duration = 400;
35
  const start = Date.now();
36
 
 
 
37
  const animate = () => {
38
+ // This makes sure that the repeated calls to transferHighlight
39
+ // don't interfere with each other. Only the last call will be
40
+ // executed.
41
+ if (currentTransitionCallback !== animate) {
42
  return;
43
  }
44
 
 
48
  transitionStage(elapsed, duration, from, to);
49
  } else {
50
  trackActiveElement(to);
51
+ currentTransitionCallback = undefined;
 
52
  }
53
 
54
  refreshStage();
55
  window.requestAnimationFrame(animate);
56
  };
57
 
58
+ currentTransitionCallback = animate;
59
  window.requestAnimationFrame(animate);
60
 
61
  from.classList.remove("driver-active-element");
62
  to.classList.add("driver-active-element");
 
 
63
  }
64
 
65
  export function destroyHighlight() {
66
  activeHighlight = undefined;
67
+ currentTransitionCallback = undefined;
68
  previousHighlight = undefined;
69
  activeHighlight = undefined;
70