Spaces:
Running
Running
| {% extends 'base.html' %} {% block content %} | |
| <div id="room-container"> | |
| <div id="welcome-modal" class="modal"> | |
| <div class="modal-content"> | |
| <h3>Welcome!</h3> | |
| <p> | |
| Your display name for this chat session will be: | |
| <span id="displayNameText" style="font-weight:bold;"></span>. | |
| </p> | |
| <div class="modal-buttons"> | |
| <button class="modal-btn" id="welcomeOkBtn">OK</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="timer-modal" class="modal"> | |
| <div class="modal-content"> | |
| <h3>Start a Timer</h3> | |
| <p><strong>Please start a timer for 20 minutes</strong>. At the 20 minute mark, you may click the button "End Chat Session" to continue with the study.</p> | |
| <div class="modal-buttons"> | |
| <button class="modal-btn" id="timerOkBtn">I have set a timer for 20 minutes.</button> | |
| </div> | |
| </div> | |
| </div> | |
| <h1 id="home-header">Chat Room</h1> | |
| <div id="room-subsection"> | |
| <div class="topic-header-row"> | |
| <div class="topic-header-info"> | |
| <h2 id="room-code-display">Topic: <span class="topic-title">{{ topic_info.title }}</span></h2> | |
| </div> | |
| <div class="topic-header-buttons"> | |
| <button id="end-exp-btn">End Chat Session</button> | |
| <button id="abort-exp-btn">Abort Experiment</button> | |
| </div> | |
| </div> | |
| <div id="end-modal" class="modal"> | |
| <div class="modal-content"> | |
| <h3>Only Exit This Way After 20 Minutes of Participation in the Chatroom.</h3> | |
| <p>This signals the end of the chat session of the experiment. You will be redirected to the post-survey.</p> | |
| <p>This button is only to be used at the end of your 20 minutes of participation in the chatroom. <strong>If you wish to exit the chat before finishing your 20 minutes, use the "Abort Experiment" button instead.</strong></p> | |
| <div class="modal-buttons"> | |
| <button class="modal-btn" id="endYesBtn">Continue</button> | |
| <button class="modal-btn" id="endNoBtn">Cancel</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="abort-modal" class="modal"> | |
| <div class="modal-content"> | |
| <h3>Are you sure you want to leave this experiment?</h3> | |
| <p>This action is permanent. You will be redirected to the post-survey and will not be able to return to the chat room.</p> | |
| <p><strong>If you finished your 20 minutes in the chatroom, do NOT exit via this button. Use the "End Chat Session" button instead.</strong></p> | |
| <div class="modal-buttons"> | |
| <button class="modal-btn" id="abortYesBtn-pre">Yes</button> | |
| <button class="modal-btn" id="abortNoBtn-pre">Cancel</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="abort-modal-confirm" class="modal"> | |
| <div class="modal-content"> | |
| <h3>Confirmation</h3> | |
| <p>By clicking yes, you will exit the experiment <strong>without</strong> completing the final survey.</p> | |
| <p>We encourage you to message us about any concerns or to <a href="{{ feedback_form_url | default('https://umw.qualtrics.com/jfe/form/SV_08v26NssCOwZTP8') }}" target="_blank">provide feedback here</a>.</p> | |
| <div class="modal-buttons"> | |
| <button class="modal-btn" id="abortYesBtn">End early with code "C9V2XFDU"</button> | |
| <button class="modal-btn" id="abortNoBtn">Cancel</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="chat-room-widget"> | |
| <div id="msgs-container"> | |
| <ul id="messages"></ul> | |
| </div> | |
| <div id="message-box"> | |
| <textarea id="message-input" name="message" placeholder="Enter your message" rows="1"></textarea> | |
| <button type="submit" id="send-btn" onclick="sendMessage()">Send</button> | |
| </div> | |
| </div> | |
| <script type="text/javascript"> | |
| // Push a state when entering the page | |
| history.pushState(null, "", location.href); | |
| window.addEventListener("popstate", function () { | |
| // Immediately push another state to prevent backward navigation | |
| history.pushState(null, "", location.href); | |
| }); | |
| var socketio = io(); | |
| const chatEnded = {{ ended | tojson }}; | |
| const textarea = document.getElementById("message-input"); | |
| if (chatEnded) { | |
| textarea.disabled = true; | |
| textarea.placeholder = "The chat has ended."; | |
| document.getElementById("send-btn").disabled = true; | |
| document.getElementById("end-exp-btn").disabled = true; | |
| document.getElementById("abort-exp-btn").disabled = true; | |
| if (socketio) { | |
| socketio.close(); | |
| } | |
| } | |
| // Handler for the welcome modal | |
| let welcomeModal = document.getElementById("welcome-modal"); | |
| let timerModal = document.getElementById("timer-modal"); | |
| const displayNameText = document.getElementById("displayNameText"); | |
| displayNameText.textContent = "{{ user }}"; | |
| // Show the modal instantly when the page loads | |
| window.onload = function() { | |
| timerModal.style.display = "block"; | |
| }; | |
| //timer pop-up | |
| document.getElementById("timerOkBtn").onclick = function () { | |
| timerModal.style.display = "none"; | |
| welcomeModal.style.display = "block"; | |
| }; | |
| // Close the modal on OK | |
| document.getElementById("welcomeOkBtn").onclick = function () { | |
| welcomeModal.style.display = "none"; | |
| }; | |
| // Creates the post-survey link (based on the bot names) | |
| const endpoint = "{{ url_for('post_survey') }}"; | |
| const endpointQuitEarly = "https://app.prolific.com/submissions/complete?cc=C9V2XFDU"; | |
| socketio.on("message", function (message) { createChatItem(message.message, message.sender) }); | |
| function createChatItem(message, sender) { | |
| //autoscroll capabilities | |
| const container = document.getElementById("msgs-container"); | |
| const shouldAutoScroll = isNearBottom(container); | |
| var messages = document.getElementById("messages"); | |
| var content; | |
| if (sender === "") { | |
| content = `<p class="member-activity">${message}</p>`; | |
| } else { | |
| var senderIsUser = "{{user}}" === sender; | |
| content = ` | |
| <li class="message-item ${senderIsUser ? "self-message-item" : "peer-message-item"}"> | |
| <p>${message}</p> | |
| <small class="${senderIsUser ? "chat-user-sender" : "chat-sender"}">${sender}</small> | |
| </li> | |
| `;} | |
| messages.insertAdjacentHTML("beforeend", content); | |
| //autoscroll capabilities | |
| if (shouldAutoScroll) { | |
| smoothScrollToBottom(container); | |
| } | |
| } | |
| function sendMessage() { | |
| var msgInput = document.getElementById("message-input"); | |
| if (msgInput.value === "") return; | |
| var msg = msgInput.value; | |
| socketio.emit("message", { message: msg }); | |
| msgInput.value = ""; | |
| msgInput.style.height = "auto"; // reset height | |
| } | |
| document.getElementById("message-input").addEventListener("keydown", function (event) { | |
| if (event.key === "Enter") { | |
| return | |
| // disabling send message so user can type a newline without sending | |
| //event.preventDefault(); // prevent a newline or form submit | |
| //sendMessage(); // call the same function as the Send button | |
| } | |
| }); | |
| textarea.addEventListener("input", () => { | |
| textarea.style.height = "auto"; // reset height | |
| textarea.style.overflowY = "hidden"; // start by hiding the scrollbar | |
| textarea.style.height = (textarea.scrollHeight + 8) + "px"; // set to fit content (+8 for bottom padding) | |
| // If we've hit the max height, allow scrolling | |
| if (textarea.scrollHeight > parseInt(getComputedStyle(textarea).maxHeight)) { | |
| textarea.style.overflowY = "auto"; | |
| } | |
| }); | |
| // Handler for the Experiment Ends confirmation pop-up | |
| const endModal = document.getElementById("end-modal"); | |
| document.getElementById("end-exp-btn").onclick = function () { | |
| endModal.style.display = "block"; | |
| }; | |
| document.getElementById("endNoBtn").onclick = function () { | |
| endModal.style.display = "none"; | |
| }; | |
| document.getElementById("endYesBtn").onclick = function (e) { | |
| //block browser confirmation popup | |
| e.stopPropagation(); | |
| // Redirect to ending survey | |
| window.open(endpoint, "_blank"); | |
| endModal.style.display = "none"; | |
| textarea.disabled = true; | |
| textarea.placeholder = "The chat has ended."; | |
| document.getElementById("send-btn").disabled = true; | |
| document.getElementById("end-exp-btn").disabled = true; | |
| document.getElementById("abort-exp-btn").disabled = true; | |
| if (socketio) { | |
| socketio.close(); | |
| } | |
| }; | |
| // Handler for the Abort Experiment confirmation pop-up | |
| let modal = document.getElementById("abort-modal"); | |
| let abortModalConfirm = document.getElementById("abort-modal-confirm"); | |
| document.getElementById("abort-exp-btn").onclick = function () { | |
| modal.style.display = "block"; | |
| }; | |
| document.getElementById("abortYesBtn-pre").onclick = function () { | |
| abortModalConfirm.style.display = "block"; | |
| modal.style.display = "none"; | |
| }; | |
| document.getElementById("abortNoBtn-pre").onclick = function () { | |
| modal.style.display = "none"; | |
| }; | |
| document.getElementById("abortYesBtn-SurveyAnyway").onclick = function (e) { | |
| //block browser confirmation popup | |
| e.stopPropagation(); | |
| // Mark that user aborted and redirect to ending survey | |
| fetch("/abort", { method: "POST" }) | |
| .then(() => { | |
| window.open(endpoint, "_blank"); | |
| }); | |
| modal.style.display = "none"; | |
| textarea.disabled = true; | |
| textarea.placeholder = "The chat has ended."; | |
| document.getElementById("send-btn").disabled = true; | |
| document.getElementById("end-exp-btn").disabled = true; | |
| document.getElementById("abort-exp-btn").disabled = true; | |
| if (socketio) { | |
| socketio.close(); | |
| } | |
| abortModalConfirm.style.display = "none"; | |
| }; | |
| document.getElementById("abortNoBtn").onclick = function () { | |
| abortModalConfirm.style.display = "none"; | |
| }; | |
| document.getElementById("abortYesBtn").onclick = function (e) { | |
| //block browser confirmation popup | |
| e.stopPropagation(); | |
| // Mark that user aborted and redirect to ending survey | |
| fetch("/abort", { method: "POST" }) | |
| .then(() => { | |
| window.open(endpointQuitEarly, "_blank"); | |
| }); | |
| modal.style.display = "none"; | |
| textarea.disabled = true; | |
| textarea.placeholder = "The chat has ended."; | |
| document.getElementById("send-btn").disabled = true; | |
| document.getElementById("end-exp-btn").disabled = true; | |
| document.getElementById("abort-exp-btn").disabled = true; | |
| if (socketio) { | |
| socketio.close(); | |
| } | |
| abortModalConfirm.style.display = "none"; | |
| }; | |
| document.getElementById("abortNoBtn").onclick = function () { | |
| abortModalConfirm.style.display = "none"; | |
| }; | |
| // add auto scroll | |
| function isNearBottom(container, threshold = 120) { | |
| const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight); | |
| return distanceFromBottom < threshold; | |
| } | |
| function smoothScrollToBottom(container) { | |
| container.scrollTo({ top: container.scrollHeight, behavior: "smooth" }); | |
| } | |
| </script> | |
| <script type="text/javascript"> | |
| </script> | |
| </div> | |
| {% endblock %} | |