Skip to content

Commit d95d06b

Browse files
authored
Fix/resolve feedback menu related issue (#200)
* fix: resolve-feedback-menu-related-issue * fix: remove wrangler configuration file
1 parent 644a81b commit d95d06b

File tree

1 file changed

+31
-48
lines changed

1 file changed

+31
-48
lines changed

docs/js/feedback.js

Lines changed: 31 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
// feedback.js
2-
document.addEventListener("DOMContentLoaded", () => {
2+
3+
function feedbackModalInit() {
4+
// Remove any previous event listeners by replacing the button and modal with clones
5+
const oldBtn = document.querySelector("#feedbackButton");
6+
const oldModal = document.querySelector("#feedbackModal");
7+
if (oldBtn) {
8+
const newBtn = oldBtn.cloneNode(true);
9+
oldBtn.parentNode.replaceChild(newBtn, oldBtn);
10+
}
11+
if (oldModal) {
12+
const newModal = oldModal.cloneNode(true);
13+
oldModal.parentNode.replaceChild(newModal, oldModal);
14+
}
15+
16+
// Now re-select after replacement
317
const feedbackButton = document.querySelector("#feedbackButton");
418
const modal = document.querySelector("#feedbackModal");
519

@@ -30,11 +44,9 @@ document.addEventListener("DOMContentLoaded", () => {
3044
}
3145

3246
function openModal() {
33-
// store previous active element so we can restore focus when modal closes
3447
lastActiveElement = document.activeElement;
3548
modal.classList.remove("tw-hidden");
3649
calculatePosition();
37-
// focus the textarea for immediate typing if present
3850
const ta = modal.querySelector("textarea");
3951
if (ta) ta.focus();
4052
}
@@ -44,35 +56,25 @@ document.addEventListener("DOMContentLoaded", () => {
4456
form.reset();
4557
errorView.classList.add("tw-hidden");
4658
successView.classList.add("tw-hidden");
47-
// remove layout class when hidden to avoid display conflicts
4859
successView.classList.remove("tw-flex");
49-
// clear any inline positioning set during calculatePosition
5060
try {
5161
modal.style.top = "";
5262
modal.style.bottom = "";
53-
} catch (e) {
54-
/* ignore */
55-
}
63+
} catch (e) {}
5664
formView.classList.remove("tw-hidden");
57-
// restore focus to previously active element
5865
try {
5966
if (lastActiveElement && typeof lastActiveElement.focus === "function") {
6067
lastActiveElement.focus();
6168
}
62-
} catch (e) {
63-
/* ignore */
64-
}
69+
} catch (e) {}
6570
}
6671

6772
function calculatePosition() {
68-
// class-based positioning like the Vue component: toggle top-full / bottom-full
6973
try {
7074
const btnRect = feedbackButton.getBoundingClientRect();
7175
const screenHeight = window.innerHeight;
7276
const buttonCenter = btnRect.top + btnRect.height / 2;
7377
const placeAbove = buttonCenter > screenHeight / 2;
74-
75-
// rely on CSS classes and the parent .tw-relative for positioning
7678
modal.classList.remove(
7779
"tw-top-full",
7880
"tw-bottom-full",
@@ -81,22 +83,18 @@ document.addEventListener("DOMContentLoaded", () => {
8183
);
8284
if (placeAbove) {
8385
modal.classList.add("tw-bottom-full", "tw-mb-4");
84-
// explicitly position above using inline style to avoid CSS specificity issues
8586
modal.style.bottom = "100%";
8687
modal.style.top = "";
8788
} else {
8889
modal.classList.add("tw-top-full", "tw-mt-4");
89-
// explicitly position below
9090
modal.style.top = "100%";
9191
modal.style.bottom = "";
9292
}
93-
// ensure right alignment like Vue: right-0 on the modal container
9493
if (!modal.classList.contains("tw-right-0"))
9594
modal.classList.add("tw-right-0");
9695
} catch (err) {}
9796
}
9897

99-
// wire tab clicks with keyboard navigation and ARIA handling
10098
if (tabs && tabs.length) {
10199
const setActiveTab = (index) => {
102100
tabs.forEach((tb, i) => {
@@ -137,7 +135,6 @@ document.addEventListener("DOMContentLoaded", () => {
137135
});
138136
});
139137

140-
// init
141138
setActiveTab(0);
142139
}
143140

@@ -165,56 +162,34 @@ document.addEventListener("DOMContentLoaded", () => {
165162

166163
form.addEventListener("submit", (e) => {
167164
e.preventDefault();
168-
169-
// First, let the browser run HTML5 validation UI (native popup) if any
170-
// required fields are missing. reportValidity() will show the native
171-
// validation message and return false if invalid.
172165
if (typeof form.reportValidity === "function") {
173166
const ok = form.reportValidity();
174167
if (!ok) {
175-
// browser showed a native message; stop submission
176168
return;
177169
}
178170
}
179-
180-
// hide any previous custom error
181171
try {
182172
errorView.classList.add("tw-hidden");
183-
} catch (err) {
184-
/* ignore */
185-
}
186-
187-
// grab textarea and read trimmed value (we already know it's non-empty)
173+
} catch (err) {}
188174
const ta =
189175
form.querySelector("textarea") || modal.querySelector("textarea");
190176
const message = (ta && ta.value && ta.value.trim()) || "";
191-
192177
const data = {
193-
// use the prepared hidden input value (always present)
194178
type: (typeInput && typeInput.value) || "Issue",
195179
message: message,
196180
currentUrl: window.location.href,
197181
userAgent: navigator.userAgent,
198182
source: "feedback_form",
199183
};
200-
201-
// Track feedback in Segment (if segment.js is loaded)
202184
if (typeof window.trackFeedback === "function") {
203185
try {
204186
window.trackFeedback(data);
205-
} catch (e) {
206-
// Segment tracking error should not block submission
207-
}
187+
} catch (e) {}
208188
}
209-
210-
// show immediate success view (keeps original UX), then submit in background
211189
formView.classList.add("tw-hidden");
212-
// ensure success view displays as flex column when visible
213190
successView.classList.add("tw-flex");
214191
successView.classList.remove("tw-hidden");
215-
216192
setTimeout(closeModal, 1500);
217-
218193
fetch(
219194
"https://script.google.com/macros/s/AKfycby5A7NSQCmG4KIBdM0HkRP-5zpRPy8aTrQHiQoe9uG_c_rv1VCiAnnZE8co7-kofgw-hg/exec",
220195
{
@@ -224,7 +199,6 @@ document.addEventListener("DOMContentLoaded", () => {
224199
headers: { "Content-Type": "application/json" },
225200
}
226201
).catch(() => {
227-
// network failure: hide success and show error
228202
try {
229203
successView.classList.add("tw-hidden");
230204
successView.classList.remove("tw-flex");
@@ -235,9 +209,18 @@ document.addEventListener("DOMContentLoaded", () => {
235209
errorView.classList.remove("tw-hidden");
236210
}
237211
if (ta && typeof ta.focus === "function") ta.focus();
238-
} catch (err) {
239-
/* ignore */
240-
}
212+
} catch (err) {}
241213
});
242214
});
215+
}
216+
217+
// Run on DOMContentLoaded and MkDocs instant navigation
218+
if (typeof window.document$ !== "undefined") {
219+
window.document$.subscribe(() => {
220+
setTimeout(feedbackModalInit, 0);
221+
});
222+
}
223+
// Always run on DOMContentLoaded (for initial load)
224+
document.addEventListener("DOMContentLoaded", () => {
225+
setTimeout(feedbackModalInit, 0);
243226
});

0 commit comments

Comments
 (0)