Will be awesome one day, I guarantee you
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

h

authored by

Cldprv and committed by
Tangled
ed257ec7 5104a041

+314 -103
+8 -7
index.html
··· 1 1 <!DOCTYPE html> 2 - <html lang="en"> 2 + <html lang="fr"> 3 3 <head> 4 4 <meta charset="UTF-8"> 5 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> ··· 19 19 s.parentNode.insertBefore(ws, s); 20 20 })(); 21 21 </script> 22 + <script defer data-site="e0b530eb8ba8e4b4" src="https://analytics-keeper--clement070110.replit.app/api/track.js"></script> 22 23 </head> 23 24 <body> 24 - 25 + 25 26 <div id="content"> 26 27 <header> 27 28 <h1>WIP - Revenez plus tard?</h1> 28 - <div> 29 + <div class="meta"> 29 30 <p id="compteur">Version: 29.04.2026.1</p> 30 - <p>Copyright: Cld</p> 31 + <p>Copyright : Cld</p> 31 32 </div> 32 33 </header> 33 34 <p>Hébergé par <a href="https://www.tangled.org">tangled.org</a></p> ··· 35 36 <h2>De l'inutilité des concours de philosophie</h2> 36 37 <subscriptum><i><s>Essai</s> Texte distrayant</i></subscriptum> 37 38 --> 38 - <h2>Ci-dessous un certain nombre de boutons <b style="background-color: rgb(132, 0, 0); color:white;">TOUS</b> fortement <b style="background-color: rgb(132, 0, 0); color:white;">déconseillés.</b></h2> 39 + <h2>Ci-dessous un certain nombre de boutons <b class="highlight">TOUS</b> fortement <b class="highlight">déconseillés.</b></h2> 39 40 <div class="btns"> 40 41 <button class="nepastoucher">On ne perd rien à essayer!</button> 41 42 <button class="nepastoucher">Par-ici!</button> 42 43 <button id="compteurplusun">APPUYEZ ICI</button> 43 44 <button id="achatautoclick">ICI C'EST MIEUX</button> 44 - <button id="gameover" style="background-color: red;">Les boutons rouges c'est gameover.</button> 45 + <button id="gameover" class="danger-button">Les boutons rouges c'est gameover.</button> 45 46 </div> 46 - <p style="display:none;color:rgb(168, 0, 0); margin:15px;" id="prevention">Vous étiez prévenu;Pas de PITIÉ</p> 47 + <p id="prevention" class="hidden">Vous étiez prévenu; Pas de PITIÉ</p> 47 48 </div> 48 49 49 50 <script src="script.js"></script>
+236 -54
script.js
··· 1 - let versionBase = "29.04.2026."; 2 - let counter = 1; 3 - let nbAutoClick = 0; 4 - let autoClickInterval = null; 1 + const VERSION_BASE = '29.04.2026.'; 2 + const STORAGE_KEY = 'nepastoucherTime'; 3 + const GAMEOVER_STORAGE_KEY = 'gameoverTime'; 4 + const WARNING_DURATION_MS = 10 * 60 * 1000; 5 + 6 + const versionEl = document.getElementById('compteur'); 7 + const contentEl = document.getElementById('content'); 8 + const preventionEl = document.getElementById('prevention'); 9 + const choiceButtons = document.querySelectorAll('.nepastoucher'); 10 + const counterButton = document.getElementById('compteurplusun'); 11 + const buyAutoClickButton = document.getElementById('achatautoclick'); 12 + const gameOverButton = document.getElementById('gameover'); 13 + 14 + const state = { 15 + counter: 1, 16 + autoClickCount: 0, 17 + autoClickAccumulator: 0, 18 + versionFlashColor: '', 19 + versionFlashExpiry: 0, 20 + autoClickInterval: 1000, 21 + isGameOver: false, 22 + fallingElements: [], 23 + baseGravity: 0.0009, 24 + bounceDamping: 0.6 25 + }; 26 + 27 + const formatVersion = () => `Version: ${VERSION_BASE}${state.counter}`; 28 + 29 + const updateVersionText = () => { 30 + versionEl.textContent = formatVersion(); 31 + }; 32 + 33 + const flashVersion = (color, duration = 500) => { 34 + state.versionFlashColor = color; 35 + state.versionFlashExpiry = performance.now() + duration; 36 + versionEl.style.color = color; 37 + }; 5 38 6 - function updateVersion() { 7 - document.getElementById('compteur').innerText = "Version: " + versionBase + counter; 8 - } 39 + const getAutoClickCost = () => Math.max(1, Math.round(5 * state.autoClickCount)); 9 40 10 - function applyEffect() { 11 - document.getElementById('content').style.transform = 'rotate(0.5turn)'; 12 - document.querySelectorAll('.nepastoucher').forEach(btn => btn.style.display = 'none'); 13 - document.getElementById('prevention').style.display = 'block'; 14 - } 41 + const applyWarningEffect = () => { 42 + contentEl.classList.add('rotated'); 43 + preventionEl.classList.remove('hidden'); 44 + choiceButtons.forEach(button => button.classList.add('hidden')); 45 + }; 46 + 47 + const saveWarningTime = () => { 48 + localStorage.setItem(STORAGE_KEY, Date.now().toString()); 49 + }; 50 + 51 + const loadWarningState = () => { 52 + const storedTime = localStorage.getItem(STORAGE_KEY); 53 + if (!storedTime) { 54 + return; 55 + } 56 + 57 + const elapsed = Date.now() - Number(storedTime); 58 + if (elapsed < WARNING_DURATION_MS) { 59 + applyWarningEffect(); 60 + } else { 61 + localStorage.removeItem(STORAGE_KEY); 62 + } 63 + }; 64 + 65 + const saveGameOverTime = () => { 66 + localStorage.setItem(GAMEOVER_STORAGE_KEY, Date.now().toString()); 67 + }; 15 68 16 - window.addEventListener('load', function() { 17 - updateVersion(); 18 - const storedTime = localStorage.getItem('nepastoucherTime'); 19 - if (storedTime) { 20 - const elapsed = Date.now() - parseInt(storedTime); 21 - if (elapsed < 10 * 60 * 1000) { // 10 minutes 22 - applyEffect(); 23 - } else { 24 - localStorage.removeItem('nepastoucherTime'); 25 - } 26 - } 27 - }); 69 + const loadGameOverState = () => { 70 + const storedTime = localStorage.getItem(GAMEOVER_STORAGE_KEY); 71 + if (!storedTime) { 72 + return; 73 + } 28 74 29 - document.querySelectorAll('.nepastoucher').forEach(btn => { 30 - btn.addEventListener('click', function() { 31 - localStorage.setItem('nepastoucherTime', Date.now()); 32 - applyEffect(); 75 + const elapsed = Date.now() - Number(storedTime); 76 + if (elapsed < WARNING_DURATION_MS) { 77 + state.isGameOver = true; 78 + const allButtons = document.querySelectorAll('button'); 79 + allButtons.forEach(button => { 80 + button.disabled = true; 33 81 }); 34 - }); 82 + prepareFallingElements(); 83 + // Move all elements to bottom position immediately 84 + state.fallingElements.forEach(entry => { 85 + entry.settled = true; 86 + entry.velocity = 0; 87 + const bottomLimit = window.innerHeight - entry.height; 88 + entry.top = bottomLimit; 89 + entry.node.style.top = `${entry.top}px`; 90 + }); 91 + } else { 92 + localStorage.removeItem(GAMEOVER_STORAGE_KEY); 93 + } 94 + }; 35 95 36 - document.getElementById('compteurplusun').addEventListener('click', function() { 37 - let versionEl = document.querySelector('header p'); 38 - versionEl.style.color = 'green'; 39 - setTimeout(() => versionEl.style.color = '', 300); 40 - counter++; 41 - updateVersion(); 42 - }); 96 + const prepareFallingElements = () => { 97 + const elements = Array.from(document.querySelectorAll('p, button, h1, h2')); 98 + 99 + // First pass: capture all positions before any DOM changes 100 + const elementData = elements.map(node => { 101 + const rect = node.getBoundingClientRect(); 102 + return { 103 + node, 104 + left: rect.left, 105 + top: rect.top, 106 + width: rect.width, 107 + height: rect.height 108 + }; 109 + }); 43 110 44 - document.getElementById('achatautoclick').addEventListener('click', function() { 45 - let cost = Math.round(5 * nbAutoClick); 46 - let versionEl = document.querySelector('header p'); 47 - if (counter >= cost) { 48 - versionEl.style.color = 'yellow'; 49 - setTimeout(() => versionEl.style.color = '', 1000); 50 - counter -= cost; 51 - nbAutoClick++; 52 - updateVersion(); 53 - if (!autoClickInterval) { 54 - autoClickInterval = setInterval(() => { 55 - counter++; 56 - updateVersion(); 57 - }, 2000); 111 + // Second pass: apply positioning and create fall entries 112 + elementData.forEach(data => { 113 + const { node, left, top, width, height } = data; 114 + 115 + node.style.position = 'fixed'; 116 + node.style.left = `${left}px`; 117 + node.style.top = `${top}px`; 118 + node.style.width = `${width}px`; 119 + node.style.height = `${height}px`; 120 + node.style.margin = '0'; 121 + node.style.padding = node.style.padding || ''; 122 + node.style.boxSizing = 'border-box'; 123 + node.style.transition = 'none'; 124 + 125 + state.fallingElements.push({ 126 + node, 127 + top, 128 + width, 129 + height, 130 + velocity: (Math.random() - 0.5) * 0.3, 131 + gravity: state.baseGravity * (0.5 + Math.random()), 132 + bounceDamping: state.bounceDamping * (0.5 + Math.random() * 0.5), 133 + settled: false 134 + }); 135 + }); 136 + }; 137 + 138 + const startGameOverFall = () => { 139 + if (state.isGameOver) { 140 + return; 141 + } 142 + 143 + state.isGameOver = true; 144 + saveGameOverTime(); 145 + 146 + // Disable all buttons 147 + const allButtons = document.querySelectorAll('button'); 148 + allButtons.forEach(button => { 149 + button.disabled = true; 150 + }); 151 + 152 + prepareFallingElements(); 153 + }; 154 + 155 + const tick = (delta) => { 156 + if (state.autoClickCount > 0) { 157 + state.autoClickAccumulator += delta; 158 + const clicks = Math.floor(state.autoClickAccumulator / state.autoClickInterval) * state.autoClickCount; 159 + if (clicks > 0) { 160 + state.autoClickAccumulator %= state.autoClickInterval; 161 + state.counter += clicks; 162 + updateVersionText(); 163 + } 164 + } 165 + 166 + if (state.isGameOver) { 167 + state.fallingElements.forEach(entry => { 168 + // Apply gravity 169 + entry.velocity += entry.gravity * delta; 170 + entry.top += entry.velocity * delta; 171 + 172 + const bottomLimit = window.innerHeight - entry.height; 173 + 174 + // Bounce collision 175 + if (entry.top >= bottomLimit) { 176 + entry.top = bottomLimit; 177 + entry.velocity *= -entry.bounceDamping; 178 + 179 + // Stop bouncing when velocity is very small 180 + if (Math.abs(entry.velocity) < 0.1) { 181 + entry.velocity = 0; 182 + entry.settled = true; 58 183 } 184 + } 185 + 186 + entry.node.style.top = `${entry.top}px`; 187 + }); 188 + } 189 + 190 + if (state.versionFlashExpiry && performance.now() >= state.versionFlashExpiry) { 191 + state.versionFlashColor = ''; 192 + state.versionFlashExpiry = 0; 193 + versionEl.style.color = ''; 194 + } 195 + }; 196 + 197 + const gameLoop = (timestamp) => { 198 + if (!gameLoop.lastTime) { 199 + gameLoop.lastTime = timestamp; 200 + } 201 + 202 + const delta = timestamp - gameLoop.lastTime; 203 + gameLoop.lastTime = timestamp; 204 + 205 + tick(delta); 206 + requestAnimationFrame(gameLoop); 207 + }; 208 + 209 + const init = () => { 210 + updateVersionText(); 211 + loadWarningState(); 212 + loadGameOverState(); 213 + 214 + choiceButtons.forEach(button => { 215 + button.addEventListener('click', () => { 216 + saveWarningTime(); 217 + applyWarningEffect(); 218 + }); 219 + }); 220 + 221 + counterButton.addEventListener('click', () => { 222 + state.counter += 1; 223 + updateVersionText(); 224 + flashVersion('green', 300); 225 + }); 226 + 227 + buyAutoClickButton.addEventListener('click', () => { 228 + const cost = getAutoClickCost(); 229 + if (state.counter >= cost) { 230 + state.counter -= cost; 231 + state.autoClickCount += 1; 232 + updateVersionText(); 233 + flashVersion('yellow', 1000); 59 234 } else { 60 - versionEl.style.color = 'red'; 61 - setTimeout(() => versionEl.style.color = '', 1000); 62 - console.log("Pas assez de points pour acheter un autoclick."); 235 + flashVersion('red', 1000); 63 236 } 64 - }); 237 + }); 238 + 239 + gameOverButton.addEventListener('click', () => { 240 + startGameOverFall(); 241 + }); 242 + 243 + requestAnimationFrame(gameLoop); 244 + }; 245 + 246 + document.addEventListener('DOMContentLoaded', init);
+70 -42
style.css
··· 1 1 body { 2 - font-family: monospace; 3 - margin: 0px 20px 20px 20px 2 + font-family: monospace; 3 + margin: 0 20px 20px; 4 4 } 5 - h1{ 6 - font-weight: 200; 7 - font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif; 5 + 6 + h1 { 7 + font-weight: 200; 8 + font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif; 8 9 } 10 + 9 11 h2 { 10 - display: inline-block; 11 - } 12 - subscriptum { 13 - display: inline; 12 + display: inline-block; 14 13 } 14 + 15 15 header { 16 - display: flex; 17 - justify-content: space-between; 18 - align-items: center; 16 + display: flex; 17 + justify-content: space-between; 18 + align-items: center; 19 + gap: 1rem; 19 20 } 20 - header div { 21 - display: flex; 22 - flex-direction: column; 21 + 22 + header .meta { 23 + display: flex; 24 + flex-direction: column; 23 25 } 26 + 24 27 header p { 25 - margin: 2px; 28 + margin: 2px; 29 + position:sticky; 26 30 } 31 + 27 32 @media (max-width: 600px) { 28 - header { 29 - flex-direction: column; 30 - align-items: flex-start; 31 - } 32 - h1 { 33 - font-size: 1.2em; 34 - } 33 + header { 34 + flex-direction: column; 35 + align-items: flex-start; 36 + } 37 + 38 + h1 { 39 + font-size: 1.2em; 40 + } 35 41 } 42 + 36 43 #content { 37 - transition: transform; 44 + transition: transform 0.3s ease; 45 + } 46 + 47 + #content.rotated { 48 + transform: rotate(180deg); 49 + } 50 + 51 + .hidden { 52 + display: none; 38 53 } 39 54 40 55 #prevention { 41 - display: none; 42 - color: red; 56 + color: red; 57 + margin: 15px 0; 43 58 } 59 + 44 60 .btns { 45 - margin: 0px -20px; 46 - display:flex; 47 - flex-wrap: wrap; 48 - width: 100%; 61 + margin: 0 -20px; 62 + display: flex; 63 + flex-wrap: wrap; 64 + gap: 8px; 65 + width: calc(100% + 40px); 49 66 } 67 + 50 68 .btns button { 51 - display:inline; 52 - margin:0; 53 - padding: 10px 20px; 54 - font-size: 1em; 55 - cursor: pointer; 56 - background-color: black; 57 - color:white; 58 - border-radius: none; 59 - outline:none; 60 - border:none; 69 + margin: 0; 70 + padding: 10px 20px; 71 + font-size: 1em; 72 + cursor: pointer; 73 + background-color: black; 74 + color: white; 75 + border: 0; 76 + border-radius: 0; 77 + outline: none; 61 78 } 62 - button:hover { 63 - background-color: #333; 79 + 80 + .btns button:hover { 81 + background-color: #333; 82 + } 83 + 84 + .highlight { 85 + background-color: rgb(132, 0, 0); 86 + color: white; 87 + padding: 0 0.25rem; 88 + } 89 + 90 + .btns button.danger-button { 91 + background-color: red; 64 92 }