Last active
June 27, 2024 07:55
-
-
Save sneakers-the-rat/0e41fe4747f0871c1f4aca514ea4ba63 to your computer and use it in GitHub Desktop.
Snake for onemillioncheckboxes.com
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Snake interface for onemillioncheckboxes.com | |
// with love from jonny | |
var direction; | |
var current_box; | |
var check_time = +new Date(); | |
var scroll_debounce = false; | |
const SPACE_MULTIPLIER = 3; | |
const spacing = 35; | |
const interval = 150; | |
var viewRect; | |
// ensure a function is only called every n milliseconds | |
function debounce(fn, delay) { | |
return () => { | |
let currentTime = +new Date(); | |
if (currentTime > check_time + delay){ | |
check_time = currentTime; | |
fn(); | |
} | |
} | |
} | |
// check whatever box we are hovering over | |
function checkHover(){ | |
const el = document.querySelector( "input:hover" ); | |
if (el === null){ | |
return | |
}; | |
current_box = el; | |
if (el.checked !== true) { | |
el.click(); | |
} | |
} | |
// save an arrow key when pressed | |
function getKey(e){ | |
switch(e.key){ | |
case 'ArrowUp': | |
direction = 'up'; | |
e.preventDefault(); | |
break; | |
case 'ArrowDown': | |
direction = 'down'; | |
e.preventDefault(); | |
break; | |
case 'ArrowLeft': | |
direction = 'left'; | |
e.preventDefault(); | |
break; | |
case 'ArrowRight': | |
direction = 'right'; | |
e.preventDefault(); | |
break; | |
} | |
} | |
// periodically get the adjacent box to the current box we are on, | |
// click on it, and set it as the new box, depending on which | |
// direction we are moving. | |
function move(){ | |
if (current_box === undefined){return}; | |
let rect = current_box.getBoundingClientRect(); | |
let x = (rect.left + rect.right) / 2; | |
let y = (rect.top + rect.bottom) / 2; | |
var x_new = x, y_new = y; | |
switch (direction){ | |
case 'up': | |
y_new -= spacing; | |
break; | |
case 'down': | |
y_new += spacing; | |
break; | |
case 'left': | |
x_new -= spacing; | |
break; | |
case 'right': | |
x_new += spacing; | |
break; | |
} | |
// get the new box | |
let el = document.elementFromPoint(x_new, y_new); | |
// if it isn't a checkbox we don't care about it | |
if (el.nodeName !== 'INPUT'){return}; | |
current_box = el; | |
// make sure it's checked | |
if (el.checked !== true){el.click()}; | |
// scroll if we need to | |
if (viewRect === undefined){setGrid()}; | |
// but come back later if we still haven't loaded | |
if (viewRect === undefined){break}; | |
if (y <= viewRect.top + (spacing*SPACE_MULTIPLIER) || y >= viewRect.bottom - (spacing*SPACE_MULTIPLIER)){ | |
if (scroll_debounce === true){return}; | |
if (direction === 'up'){ | |
el.scrollIntoView({block: 'end'}); | |
} else { | |
el.scrollIntoView({block: 'start'}); | |
} | |
scroll_debounce = true; | |
} else { | |
scroll_debounce = false; | |
} | |
} | |
function setGrid(){ | |
viewRect = document.querySelector('.grid').getBoundingClientRect(); | |
} | |
const debouncedHover = debounce(checkHover, 100); | |
window.addEventListener('load', () => { | |
document.addEventListener('keydown', getKey); | |
document.addEventListener('mousemove', debouncedHover); | |
window.addEventListener('resize', setGrid); | |
setInterval(move, interval); | |
console.log("SNAKE LOADED"); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment