Other js files uploaded
Browse files- _api.js +30 -0
- _dom.js +31 -0
- _events.js +58 -0
- _helpers.js +11 -0
- main.js +7 -0
- myClasses.js +178 -0
_api.js
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const TOKEN = ""; // Replace with your actual token
|
2 |
+
|
3 |
+
async function query(chooseModel, token = TOKEN) {
|
4 |
+
try {
|
5 |
+
const response = await fetch(
|
6 |
+
`https://api-inference.huggingface.co/models/${chooseModel}`,
|
7 |
+
{
|
8 |
+
headers: {
|
9 |
+
Authorization: `Bearer ${token}`,
|
10 |
+
"Content-Type": "application/json",
|
11 |
+
},
|
12 |
+
method: "POST",
|
13 |
+
body: JSON.stringify({ inputs: text.value }),
|
14 |
+
}
|
15 |
+
);
|
16 |
+
|
17 |
+
if (!response.ok) {
|
18 |
+
throw new Error(`Error: ${response.status} ${response.statusText}`);
|
19 |
+
}
|
20 |
+
|
21 |
+
const result = await response.blob();
|
22 |
+
return result;
|
23 |
+
} catch (error) {
|
24 |
+
notificationInstance.show(
|
25 |
+
"error",
|
26 |
+
"Error fetching the image. Please try again later."
|
27 |
+
);
|
28 |
+
throw error; // Re-throw the error to handle it in the click event listener
|
29 |
+
}
|
30 |
+
}
|
_dom.js
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
//inputs
|
2 |
+
const token = document.querySelector("#token");
|
3 |
+
const text = document.querySelector("#text");
|
4 |
+
|
5 |
+
//others
|
6 |
+
const hintIcon = document.querySelector("#hint-icon");
|
7 |
+
const hintContent = document.querySelector("#hint-content");
|
8 |
+
|
9 |
+
//call to actions
|
10 |
+
const chooseModel = document.querySelector("#chooseModel");
|
11 |
+
const btn = document.querySelector("#btn");
|
12 |
+
const downloadBtn = document.querySelector("#downloadBtn");
|
13 |
+
const togglePassword = document.querySelector("#toggle-password");
|
14 |
+
|
15 |
+
//outputs
|
16 |
+
const modelInfo = document.querySelector("#model-info-text"); // Get the model info div
|
17 |
+
const loader = document.querySelector("#loader");
|
18 |
+
const img = document.querySelector("#img");
|
19 |
+
const historyContainer = document.querySelector("#history");
|
20 |
+
|
21 |
+
// ===============data=============
|
22 |
+
const modelDetails = {
|
23 |
+
"Melonie/text_to_image_finetuned":
|
24 |
+
"These are LoRA adaption weights for runwayml/stable-diffusion-v1-5. The weights were fine-tuned on the lambdalabs/pokemon-blip-captions dataset.",
|
25 |
+
|
26 |
+
"mann-e/Mann-E_Dreams":
|
27 |
+
"This is the newest SDXL based model from Mann-E platform, which is a generative AI startup based in Iran. ",
|
28 |
+
|
29 |
+
"alvdansen/midsommarcartoon":
|
30 |
+
"A retro-style cartoon print model that blends a bit of an anime influence with classic northern european cartoons.",
|
31 |
+
};
|
_events.js
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
document.addEventListener("DOMContentLoaded", () => {
|
2 |
+
// Instantiate Hint for API token
|
3 |
+
const apiTokenHint = new Hint("hint-icon", "hint-content");
|
4 |
+
|
5 |
+
// Instantiate Hint for Model Info
|
6 |
+
const modelInfoHint = new Hint("model-hint-icon", "model-hint-content");
|
7 |
+
|
8 |
+
chooseModel.addEventListener("change", updateModelInfo);
|
9 |
+
|
10 |
+
togglePassword.addEventListener("click", () => {
|
11 |
+
const type =
|
12 |
+
token.getAttribute("type") === "password" ? "text" : "password";
|
13 |
+
token.setAttribute("type", type);
|
14 |
+
|
15 |
+
togglePassword.querySelector("i").classList.toggle("fa-eye-slash");
|
16 |
+
togglePassword.querySelector("i").classList.toggle("fa-eye");
|
17 |
+
});
|
18 |
+
|
19 |
+
btn.addEventListener("click", async () => {
|
20 |
+
//form validations
|
21 |
+
if (text.value.trim() === "") {
|
22 |
+
notificationInstance.show("error", "Please enter some text.");
|
23 |
+
return;
|
24 |
+
}
|
25 |
+
|
26 |
+
if (token.value.trim() === "") {
|
27 |
+
notificationInstance.show("error", "Please enter your API token.");
|
28 |
+
|
29 |
+
return;
|
30 |
+
}
|
31 |
+
|
32 |
+
loader.classList.remove("hidden");
|
33 |
+
img.src = ""; // Clear the current image
|
34 |
+
downloadBtn.classList.add("hidden");
|
35 |
+
|
36 |
+
try {
|
37 |
+
const response = await query(chooseModel.value, token.value);
|
38 |
+
const objectUrl = URL.createObjectURL(response);
|
39 |
+
img.src = objectUrl;
|
40 |
+
downloadBtn.classList.remove("hidden");
|
41 |
+
imageHistoryInstance.addToHistory(objectUrl);
|
42 |
+
} catch (error) {
|
43 |
+
notificationInstance.show(
|
44 |
+
"error",
|
45 |
+
"Sorry, the model is currently unavailable. Please try again later."
|
46 |
+
);
|
47 |
+
} finally {
|
48 |
+
loader.classList.add("hidden");
|
49 |
+
}
|
50 |
+
});
|
51 |
+
|
52 |
+
downloadBtn.addEventListener("click", () => {
|
53 |
+
const link = document.createElement("a");
|
54 |
+
link.href = img.src;
|
55 |
+
link.download = "generated_image.png";
|
56 |
+
link.click();
|
57 |
+
});
|
58 |
+
}); //END OF EVENT LISTENER
|
_helpers.js
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function updateModelInfo() {
|
2 |
+
const selectedModel = chooseModel.value;
|
3 |
+
modelInfo.textContent =
|
4 |
+
modelDetails[selectedModel] || "No information available for this model.";
|
5 |
+
}
|
6 |
+
|
7 |
+
//for test only
|
8 |
+
// function showHistory() {
|
9 |
+
// console.log(imageHistoryInstance.history, "history");
|
10 |
+
// historyContainer.classList.remove("hidden");
|
11 |
+
// }
|
main.js
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
//initaializers
|
2 |
+
|
3 |
+
// Initialize model info display
|
4 |
+
updateModelInfo();
|
5 |
+
|
6 |
+
// Initialize image saved history & display
|
7 |
+
imageHistoryInstance.loadImageHistory();
|
myClasses.js
ADDED
@@ -0,0 +1,178 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Hint class definition
|
2 |
+
class Hint {
|
3 |
+
constructor(hintIconId, hintContentId) {
|
4 |
+
this.hintIcon = document.querySelector(`#${hintIconId}`);
|
5 |
+
this.hintContent = document.querySelector(`#${hintContentId}`);
|
6 |
+
|
7 |
+
// Bind event listener
|
8 |
+
this.hintIcon.addEventListener("click", this.toggle.bind(this));
|
9 |
+
}
|
10 |
+
|
11 |
+
toggle(event) {
|
12 |
+
event.preventDefault();
|
13 |
+
this.hintContent.classList.toggle("show");
|
14 |
+
}
|
15 |
+
}
|
16 |
+
|
17 |
+
// Notification class with Singleton pattern (no need to create new instances for each notification)
|
18 |
+
class Notification {
|
19 |
+
constructor() {
|
20 |
+
if (!Notification.instance) {
|
21 |
+
Notification.instance = this;
|
22 |
+
this.notifications = []; // Array to store active notifications
|
23 |
+
}
|
24 |
+
return Notification.instance;
|
25 |
+
}
|
26 |
+
|
27 |
+
show(type, message) {
|
28 |
+
const notificationElement = document.createElement("div");
|
29 |
+
notificationElement.className = `notification ${type}`;
|
30 |
+
notificationElement.textContent = message;
|
31 |
+
|
32 |
+
// Add close button
|
33 |
+
const closeButton = document.createElement("span");
|
34 |
+
closeButton.className = "close-btn";
|
35 |
+
closeButton.innerHTML = "×";
|
36 |
+
closeButton.addEventListener("click", () =>
|
37 |
+
this.close(notificationElement)
|
38 |
+
);
|
39 |
+
notificationElement.appendChild(closeButton);
|
40 |
+
|
41 |
+
document.body.appendChild(notificationElement);
|
42 |
+
|
43 |
+
// Auto-close after 5 seconds (5000 milliseconds)
|
44 |
+
setTimeout(() => {
|
45 |
+
this.close(notificationElement);
|
46 |
+
}, 5000);
|
47 |
+
}
|
48 |
+
|
49 |
+
close(notificationElement) {
|
50 |
+
notificationElement.remove();
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
// Singleton instance
|
55 |
+
const notificationInstance = new Notification();
|
56 |
+
|
57 |
+
// Example usage:
|
58 |
+
// notificationInstance.show("success", "Operation successful!");
|
59 |
+
// notificationInstance.show("error", "An error occurred. Please try again.");
|
60 |
+
// notificationInstance.show("info", "Informational message.");
|
61 |
+
|
62 |
+
// ImageHistory class
|
63 |
+
class ImageHistory {
|
64 |
+
constructor(historyContainerId) {
|
65 |
+
this.history = []; // Array to store image URLs
|
66 |
+
this.historyContainer = document.querySelector(`#${historyContainerId}`);
|
67 |
+
}
|
68 |
+
|
69 |
+
addToHistory(imageUrl) {
|
70 |
+
this.history.push(imageUrl);
|
71 |
+
this.renderHistory(); // Update the DOM to reflect changes
|
72 |
+
}
|
73 |
+
|
74 |
+
renderHistory() {
|
75 |
+
// Clear existing history items in the DOM
|
76 |
+
this.historyContainer.innerHTML = "";
|
77 |
+
|
78 |
+
if (this.history.length === 0) {
|
79 |
+
const historyItem = document.createElement("p");
|
80 |
+
historyItem.textContent = "No images generated yet.";
|
81 |
+
this.historyContainer.appendChild(historyItem);
|
82 |
+
return;
|
83 |
+
}
|
84 |
+
|
85 |
+
// Render each image in history
|
86 |
+
this.history.forEach((imageUrl, index) => {
|
87 |
+
const historyItem = document.createElement("div");
|
88 |
+
historyItem.classList.add("history-item");
|
89 |
+
|
90 |
+
const image = document.createElement("img");
|
91 |
+
image.src = imageUrl;
|
92 |
+
|
93 |
+
historyItem.appendChild(image);
|
94 |
+
|
95 |
+
// Add download button
|
96 |
+
const downloadButton = document.createElement("span");
|
97 |
+
const iconDownload = document.createElement("i");
|
98 |
+
iconDownload.classList.add("fas", "fa-arrow-down");
|
99 |
+
downloadButton.appendChild(iconDownload);
|
100 |
+
// downloadButton.textContent = "Download";
|
101 |
+
downloadButton.classList.add("downloadButton");
|
102 |
+
downloadButton.addEventListener("click", (e) => {
|
103 |
+
e.preventDefault();
|
104 |
+
this.downloadThisImage(index);
|
105 |
+
});
|
106 |
+
historyItem.appendChild(downloadButton);
|
107 |
+
|
108 |
+
// Add remove button
|
109 |
+
const removeBtn = document.createElement("span");
|
110 |
+
const iconRemove = document.createElement("i");
|
111 |
+
iconRemove.classList.add("fas", "fa-xmark");
|
112 |
+
removeBtn.appendChild(iconRemove);
|
113 |
+
// removeBtn.textContent = "Remove";
|
114 |
+
removeBtn.classList.add("removeButton");
|
115 |
+
|
116 |
+
removeBtn.addEventListener("click", (e) => this.removeFromHistory(index));
|
117 |
+
historyItem.appendChild(removeBtn);
|
118 |
+
|
119 |
+
this.historyContainer.appendChild(historyItem);
|
120 |
+
});
|
121 |
+
}
|
122 |
+
|
123 |
+
downloadThisImage(index) {
|
124 |
+
const imageUrl = this.history[index];
|
125 |
+
if (imageUrl) {
|
126 |
+
// // Create a temporary <a> element to trigger download
|
127 |
+
const link = document.createElement("a");
|
128 |
+
link.href = imageUrl;
|
129 |
+
link.download = `image_${index + 1}.png`; // Adjust filename as needed
|
130 |
+
link.click();
|
131 |
+
link.remove();
|
132 |
+
} else {
|
133 |
+
// // Handle error or show notification if image URL not found
|
134 |
+
notificationInstance.show("error", "Image URL not found.");
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
removeFromHistory(index) {
|
139 |
+
if (index >= 0 && index < this.history.length) {
|
140 |
+
this.history.splice(index, 1);
|
141 |
+
this.renderHistory(); // Update the DOM after removal
|
142 |
+
notificationInstance.show("success", "Image removed from history.");
|
143 |
+
} else {
|
144 |
+
// Handle error or show notification if index is out of range
|
145 |
+
notificationInstance.show("error", "Invalid index.");
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
clearHistory() {
|
150 |
+
this.history = [];
|
151 |
+
this.saveToLocalStorage();
|
152 |
+
this.renderHistory();
|
153 |
+
notificationInstance.show("success", "History cleared.");
|
154 |
+
}
|
155 |
+
|
156 |
+
saveToLocalStorage() {
|
157 |
+
localStorage.setItem("TextToImgHistory", JSON.stringify(this.history));
|
158 |
+
notificationInstance.show("success", "History saved.");
|
159 |
+
}
|
160 |
+
|
161 |
+
loadImageHistory() {
|
162 |
+
const savedHistory = localStorage.getItem("TextToImgHistory");
|
163 |
+
if (savedHistory) {
|
164 |
+
this.history = JSON.parse(savedHistory);
|
165 |
+
this.renderHistory();
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
// clearLocalStorage() {
|
170 |
+
// localStorage.removeItem("TextToImgHistory");
|
171 |
+
// }
|
172 |
+
}
|
173 |
+
|
174 |
+
// Singleton instance of ImageHistory
|
175 |
+
const imageHistoryInstance = new ImageHistory("history-container"); // Provide ID of history container element
|
176 |
+
|
177 |
+
// Example usage:
|
178 |
+
// imageHistoryInstance.addToHistory("https://example.com/image1.png");
|