function logGoogleEvent(action, label = undefined) { if (typeof window.gtag === "function") { window.gtag("event", action, { event_category: "Page feedback", event_label: label, }); } else if (window.dataLayer != null) { window.dataLayer.push({ event: "click_feedback_rating", object_type: label, }); } } const LANG_TO_CONTENT = { en: { ratingPrompt: "Did you find what you were looking for on this page?", ratingPositive: "Yes", ratingNegative: "No", commentPromptPositive: "Great! We're looking for ways to improve this page — what ideas come to mind?", commentPromptNegative: "Sorry to hear that. What were you looking for today?", commentPromptDisclaimer: "Your feedback helps improve this web page. For specific questions about your situation, ", commentPromptDisclaimerLink: "contact us", commentSubmit: "Send feedback", commentSubmitLoading: "Sending...", commentConfirmation: "Thanks for sharing your thoughts!", emailPrompt: "To hear about paid feedback opportunities in the future, join our user testing list.", emailLabel: "Email address", emailSubmit: "Join the list", emailSubmitLoading: "Joining...", errorMessage: "Try again, please. We didn't get your answer because of a technical issue.", emailConfirmation: "Thanks for signing up!", }, es: { ratingPrompt: "¿Encontraste lo que buscabas en esta página?", ratingPositive: "Sí", ratingNegative: "No", commentPromptPositive: "¡Excelente! Estamos buscando formas de mejorar esta página. ¿Qué ideas se te ocurren?", commentPromptNegative: "Lamentamos escuchar eso. ¿De que se trataba su búsqueda?", commentPromptDisclaimer: "Sus comentarios nos ayudan a mejorar nuestro sitio de web. Si tiene preguntas específicas sobre su situación, ", commentPromptDisclaimerLink: "por favor póngase en contacto con nosotros", commentSubmit: "Enviar comentarios", commentSubmitLoading: "Enviando...", commentConfirmation: "¡Gracias por compartir tus ideas!", emailPrompt: "Para conocer mas oportunidades de comentarios pagados en el futuro, sea parte de nuestra lista de prueba de usuarios.", emailLabel: "Dirección de correo electrónico", emailSubmit: "Sea parte de la lista", emailSubmitLoading: "Enviando...", errorMessage: "Por favor, inténtalo de nuevo. No obtuvimos su respuesta debido a un problema técnico.", emailConfirmation: "¡Gracias por registrarte!", }, }; const API_URL = "https://innovation.nj.gov/app/feedback/dev"; const JSON_HEADER = { "Content-Type": "application/json", }; class NJFeedbackWidget extends window.HTMLElement { constructor() { super(); this.rating = false; this.feedbackId = undefined; this.retryRating = false; this.language = new URL(window.location).searchParams.get("lang") ?? "en"; } connectedCallback() { this.innerHTML = this.getHTML(); this.applyListeners(); this.addStyling(); document.addEventListener( "changeLanguage", this.handleChangeLanguage.bind(this) ); } disconnectedCallback() { document.removeEventListener( "changeLanguage", this.handleChangeLanguage.bind(this) ); } handleChangeLanguage(e) { this.language = e.detail; this.innerHTML = this.getHTML(); this.applyListeners(); } applyListeners() { this.querySelector("#yesButton").addEventListener("click", (_e) => { this.handleRating(true); }); this.querySelector("#noButton").addEventListener("click", (_e) => { this.handleRating(false); }); const commentForm = this.querySelector("#commentForm"); const commentButton = document.getElementById("commentSubmit"); commentButton.addEventListener("click", (e) => { if (commentButton.getAttribute("aria-disabled") === "true") { e.preventDefault(); } }); commentForm.addEventListener("submit", (e) => { e.preventDefault(); commentButton.setAttribute("aria-disabled", "true"); this.hideElement("#commentSubmitText"); this.showElement("#commentSubmitLoadingText"); const comment = e.target.elements.comment.value; const postData = this.retryRating || this.feedbackId == null ? { comment, rating: this.rating, pageURL: window.location.href } : { feedbackId: this.feedbackId, comment, }; fetch(`${API_URL}/comment`, { method: "POST", headers: JSON_HEADER, body: JSON.stringify(postData), }) .then((response) => response.json()) .then((data) => { if (this.feedbackId == null) { this.feedbackId = data.feedbackId; } if (data.message === "Success" && this.feedbackId != null) { this.hideElement("#commentPrompt"); if (this.getAttribute("skip-email-step") === "true") { this.showElement("#confirmation", "flex"); } else { this.showElement("#emailPrompt"); } } else { this.showElement("#commentSubmitError"); } }) .catch((e) => { this.showElement("#commentSubmitError"); }) .finally(() => { this.hideElement("#commentSubmitLoadingText"); this.showElement("#commentSubmitText"); commentButton.removeAttribute("aria-disabled"); }); }); const emailForm = this.querySelector("#emailForm"); const emailButton = document.getElementById("emailSubmit"); emailButton.addEventListener("click", (e) => { if (emailButton.getAttribute("aria-disabled") === "true") { e.preventDefault(); } }); emailForm.addEventListener("submit", (e) => { e.preventDefault(); emailButton.setAttribute("aria-disabled", "true"); this.hideElement("#emailSubmitText"); this.showElement("#emailSubmitLoadingText"); const postData = { feedbackId: this.feedbackId, email: e.target.elements.email.value, }; fetch(`${API_URL}/email`, { method: "POST", headers: JSON_HEADER, body: JSON.stringify(postData), }) .then((response) => response.json()) .then((data) => { if (data.message === "Success" && data.feedbackId != null) { this.hideElement("#emailPrompt"); this.showElement("#confirmation", "flex"); } else { this.showElement("#emailSubmitError"); } }) .catch((e) => { this.showElement("#emailSubmitError"); }) .finally(() => { this.hideElement("#emailSubmitLoadingText"); this.showElement("#emailSubmitText"); emailButton.removeAttribute("aria-disabled"); }); }); } handleRating(rating) { const commentButton = document.getElementById("commentSubmit"); this.rating = rating; if (rating) { this.hideElement("#commentPromptTextNeg"); this.showElement("#commentPromptTextPos"); } else { this.hideElement("#commentPromptTextPos"); this.showElement("#commentPromptTextNeg"); } this.hideElement("#ratingPrompt"); this.showElement("#commentPrompt"); const onlySaveRatingToAnalytics = this.getAttribute("only-save-rating-to-analytics") === "true"; if (onlySaveRatingToAnalytics) { logGoogleEvent("Clicked initial button", rating ? "Yes" : "No"); } else { commentButton.setAttribute("aria-disabled", "true"); const postData = { pageURL: window.location.href, rating, }; fetch(`${API_URL}/rating`, { method: "POST", headers: JSON_HEADER, body: JSON.stringify(postData), }) .then((response) => response.json()) .then((data) => { if (data.message === "Success" && data.feedbackId != null) { this.feedbackId = data.feedbackId; logGoogleEvent("Clicked initial button", rating ? "Yes" : "No"); } else { this.retryRating = true; } }) .catch((e) => { this.retryRating = true; }) .finally(() => { commentButton.removeAttribute("aria-disabled"); }); } } showElement(selector, displayType = "block") { this.querySelector(selector).style.display = displayType; } hideElement(selector) { this.querySelector(selector).style.display = "none"; } getHTML() { const content = LANG_TO_CONTENT[this.language]; const contactLink = this.getAttribute("contact-link") || "https://www.nj.gov/nj/feedback.html"; const showCommentDisclaimer = this.getAttribute("show-comment-disclaimer") !== "false"; const html = /*html*/ `