Confirm on exit popup
Browse files- index.html +17 -3
- src/driver.ts +15 -6
- src/state.ts +3 -5
- src/style.css +2 -2
index.html
CHANGED
@@ -201,6 +201,7 @@
|
|
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,15 +399,28 @@ npm install driver.js</pre
|
|
398 |
driverObj.drive();
|
399 |
});
|
400 |
|
401 |
-
document.getElementById("
|
402 |
const driverObj = driver({
|
403 |
animate: true,
|
|
|
404 |
opacity: 0.3,
|
405 |
-
|
406 |
-
|
|
|
|
|
|
|
407 |
driverObj.destroy();
|
408 |
}
|
409 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
410 |
steps: [
|
411 |
{
|
412 |
element: ".page-header",
|
|
|
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 |
+
<button id="confirm-exit-tour">Confirm on Exit</button>
|
205 |
</div>
|
206 |
|
207 |
<ul>
|
|
|
399 |
driverObj.drive();
|
400 |
});
|
401 |
|
402 |
+
document.getElementById("confirm-exit-tour").addEventListener("click", () => {
|
403 |
const driverObj = driver({
|
404 |
animate: true,
|
405 |
+
backdropColor: "green",
|
406 |
opacity: 0.3,
|
407 |
+
steps: basicTourSteps,
|
408 |
+
onDestroyStarted: () => {
|
409 |
+
if (driverObj.hasNextStep() && confirm("Are you sure?")) {
|
410 |
+
driverObj.destroy();
|
411 |
+
} else {
|
412 |
driverObj.destroy();
|
413 |
}
|
414 |
},
|
415 |
+
});
|
416 |
+
|
417 |
+
driverObj.drive();
|
418 |
+
});
|
419 |
+
|
420 |
+
document.getElementById("async-tour").addEventListener("click", () => {
|
421 |
+
const driverObj = driver({
|
422 |
+
animate: true,
|
423 |
+
opacity: 0.3,
|
424 |
steps: [
|
425 |
{
|
426 |
element: ".page-header",
|
src/driver.ts
CHANGED
@@ -145,16 +145,15 @@ export function driver(options: Config = {}) {
|
|
145 |
});
|
146 |
}
|
147 |
|
148 |
-
function destroy(
|
149 |
const activeElement = getState("activeElement");
|
150 |
const activeStep = getState("activeStep");
|
151 |
|
152 |
const onDestroyStarted = getConfig("onDestroyStarted");
|
153 |
-
|
154 |
// `onDestroyStarted` is used to confirm the exit of tour. If we trigger
|
155 |
// the hook for when user calls `destroy`, driver will get into infinite loop
|
156 |
// not causing tour to be destroyed.
|
157 |
-
if (
|
158 |
onDestroyStarted(activeElement, activeStep!);
|
159 |
return;
|
160 |
}
|
@@ -186,15 +185,25 @@ export function driver(options: Config = {}) {
|
|
186 |
|
187 |
return {
|
188 |
isActive: () => getState("isInitialized") || false,
|
189 |
-
refresh:
|
190 |
-
requireRefresh();
|
191 |
-
},
|
192 |
drive: (stepIndex: number = 0) => {
|
193 |
init();
|
194 |
drive(stepIndex);
|
195 |
},
|
196 |
moveNext,
|
197 |
movePrevious,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
highlight: (step: DriveStep) => {
|
199 |
init();
|
200 |
highlight({
|
|
|
145 |
});
|
146 |
}
|
147 |
|
148 |
+
function destroy(withOnDestroyStartedHook = true) {
|
149 |
const activeElement = getState("activeElement");
|
150 |
const activeStep = getState("activeStep");
|
151 |
|
152 |
const onDestroyStarted = getConfig("onDestroyStarted");
|
|
|
153 |
// `onDestroyStarted` is used to confirm the exit of tour. If we trigger
|
154 |
// the hook for when user calls `destroy`, driver will get into infinite loop
|
155 |
// not causing tour to be destroyed.
|
156 |
+
if (withOnDestroyStartedHook && onDestroyStarted) {
|
157 |
onDestroyStarted(activeElement, activeStep!);
|
158 |
return;
|
159 |
}
|
|
|
185 |
|
186 |
return {
|
187 |
isActive: () => getState("isInitialized") || false,
|
188 |
+
refresh: requireRefresh,
|
|
|
|
|
189 |
drive: (stepIndex: number = 0) => {
|
190 |
init();
|
191 |
drive(stepIndex);
|
192 |
},
|
193 |
moveNext,
|
194 |
movePrevious,
|
195 |
+
hasNextStep: () => {
|
196 |
+
const steps = getConfig("steps") || [];
|
197 |
+
const activeIndex = getState("activeIndex");
|
198 |
+
|
199 |
+
return activeIndex !== undefined && steps[activeIndex + 1];
|
200 |
+
},
|
201 |
+
hasPreviousStep: () => {
|
202 |
+
const steps = getConfig("steps") || [];
|
203 |
+
const activeIndex = getState("activeIndex");
|
204 |
+
|
205 |
+
return activeIndex !== undefined && steps[activeIndex - 1];
|
206 |
+
},
|
207 |
highlight: (step: DriveStep) => {
|
208 |
init();
|
209 |
highlight({
|
src/state.ts
CHANGED
@@ -5,19 +5,17 @@ import { DriveStep } from "./driver";
|
|
5 |
export type State = {
|
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 |
-
|
15 |
activeElement?: Element;
|
16 |
activeStep?: DriveStep;
|
|
|
17 |
previousElement?: Element;
|
18 |
previousStep?: DriveStep;
|
19 |
-
transitionCallback?: () => void;
|
20 |
|
|
|
21 |
|
22 |
activeStagePosition?: StageDefinition;
|
23 |
stageSvg?: SVGSVGElement;
|
|
|
5 |
export type State = {
|
6 |
// Whether driver is initialized or not
|
7 |
isInitialized?: boolean;
|
|
|
|
|
|
|
8 |
// Used to bounce the resize event
|
9 |
resizeTimeout?: number;
|
10 |
|
11 |
+
activeIndex?: number;
|
12 |
activeElement?: Element;
|
13 |
activeStep?: DriveStep;
|
14 |
+
|
15 |
previousElement?: Element;
|
16 |
previousStep?: DriveStep;
|
|
|
17 |
|
18 |
+
transitionCallback?: () => void;
|
19 |
|
20 |
activeStagePosition?: StageDefinition;
|
21 |
stageSvg?: SVGSVGElement;
|
src/style.css
CHANGED
@@ -24,11 +24,11 @@
|
|
24 |
}
|
25 |
|
26 |
.driver-fade .driver-stage {
|
27 |
-
animation: animate-fade-in
|
28 |
}
|
29 |
|
30 |
.driver-fade .driver-popover {
|
31 |
-
animation: animate-fade-in
|
32 |
}
|
33 |
|
34 |
/* Popover styles */
|
|
|
24 |
}
|
25 |
|
26 |
.driver-fade .driver-stage {
|
27 |
+
animation: animate-fade-in 300ms ease-in-out;
|
28 |
}
|
29 |
|
30 |
.driver-fade .driver-popover {
|
31 |
+
animation: animate-fade-in 300ms;
|
32 |
}
|
33 |
|
34 |
/* Popover styles */
|