Spaces:
Running
Running
Update static/application.js
Browse files- static/application.js +69 -172
static/application.js
CHANGED
@@ -1,213 +1,110 @@
|
|
1 |
document.addEventListener("DOMContentLoaded", () => {
|
2 |
const convo = document.querySelector(".convo");
|
3 |
-
const input = document.querySelector("#
|
4 |
const sendBtn = document.querySelector(".sendingQA");
|
5 |
-
const fileBtn = document.querySelector("
|
6 |
-
const imageBtn = document.querySelector("
|
7 |
-
|
8 |
-
|
9 |
-
let filePreviewBubble = null;
|
10 |
-
|
11 |
-
// Hidden file input
|
12 |
-
const fileInput = document.createElement("input");
|
13 |
-
fileInput.type = "file";
|
14 |
-
fileInput.style.display = "none";
|
15 |
-
document.body.appendChild(fileInput);
|
16 |
|
17 |
-
//
|
18 |
fileBtn.addEventListener("click", () => {
|
19 |
-
fileInput.value = "";
|
20 |
-
fileInput.accept = ".pdf,.docx,.pptx,.xlsx";
|
21 |
fileInput.click();
|
22 |
});
|
23 |
|
24 |
-
// ๐ผ๏ธ Handle image icon click
|
25 |
imageBtn.addEventListener("click", () => {
|
26 |
-
|
27 |
-
|
28 |
-
fileInput.click();
|
29 |
});
|
30 |
|
31 |
-
//
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
if (filePreviewBubble) filePreviewBubble.remove();
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
filePreviewBubble.textContent = ๐ Selected: ${file.name};
|
41 |
-
convo.appendChild(filePreviewBubble);
|
42 |
-
convo.scrollTop = convo.scrollHeight;
|
43 |
-
}
|
44 |
-
});
|
45 |
|
46 |
-
//
|
47 |
convo.addEventListener("dragover", (e) => {
|
48 |
e.preventDefault();
|
49 |
-
convo.classList.add("drag-
|
50 |
});
|
51 |
|
52 |
convo.addEventListener("dragleave", () => {
|
53 |
-
convo.classList.remove("drag-
|
54 |
});
|
55 |
|
56 |
convo.addEventListener("drop", (e) => {
|
57 |
e.preventDefault();
|
58 |
-
convo.classList.remove("drag-
|
59 |
-
|
60 |
-
const file = e.dataTransfer.files[0];
|
61 |
-
if (file) {
|
62 |
-
selectedFile = file;
|
63 |
-
|
64 |
-
if (filePreviewBubble) filePreviewBubble.remove();
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
}
|
72 |
});
|
73 |
|
74 |
-
|
|
|
75 |
const bubble = document.createElement("div");
|
76 |
-
bubble.className = bubble ${
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
const icon = document.createElement("i");
|
100 |
-
icon.className = "fa-solid fa-volume-high audio-toggle";
|
101 |
-
icon.title = "Click to mute";
|
102 |
-
icon.style.cursor = "pointer";
|
103 |
-
icon.style.fontSize = "20px";
|
104 |
-
icon.style.marginLeft = "40px";
|
105 |
-
|
106 |
-
let currentAudio = new Audio(audioSrc);
|
107 |
-
currentAudio.play();
|
108 |
-
|
109 |
-
let isMuted = false;
|
110 |
-
icon.addEventListener("click", () => {
|
111 |
-
if (isMuted) {
|
112 |
-
currentAudio = new Audio(audioSrc);
|
113 |
-
currentAudio.play();
|
114 |
-
isMuted = false;
|
115 |
-
icon.classList.replace("fa-volume-xmark", "fa-volume-high");
|
116 |
-
icon.title = "Click to mute";
|
117 |
-
} else {
|
118 |
-
currentAudio.pause();
|
119 |
-
isMuted = true;
|
120 |
-
icon.classList.replace("fa-volume-high", "fa-volume-xmark");
|
121 |
-
icon.title = "Click to unmute";
|
122 |
-
}
|
123 |
-
});
|
124 |
-
|
125 |
-
message.appendChild(icon);
|
126 |
-
}
|
127 |
}
|
128 |
|
129 |
-
bubble.appendChild(label);
|
130 |
-
bubble.appendChild(message);
|
131 |
convo.appendChild(bubble);
|
132 |
convo.scrollTop = convo.scrollHeight;
|
133 |
-
return bubble;
|
134 |
}
|
135 |
|
136 |
-
//
|
137 |
-
|
138 |
-
const
|
139 |
-
if (!
|
140 |
-
|
141 |
-
if (!selectedFile) {
|
142 |
-
alert("Please upload a document or image first.");
|
143 |
-
return;
|
144 |
-
}
|
145 |
-
|
146 |
-
if (filePreviewBubble) {
|
147 |
-
filePreviewBubble.remove();
|
148 |
-
filePreviewBubble = null;
|
149 |
-
}
|
150 |
-
|
151 |
-
createMessageBubble(question, "You", null, selectedFile.name);
|
152 |
-
const thinkingBubble = createMessageBubble("Wait, let me think ๐ค...", "Chris");
|
153 |
-
|
154 |
-
const formData = new FormData();
|
155 |
-
formData.append("question", question);
|
156 |
-
formData.append("file", selectedFile);
|
157 |
-
|
158 |
-
try {
|
159 |
-
const response = await fetch("/predict", {
|
160 |
-
method: "POST",
|
161 |
-
body: formData
|
162 |
-
});
|
163 |
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
const icon = document.createElement("i");
|
173 |
-
icon.className = "fa-solid fa-volume-high audio-toggle";
|
174 |
-
icon.title = "Click to mute";
|
175 |
-
icon.style.cursor = "pointer";
|
176 |
-
icon.style.fontSize = "18px";
|
177 |
-
icon.style.marginLeft = "10px";
|
178 |
-
|
179 |
-
let currentAudio = new Audio(audioSrc);
|
180 |
-
currentAudio.play();
|
181 |
-
|
182 |
-
let isMuted = false;
|
183 |
-
icon.addEventListener("click", () => {
|
184 |
-
if (isMuted) {
|
185 |
-
currentAudio = new Audio(audioSrc); // restart
|
186 |
-
currentAudio.play();
|
187 |
-
isMuted = false;
|
188 |
-
icon.classList.replace("fa-volume-xmark", "fa-volume-high");
|
189 |
-
icon.title = "Click to mute";
|
190 |
-
} else {
|
191 |
-
currentAudio.pause();
|
192 |
-
isMuted = true;
|
193 |
-
icon.classList.replace("fa-volume-high", "fa-volume-xmark");
|
194 |
-
icon.title = "Click to unmute";
|
195 |
-
}
|
196 |
-
});
|
197 |
-
|
198 |
-
message.style.display = "flex";
|
199 |
-
message.style.justifyContent = "space-between";
|
200 |
-
message.appendChild(icon);
|
201 |
-
}
|
202 |
-
} catch (err) {
|
203 |
-
const message = thinkingBubble.querySelector(".text");
|
204 |
-
message.innerText = "โ ๏ธ Chris had trouble responding.";
|
205 |
-
}
|
206 |
|
|
|
207 |
input.value = "";
|
208 |
-
|
209 |
-
|
|
|
210 |
|
|
|
|
|
|
|
|
|
211 |
|
212 |
/*
|
213 |
document.addEventListener("DOMContentLoaded", () => {
|
|
|
1 |
document.addEventListener("DOMContentLoaded", () => {
|
2 |
const convo = document.querySelector(".convo");
|
3 |
+
const input = document.querySelector("#user-input");
|
4 |
const sendBtn = document.querySelector(".sendingQA");
|
5 |
+
const fileBtn = document.querySelector("#file-btn");
|
6 |
+
const imageBtn = document.querySelector("#image-btn");
|
7 |
+
const fileInput = document.querySelector("#file-upload");
|
8 |
+
const imageInput = document.querySelector("#image-upload");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
+
// --- File Upload Logic (Supports Re-selection) ---
|
11 |
fileBtn.addEventListener("click", () => {
|
12 |
+
fileInput.value = ""; // Reset to allow same-file reselection
|
|
|
13 |
fileInput.click();
|
14 |
});
|
15 |
|
|
|
16 |
imageBtn.addEventListener("click", () => {
|
17 |
+
imageInput.value = ""; // Reset to allow same-file reselection
|
18 |
+
imageInput.click();
|
|
|
19 |
});
|
20 |
|
21 |
+
// Handle file/image selection
|
22 |
+
const handleFileUpload = (file, type) => {
|
23 |
+
if (!file) return;
|
24 |
+
createFilePreview(file.name, type);
|
25 |
+
};
|
|
|
26 |
|
27 |
+
fileInput.addEventListener("change", () => handleFileUpload(fileInput.files[0], "file"));
|
28 |
+
imageInput.addEventListener("change", () => handleFileUpload(imageInput.files[0], "image"));
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
+
// --- Drag & Drop Support ---
|
31 |
convo.addEventListener("dragover", (e) => {
|
32 |
e.preventDefault();
|
33 |
+
convo.classList.add("drag-active");
|
34 |
});
|
35 |
|
36 |
convo.addEventListener("dragleave", () => {
|
37 |
+
convo.classList.remove("drag-active");
|
38 |
});
|
39 |
|
40 |
convo.addEventListener("drop", (e) => {
|
41 |
e.preventDefault();
|
42 |
+
convo.classList.remove("drag-active");
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
+
const files = e.dataTransfer.files;
|
45 |
+
if (files.length > 0) {
|
46 |
+
const file = files[0];
|
47 |
+
const type = file.type.startsWith("image") ? "image" : "file";
|
48 |
+
createFilePreview(file.name, type);
|
49 |
}
|
50 |
});
|
51 |
|
52 |
+
// --- Chat Bubbles & Audio Toggle ---
|
53 |
+
function createMessageBubble(message, isUser = true, audioSrc = null) {
|
54 |
const bubble = document.createElement("div");
|
55 |
+
bubble.className = `bubble ${isUser ? "right" : "left"}`;
|
56 |
+
bubble.innerHTML = `<span>${message}</span>`;
|
57 |
+
|
58 |
+
if (audioSrc && !isUser) {
|
59 |
+
const audio = document.createElement("audio");
|
60 |
+
audio.src = audioSrc;
|
61 |
+
audio.autoplay = true;
|
62 |
+
audio.currentTime = 0; // Restarts audio when unmuted
|
63 |
+
|
64 |
+
const audioIcon = document.createElement("i");
|
65 |
+
audioIcon.className = "fa-solid fa-volume-high audio-toggle";
|
66 |
+
audioIcon.title = "Click to mute";
|
67 |
+
|
68 |
+
bubble.appendChild(audio);
|
69 |
+
bubble.appendChild(audioIcon);
|
70 |
+
|
71 |
+
audioIcon.addEventListener("click", () => {
|
72 |
+
audio.muted = !audio.muted;
|
73 |
+
if (!audio.muted) audio.currentTime = 0; // Restart on unmute
|
74 |
+
audioIcon.classList.toggle("fa-volume-high");
|
75 |
+
audioIcon.classList.toggle("fa-volume-xmark");
|
76 |
+
audioIcon.title = audio.muted ? "Click to unmute" : "Click to mute";
|
77 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
}
|
79 |
|
|
|
|
|
80 |
convo.appendChild(bubble);
|
81 |
convo.scrollTop = convo.scrollHeight;
|
|
|
82 |
}
|
83 |
|
84 |
+
// --- Send Message ---
|
85 |
+
function sendMessage() {
|
86 |
+
const message = input.value.trim();
|
87 |
+
if (!message && !fileInput.files.length && !imageInput.files.length) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
|
89 |
+
if (message) createMessageBubble(message, true);
|
90 |
+
if (fileInput.files.length) handleFileUpload(fileInput.files[0], "file");
|
91 |
+
if (imageInput.files.length) handleFileUpload(imageInput.files[0], "image");
|
92 |
|
93 |
+
// Simulate bot response
|
94 |
+
setTimeout(() => {
|
95 |
+
createMessageBubble("Here's your answer!", false, "/static/audio/response.mp3");
|
96 |
+
}, 1000);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
|
98 |
+
// Reset inputs
|
99 |
input.value = "";
|
100 |
+
fileInput.value = "";
|
101 |
+
imageInput.value = "";
|
102 |
+
}
|
103 |
|
104 |
+
// Event listeners
|
105 |
+
sendBtn.addEventListener("click", sendMessage);
|
106 |
+
input.addEventListener("keydown", (e) => e.key === "Enter" && sendMessage());
|
107 |
+
});
|
108 |
|
109 |
/*
|
110 |
document.addEventListener("DOMContentLoaded", () => {
|