]> git.cworth.org Git - zombocom-ai/blob - index.html
Revert "Don't show any images until the user generates a new one"
[zombocom-ai] / index.html
1 <!DOCTYPE html>
2 <html>
3
4 <head>
5   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
6   <title>ZOMBO</title>
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">
11 </head>
12
13 <body>
14   <div id="content">
15
16     <div id="header" align="center">
17       <p>
18         <br>
19       </p>
20
21       <p>
22         <img src="/zombocom.png" alt="Zombocom" longdesc="http://zombo.com" width="1199" height="217">
23       </p>
24     </div>
25
26     <p>
27       Welcome to Zombocom. You can do anything at Zombocom, anything at
28       all. The only limit is yourself!
29     </p>
30
31     <dialog id="name-dialog">
32       <form method="dialog">
33         <p>
34           <label>Your name:
35             <input id="name" type="text" autocomplete="off">
36           </label>
37         </p>
38         <div>
39           <button value="default">OK</button>
40         </div>
41       </form>
42     </dialog>
43
44     <p>
45       <div id="spinner" align="center">
46         <div class="animate-flicker">
47           <p>
48             <img src="/pngwheel.png" class="rotate thefade">
49           </p>
50         </div>
51       </div>
52
53       <form action="" id="zombo-form">
54         <div class="form-row large">
55           <label for="prompt">
56             What can you imagine?
57           </label>
58           <button id="safety" type="button">Safety prompt</button>
59           <textarea id="prompt" rows="4" width="100%" autocomplete="off" required></textarea>
60         </div>
61
62         <div class="form-row small left">
63           <div class="labeled-row">
64             <label for="code">
65               Numeric code:
66             </label>
67             <input id="code" type="number" min="0" max="4294967295" autocomplete="off" placeholder="(Leave blank for random)" />
68           </div>
69         </div>
70
71         <div class="form-row large">
72           <button id="generate" type="submit">Make the infinite possible</button>
73         </div>
74       </form>
75     </p>
76
77     <div id="images">
78     </div>
79
80     <audio loop="" src="/zombo_words.mp3" type="audio/mpeg"></audio>
81     <button id="mute" class="menu-button fade volume">
82       <div>🔊</div>
83       <script>
84 const mute = document.querySelector("#mute");
85 const icon = document.querySelector("#mute > div");
86 const audio = document.querySelector("audio");
87
88 mute.addEventListener("click", () => {
89   if (audio.paused) {
90       audio.volume = 0.2;
91       audio.play();
92       icon.innerHTML = "🔈";
93   } else {
94       audio.pause();
95       icon.innerHTML = "🔊";
96   }
97   mute.classList.add("fade");
98 });
99       </script>
100
101     </button>
102
103     <button id="profile" class="menu-button">
104       <div>👤</div>
105     </button>
106
107   </div>
108
109   <script src="/socket.io/socket.io.js"></script>
110   <script>
111     var socket = io();
112
113     const name_input = document.querySelector("#name");
114     const name_dialog = document.querySelector("#name-dialog");
115     const images = document.querySelector("#images");
116     const zombo_form = document.querySelector("#zombo-form");
117     const prompt = document.querySelector("#prompt");
118     const code = document.querySelector("#code");
119     const safety= document.querySelector("#safety");
120     const spinner = document.querySelector("#spinner");
121     const profile = document.querySelector("#profile");
122     var spinner_timeout;
123
124     profile.addEventListener('click', () => {
125         name_dialog.showModal();
126     });
127
128     name_dialog.addEventListener('close', () => {
129         socket.emit('set-name', name_input.value);
130     });
131
132     socket.on('comment', function(comment) {
133         const comments = document.querySelector("#" + comment.comments_id);
134         const dt = document.createElement('dt');
135         const dd = document.createElement('dd');
136         dt.textContent = comment.name + ':';
137         dd.textContent = comment.text;
138         comments.appendChild(dt);
139         comments.appendChild(dd);
140     });
141
142     socket.on('inform-name', (name) => {
143         console.log("Received inform-name event: " + name);
144         name_input.value = name;
145     });
146
147     socket.on('reset', () => {
148         images.replaceChildren();
149     });
150
151     socket.on('image', (image) => {
152         const figure = document.createElement('figure');
153
154         const img = document.createElement('img');
155         img.src = image.filename;
156         figure.appendChild(img);
157
158         const figcaption = document.createElement('figcaption');
159         const caption_text = document.createTextNode(`${image.prompt} (${image.code}) `);
160         figcaption.appendChild(caption_text);
161
162         const reuse_button = document.createElement('button');
163         reuse_button.appendChild(document.createTextNode("Reuse"));
164         figcaption.appendChild(reuse_button);
165
166         reuse_button.addEventListener('click', () => {
167             prompt.value = image.prompt;
168             window.scrollTo(0,0);
169         });
170
171         figure.appendChild(figcaption);
172
173         const dl_comments = document.createElement('dl');
174         const comments_id = "comments_" + image.index;
175         dl_comments.className = "comments";
176         dl_comments.id = comments_id;
177         figure.appendChild(dl_comments);
178
179         const comment_form = document.createElement('form');
180         const comment_input = document.createElement('input')
181         comment_input.type = "text";
182         comment_input.className = "comment";
183         comment_input.placeholder = "Add a comment";
184         comment_form.appendChild(comment_input);
185         figure.appendChild(comment_form);
186
187         comment_input.addEventListener('focus', () => {
188             /* Do nothing if name is already set. */
189             if (name_input.value)
190                 return;
191
192             /* Otherwise, bring up the modal dialog to set the name. */
193             name_dialog.showModal();
194         });
195
196         comment_form.addEventListener('submit', function(e) {
197             e.preventDefault();
198             if (comment_input.value) {
199                 socket.emit('comment', {comments_id: comments_id,
200                                         text: comment_input.value});
201                 comment_input.value = '';
202             }
203         });
204
205         images.prepend(figure);
206     });
207
208     function hide_spinner() {
209         zombo_form.style.display = "grid";
210         spinner.style.display = "none";
211     }
212
213     zombo_form.addEventListener('submit', function(e) {
214         e.preventDefault();
215         /* Hide the form and show spinner while generation is happening. */
216         zombo_form.style.display = "none";
217         spinner.style.display = "block";
218         spinner_timeout = setTimeout(hide_spinner, 60000);
219         socket.emit('generate', {"prompt": prompt.value, "code": code.value});
220         prompt.value = '';
221     });
222
223     socket.on('generation-done', () => {
224         /* Re-display the form and hide spinner now that generation is over. */
225         clearTimeout(spinner_timeout);
226         hide_spinner();
227     });
228
229     function random_from(items) {
230         return items[Math.floor(Math.random()*items.length)];
231     }
232
233     safety.addEventListener("click", () => {
234         const art_type = [
235             "A portrait of",
236             "A hyperrealistic photograph of",
237             "A matte painting of",
238             "Epic fantasy card art of",
239             "Professional oil painting of",
240             "An image of",
241             "A pencil sketch of",
242             "A watercolor of",
243             "A 3D rendering of",
244             "A marble statue of",
245         ];
246         const subject = [
247             " a modern home",
248             " crashing waves",
249             " a Porsche 911 Carrera",
250             " a Halo spartan",
251             " a cute cat",
252             " a mad scientist",
253             " an elfin princess",
254             " sci-fi buildings",
255             " pastel purple clouds",
256             " a Teenage Mutant Ninja Turtle",
257             " Pikachu",
258         ];
259         const scenery = [
260             " in tropical surroundings",
261             " in space",
262             " in an ocean storm",
263             " in a snowy forest",
264             " in a cardboard box",
265             " holding an axe",
266             " in an epic landscape",
267             " in a haunted forest",
268             " riding a motorbike",
269             " in a futuristic city at night",
270             " in a dystopian landscape, foggy",
271             " in the land of snow",
272             " that looks like a watermelon",
273             " on the streets of London at night with neon lights flashing",
274             " that is part octopus",
275             " melting into a puddle",
276             " on a birthday cake",
277         ];
278         const artist = [
279             ", unreal engine 5",
280             ", concept art",
281             ", graphic novel",
282             " by Vincent Van Gogh",
283             " by Claude Monet",
284             " by Johannes Vermeer",
285             ", fantasy art, neon fog",
286             ", epic lighting from above",
287             ", trending on artstation",
288             " by Gustav Klimt",
289             " by Leonardo da Vinci",
290         ];
291
292         prompt.value = random_from(art_type) + random_from(subject) +
293             random_from(scenery) + random_from(artist);
294         return false;
295     });
296
297   </script>
298 </body>
299 </html>