<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ZOMBO</title>
<link href="/zombo.css" rel="stylesheet" type="text/css">
- <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
+ <meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="HandheldFriendly" content="true">
</head>
<body>
- <div align="center">
- <p>
- <br>
- </p>
+ <div id="content">
+
+ <div id="header" align="center">
+ <p>
+ <br>
+ </p>
+
+ <p>
+ <img src="/zombocom.png" alt="Zombocom" longdesc="http://zombo.com" width="1199" height="217">
+ </p>
+ </div>
<p>
- <img src="/zombocom.png" alt="Zombocom" longdesc="http://zombo.com" width="1199" height="217">
+ Welcome to Zombocom. You can do anything at Zombocom, anything at
+ all. The only limit is yourself!
</p>
- </div>
- <p>
- Welcome to Zombocom. You can do anything at Zombcom, anything at
- all. The only limit is yourself!
- </p>
-
- <p>
- <form action="" id="zombo-form">
- <div class="form-row large">
- <label for="prompt">
- What do you imagine?
- </label>
- <input id="prompt" autocomplete="off" required />
- </div>
+ <dialog id="name-dialog">
+ <form method="dialog">
+ <p>
+ <label>Your name:
+ <input id="name" type="text">
+ </label>
+ </p>
+ <div>
+ <button value="cancel">Cancel</button>
+ <button id="confirm" value="default">Confirm</button>
+ </div>
+ </form>
+ </dialog>
- <div class="form-row small left">
- <label for="code">
- Numeric code
- </label>
- <input id="code" autocomplete="off" placeholder="(Chosen randomly)" />
+ <p>
+ <div id="spinner" align="center">
+ <div class="animate-flicker">
+ <p>
+ <img src="/pngwheel.png" class="rotate thefade">
+ </p>
+ </div>
</div>
- <div class="form-row small right">
- <button>Safety prompt</button>
- </div>
+ <form action="" id="zombo-form">
+ <div class="form-row large">
+ <label for="prompt">
+ What can you imagine?
+ </label>
+ <button id="safety" type="button">Safety prompt</button>
+ <textarea id="prompt" rows="4" width="100%" autocomplete="off" required></textarea>
+ </div>
- <div class="form-row large">
- <button>Make the infinite possible</button>
- </div>
- </form>
- </p>
-
- <div align="center">
- <div class="animate-flicker">
- <p>
- <img src="/pngwheel.png" class="rotate thefade">
- </p>
- </div>
- </div>
+ <div class="form-row small left">
+ <div class="labeled-row">
+ <label for="code">
+ Numeric code:
+ </label>
+ <input id="code" type="text" autocomplete="off" placeholder="(Leave blank for random)" />
+ </div>
+ </div>
- <audio loop="" src="/zombo_words.mp3" type="audio/mpeg"></audio>
- <button id="mute" class="fade volume">
- <div>🔊</div>
- <script>
+ <div class="form-row large">
+ <button id="generate" type="submit">Make the infinite possible</button>
+ </div>
+ </form>
+ </p>
+
+ <div id="images">
+ </div>
+
+ <ul id="comments">
+ </ul>
+
+ <p>
+ <form action="" id="comment-form">
+ <input id="comment" type="text" style="width:100%" autocomplete="off" placeholder="Add a comment" />
+ </form>
+ </p>
+
+ <audio loop="" src="/zombo_words.mp3" type="audio/mpeg"></audio>
+ <button id="mute" class="menu-button fade volume">
+ <div>🔊</div>
+ <script>
const mute = document.querySelector("#mute");
const icon = document.querySelector("#mute > div");
const audio = document.querySelector("audio");
}
mute.classList.add("fade");
});
- </script>
+ </script>
+
+ </button>
+
+ <button id="profile" class="menu-button">
+ <div>👤</div>
+ </button>
+
+ </div>
+
+ <script src="/socket.io/socket.io.js"></script>
+ <script>
+ var socket = io();
+
+ const name = document.querySelector("#name");
+ const name_dialog = document.querySelector("#name-dialog");
+ const images = document.querySelector("#images");
+ const comments = document.querySelector("#comments");
+ const comment_form = document.querySelector("#comment-form");
+ const comment = document.querySelector("#comment");
+ const zombo_form = document.querySelector("#zombo-form");
+ const prompt = document.querySelector("#prompt");
+ const code = document.querySelector("#code");
+ const safety= document.querySelector("#safety");
+ const spinner = document.querySelector("#spinner");
+ const profile = document.querySelector("#profile");
+ var spinner_timeout;
+
+ comment.addEventListener('focus', () => {
+ /* Do nothing if name is already set. */
+ if (name.value)
+ return;
+
+ /* Otherwise, bring up the modal dialog to set the name. */
+ name_dialog.showModal();
+ });
+
+ profile.addEventListener('click', () => {
+ name_dialog.showModal();
+ });
+
+ name_dialog.addEventListener('close', () => {
+ socket.emit('set-name', name.value);
+ });
+
+ comment_form.addEventListener('submit', function(e) {
+ e.preventDefault();
+ if (comment.value) {
+ socket.emit('comment', comment.value);
+ comment.value = '';
+ }
+ });
+
+ socket.on('comment', function(msg) {
+ var item = document.createElement('li');
+ item.textContent = msg;
+ comments.appendChild(item);
+ });
+
+ socket.on('inform-name', (name) => {
+ console.log("Received inform-name event: " + name);
+ name.value = name;
+ });
+
+ socket.on('reset', () => {
+ images.replaceChildren();
+ });
+
+ socket.on('image', (image) => {
+ const figure = document.createElement('figure');
+ const img = document.createElement('img');
+ img.src = image.filename;
+ const figcaption = document.createElement('figcaption');
+ const caption_text = document.createTextNode(`${image.prompt} (${image.code})`);
+ figcaption.appendChild(caption_text);
+ figure.appendChild(img);
+ figure.appendChild(figcaption);
+ images.prepend(figure);
+ });
+
+ function hide_spinner() {
+ zombo_form.style.display = "grid";
+ spinner.style.display = "none";
+ }
+
+ zombo_form.addEventListener('submit', function(e) {
+ e.preventDefault();
+ /* Hide the form and show spinner while generation is happening. */
+ zombo_form.style.display = "none";
+ spinner.style.display = "block";
+ spinner_timeout = setTimeout(hide_spinner, 60000);
+ socket.emit('generate', {"prompt": prompt.value, "code": code.value});
+ prompt.value = '';
+ });
+
+ socket.on('generation-done', () => {
+ /* Re-display the form and hide spinner now that generation is over. */
+ clearTimeout(spinner_timeout);
+ hide_spinner();
+ });
+
+ function random_from(items) {
+ return items[Math.floor(Math.random()*items.length)];
+ }
+
+ safety.addEventListener("click", () => {
+ const art_type = [
+ "A portrait of",
+ "A hyperrealistic photograph of",
+ "A matte painting of",
+ "Epic fantasy card art of",
+ "Professional oil painting of",
+ "An image of",
+ "A pencil sketch of",
+ "A watercolor of",
+ ];
+ const subject = [
+ " a modern home",
+ " crashing waves",
+ " a Porsche 911 Carrera",
+ " a Halo spartan",
+ " a cute cat",
+ " a mad scientist",
+ " an elfin princess",
+ " sci-fi buildings",
+ " pastel purple clouds",
+ " a Teenage Mutant Ninja Turtle",
+ ];
+ const scenery = [
+ " in tropical surroundings",
+ " in space",
+ " in an ocean storm",
+ " in a snowy forest",
+ " in a cardboard box",
+ " holding an axe",
+ " in an epic landscape",
+ " in a haunted forest",
+ " riding a motorbike",
+ " in a futuristic city at night",
+ " in a dystopian landscape, foggy",
+ " in the land of snow",
+ " that looks like a watermelon",
+ " on the streets of London at night with neon lights flashing",
+ " that is part octopus",
+ " melting into a puddle",
+ ];
+ const artist = [
+ ", unreal engine 5",
+ ", concept art",
+ ", graphic novel",
+ " by Vincent Van Gogh",
+ " by Claude Monet",
+ " by Johannes Vermeer",
+ ", fantasy art, neon fog",
+ ", epic lighting from above",
+ ", trending on artstation",
+ ];
+
+ prompt.value = random_from(art_type) + random_from(subject) +
+ random_from(scenery) + random_from(artist);
+ return false;
+ });
- </button>
+ </script>
</body>
</html>