Skip to content

Commit 9d477c6

Browse files
authored
Add files via upload
1 parent 118dac3 commit 9d477c6

File tree

5 files changed

+659
-0
lines changed

5 files changed

+659
-0
lines changed

dist/lcwTourGuide.js

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
class lcwTourGuide {
2+
constructor(options = {}) {
3+
this.steps = Array.from(document.querySelectorAll('[data-lcw-tour-step]')).sort((a, b) => a.dataset.tourStep - b.dataset.tourStep);
4+
5+
this.current = 0;
6+
this.tooltip = null;
7+
this.overlay = null;
8+
9+
// callbacks
10+
this.onStart = options.onStart || (() => { });
11+
this.onEnd = options.onEnd || (() => { });
12+
this.onStep = options.onStep || (() => { });
13+
}
14+
15+
start() {
16+
if (!this.steps.length) return;
17+
this._createOverlay();
18+
this._showStep(this.current);
19+
20+
// fire callback
21+
this.onStart();
22+
}
23+
24+
_createOverlay() {
25+
this.overlay = document.createElement('div');
26+
this.overlay.className = 'lcw-tour-overlay';
27+
document.body.appendChild(this.overlay);
28+
}
29+
30+
_showStep(index) {
31+
const step = this.steps[index];
32+
33+
// scroll so both element + space for tooltip is visible
34+
const rect = step.getBoundingClientRect();
35+
const tooltipHeight = 120; // estimated
36+
const scrollY = window.scrollY + rect.top - (window.innerHeight / 2 - rect.height / 2);
37+
38+
let targetScroll = scrollY;
39+
if (rect.bottom + tooltipHeight > window.innerHeight) {
40+
targetScroll = window.scrollY + rect.top - tooltipHeight - 20;
41+
}
42+
window.scrollTo({ top: targetScroll, behavior: 'smooth' });
43+
44+
// Remove highlight from all
45+
this.steps.forEach(el => el.classList.remove('lcw-tour-highlight'));
46+
47+
setTimeout(() => {
48+
const rect = step.getBoundingClientRect();
49+
if (this.tooltip) this.tooltip.remove();
50+
51+
// Highlight the current step
52+
step.classList.add('lcw-tour-highlight');
53+
54+
this.tooltip = document.createElement('div');
55+
this.tooltip.className = 'lcw-tour-tooltip';
56+
this.tooltip.innerHTML = `
57+
<div class="lcw-tour-close" id="close-tour">&times;</div>
58+
<div style="margin-top: 10px;">${step.dataset.lcwTourText}</div>
59+
<div style="margin-top: 12px;">
60+
${index > 0 ? '<button id="prev-step">Previous</button>' : ''}
61+
${index < this.steps.length - 1
62+
? '<button id="next-step">Next</button>'
63+
: '<button id="end-tour">Done</button>'}
64+
</div>`;
65+
document.body.appendChild(this.tooltip);
66+
67+
// Decide tooltip position
68+
const tooltipRect = this.tooltip.getBoundingClientRect();
69+
let top = rect.bottom + window.scrollY + 10; // default below
70+
if (rect.bottom + tooltipRect.height + 20 > window.innerHeight) {
71+
// place above if not enough space
72+
top = rect.top + window.scrollY - tooltipRect.height - 10;
73+
}
74+
75+
let left = rect.left + window.scrollX;
76+
if (left + tooltipRect.width > window.innerWidth) {
77+
left = window.innerWidth - tooltipRect.width - 10;
78+
}
79+
if (left < 0) left = 10;
80+
81+
this.tooltip.style.top = `${top}px`;
82+
this.tooltip.style.left = `${left}px`;
83+
84+
// Button Events
85+
document.getElementById('next-step')?.addEventListener('click', () => this._next());
86+
document.getElementById('prev-step')?.addEventListener('click', () => this._prev());
87+
document.getElementById('end-tour')?.addEventListener('click', () => this._end());
88+
document.getElementById('close-tour')?.addEventListener('click', () => this._end());
89+
90+
// fire step callback
91+
this.onStep(index, step);
92+
}, 400);
93+
}
94+
95+
_next() {
96+
if (this.current < this.steps.length - 1) {
97+
this.current++;
98+
this._showStep(this.current);
99+
} else {
100+
this._end();
101+
}
102+
}
103+
104+
_prev() {
105+
if (this.current > 0) {
106+
this.current--;
107+
this._showStep(this.current);
108+
}
109+
}
110+
111+
_end() {
112+
this.tooltip?.remove();
113+
this.overlay?.remove();
114+
this.steps.forEach(el => el.classList.remove('lcw-tour-highlight'));
115+
this.tooltip = null;
116+
this.overlay = null;
117+
this.current = 0;
118+
119+
// fire callback
120+
this.onEnd();
121+
}
122+
}
123+
window.lcwTourGuide = lcwTourGuide;

dist/lcwTourGuide.min.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)