5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
7 <link href="/zombo.css" rel="stylesheet" type="text/css">
8 <meta name="viewport" content="width=device-width,initial-scale=1">
9 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
10 <meta name="HandheldFriendly" content="true">
16 <div id="header" align="center">
22 <img src="/zombocom.png" alt="Zombocom" longdesc="http://zombo.com" width="1199" height="217">
27 Welcome to Zombocom. You can do anything at Zombocom, anything at
28 all. The only limit is yourself!
31 <dialog id="name-dialog">
32 <form method="dialog">
35 <input id="name" type="text" autocomplete="off">
39 <button value="default">OK</button>
45 <div id="spinner" align="center">
46 <div class="animate-flicker">
48 <img src="/pngwheel.png" class="rotate thefade">
53 <form action="" id="zombo-form">
54 <div class="form-row large">
58 <button id="safety" type="button">Safety prompt</button>
59 <textarea id="prompt" rows="4" width="100%" autocomplete="off" required></textarea>
62 <div class="form-row small left">
63 <div class="labeled-row">
67 <input id="code" type="number" min="0" max="4294967295" autocomplete="off" placeholder="(Leave blank for random)" />
71 <div class="form-row large">
72 <button id="generate" type="submit">Make the infinite possible</button>
80 <audio loop="" src="/zombo_words.mp3" type="audio/mpeg"></audio>
81 <button id="mute" class="menu-button fade volume">
84 const mute = document.querySelector("#mute");
85 const icon = document.querySelector("#mute > div");
86 const audio = document.querySelector("audio");
88 mute.addEventListener("click", () => {
92 icon.innerHTML = "🔈";
95 icon.innerHTML = "🔊";
97 mute.classList.add("fade");
103 <button id="profile" class="menu-button">
109 <script src="/socket.io/socket.io.js"></script>
113 const name_input = document.querySelector("#name");
114 const name_dialog = document.querySelector("#name-dialog");
116 const images = document.querySelector("#images");
117 const zombo_form = document.querySelector("#zombo-form");
118 const prompt = document.querySelector("#prompt");
119 const code = document.querySelector("#code");
120 const safety= document.querySelector("#safety");
121 const spinner = document.querySelector("#spinner");
122 const profile = document.querySelector("#profile");
125 profile.addEventListener('click', () => {
126 name_dialog.showModal();
129 name_dialog.addEventListener('close', () => {
130 socket.emit('set-name', name_input.value);
133 socket.on('comment', function(comment) {
134 const comments = document.querySelector("#" + comment.comments_id);
135 const dt = document.createElement('dt');
136 const dd = document.createElement('dd');
137 dt.textContent = comment.name + ':';
138 dd.textContent = comment.text;
139 comments.appendChild(dt);
140 comments.appendChild(dd);
143 socket.on('inform-name', (name) => {
144 console.log("Received inform-name event: " + name);
146 /* When we receive a name we store it in 3 places:
148 * * The informed_name variable (confirming what the server knows)
149 * * The name_input field (so the user will see that in their profile)
150 * * In localStorage (for use in a future session)
152 informed_name = name;
153 name_input.value = name;
154 localStorage.setItem('name', name);
157 socket.on('reset', () => {
158 images.replaceChildren();
161 socket.on('image', (image) => {
162 const figure = document.createElement('figure');
164 const img = document.createElement('img');
165 img.src = image.filename;
166 figure.appendChild(img);
168 const figcaption = document.createElement('figcaption');
169 const caption_text = document.createTextNode(`${image.prompt} (${image.code}) `);
170 figcaption.appendChild(caption_text);
172 const reuse_button = document.createElement('button');
173 reuse_button.appendChild(document.createTextNode("Reuse"));
174 figcaption.appendChild(reuse_button);
176 reuse_button.addEventListener('click', () => {
177 prompt.value = image.prompt;
178 window.scrollTo(0,0);
181 figure.appendChild(figcaption);
183 const dl_comments = document.createElement('dl');
184 const comments_id = "comments_" + image.index;
185 dl_comments.className = "comments";
186 dl_comments.id = comments_id;
187 figure.appendChild(dl_comments);
189 const comment_form = document.createElement('form');
190 const comment_input = document.createElement('input')
191 comment_input.type = "text";
192 comment_input.className = "comment";
193 comment_input.placeholder = "Add a comment";
194 comment_form.appendChild(comment_input);
195 figure.appendChild(comment_form);
197 comment_input.addEventListener('focus', () => {
198 /* If the server has informed us it has our name, we are done. */
202 /* If server has no name, check local storage. */
203 const name = localStorage.getItem('name');
205 socket.emit('set-name', name);
209 /* Failing both, bring up the modal dialog to set the name. */
210 name_dialog.showModal();
213 comment_form.addEventListener('submit', function(e) {
215 if (comment_input.value) {
216 socket.emit('comment', {comments_id: comments_id,
217 text: comment_input.value});
218 comment_input.value = '';
222 images.prepend(figure);
225 function hide_spinner() {
226 zombo_form.style.display = "grid";
227 spinner.style.display = "none";
230 zombo_form.addEventListener('submit', function(e) {
232 /* Hide the form and show spinner while generation is happening. */
233 zombo_form.style.display = "none";
234 spinner.style.display = "block";
235 spinner_timeout = setTimeout(hide_spinner, 60000);
236 socket.emit('generate', {"prompt": prompt.value, "code": code.value});
240 socket.on('generation-done', () => {
241 /* Re-display the form and hide spinner now that generation is over. */
242 clearTimeout(spinner_timeout);
246 function random_from(items) {
247 return items[Math.floor(Math.random()*items.length)];
250 safety.addEventListener("click", () => {
253 "A hyperrealistic photograph of",
254 "A matte painting of",
255 "Epic fantasy card art of",
256 "Professional oil painting of",
258 "A pencil sketch of",
261 "A marble statue of",
266 " a Porsche 911 Carrera",
270 " an elfin princess",
272 " pastel purple clouds",
273 " a Teenage Mutant Ninja Turtle",
277 " in tropical surroundings",
279 " in an ocean storm",
280 " in a snowy forest",
281 " in a cardboard box",
283 " in an epic landscape",
284 " in a haunted forest",
285 " riding a motorbike",
286 " in a futuristic city at night",
287 " in a dystopian landscape, foggy",
288 " in the land of snow",
289 " that looks like a watermelon",
290 " on the streets of London at night with neon lights flashing",
291 " that is part octopus",
292 " melting into a puddle",
293 " on a birthday cake",
299 " by Vincent Van Gogh",
301 " by Johannes Vermeer",
302 ", fantasy art, neon fog",
303 ", epic lighting from above",
304 ", trending on artstation",
306 " by Leonardo da Vinci",
309 prompt.value = random_from(art_type) + random_from(subject) +
310 random_from(scenery) + random_from(artist);