Skip to content

Instantly share code, notes, and snippets.

@sneakers-the-rat
Last active June 27, 2024 07:55
Show Gist options
  • Save sneakers-the-rat/0e41fe4747f0871c1f4aca514ea4ba63 to your computer and use it in GitHub Desktop.
Save sneakers-the-rat/0e41fe4747f0871c1f4aca514ea4ba63 to your computer and use it in GitHub Desktop.
Snake for onemillioncheckboxes.com
// 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