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();
160 /* Since the server is seeing us for the first time, let it
161 know our name (if we have one). */
162 const name = localStorage.getItem('name');
164 socket.emit('set-name', name);
169 socket.on('image', (image) => {
170 const figure = document.createElement('figure');
172 const img = document.createElement('img');
173 img.src = image.filename;
174 figure.appendChild(img);
176 const figcaption = document.createElement('figcaption');
177 const caption_text = document.createTextNode(`${image.prompt} (${image.code}) `);
178 figcaption.appendChild(caption_text);
180 const reuse_button = document.createElement('button');
181 reuse_button.appendChild(document.createTextNode("Reuse"));
182 figcaption.appendChild(reuse_button);
184 reuse_button.addEventListener('click', () => {
185 prompt.value = image.prompt;
186 window.scrollTo(0,0);
189 figure.appendChild(figcaption);
191 const dl_comments = document.createElement('dl');
192 const comments_id = "comments_" + image.index;
193 dl_comments.className = "comments";
194 dl_comments.id = comments_id;
195 figure.appendChild(dl_comments);
197 const comment_form = document.createElement('form');
198 const comment_input = document.createElement('input')
199 comment_input.type = "text";
200 comment_input.className = "comment";
201 comment_input.placeholder = "Add a comment";
202 comment_form.appendChild(comment_input);
203 figure.appendChild(comment_form);
205 comment_input.addEventListener('focus', () => {
206 /* If the server has informed us it has our name, we are done. */
210 /* If server has no name, check local storage. */
211 const name = localStorage.getItem('name');
213 socket.emit('set-name', name);
217 /* Failing both, bring up the modal dialog to set the name. */
218 name_dialog.showModal();
221 comment_form.addEventListener('submit', function(e) {
223 if (comment_input.value) {
224 socket.emit('comment', {comments_id: comments_id,
225 text: comment_input.value});
226 comment_input.value = '';
230 images.prepend(figure);
233 function hide_spinner() {
234 zombo_form.style.display = "grid";
235 spinner.style.display = "none";
238 zombo_form.addEventListener('submit', function(e) {
240 /* Hide the form and show spinner while generation is happening. */
241 zombo_form.style.display = "none";
242 spinner.style.display = "block";
243 spinner_timeout = setTimeout(hide_spinner, 60000);
244 socket.emit('generate', {"prompt": prompt.value, "code": code.value});
248 socket.on('generation-done', () => {
249 /* Re-display the form and hide spinner now that generation is over. */
250 clearTimeout(spinner_timeout);
254 function random_from(items) {
255 return items[Math.floor(Math.random()*items.length)];
258 safety.addEventListener("click", () => {
261 "A hyperrealistic photograph of",
262 "A matte painting of",
263 "Epic fantasy card art of",
264 "Professional oil painting of",
266 "A pencil sketch of",
269 "A marble statue of",
274 " a Porsche 911 Carrera",
278 " an elfin princess",
280 " pastel purple clouds",
281 " a Teenage Mutant Ninja Turtle",
285 " in tropical surroundings",
287 " in an ocean storm",
288 " in a snowy forest",
289 " in a cardboard box",
291 " in an epic landscape",
292 " in a haunted forest",
293 " riding a motorbike",
294 " in a futuristic city at night",
295 " in a dystopian landscape, foggy",
296 " in the land of snow",
297 " that looks like a watermelon",
298 " on the streets of London at night with neon lights flashing",
299 " that is part octopus",
300 " melting into a puddle",
301 " on a birthday cake",
307 " by Vincent Van Gogh",
309 " by Johannes Vermeer",
310 ", fantasy art, neon fog",
311 ", epic lighting from above",
312 ", trending on artstation",
314 " by Leonardo da Vinci",
317 prompt.value = random_from(art_type) + random_from(subject) +
318 random_from(scenery) + random_from(artist);