Skip to content

Instantly share code, notes, and snippets.

@noppelmax
Created August 28, 2025 18:13
Show Gist options
  • Save noppelmax/32d01c8d160f19b3d0bf2c5298c761a4 to your computer and use it in GitHub Desktop.
Save noppelmax/32d01c8d160f19b3d0bf2c5298c761a4 to your computer and use it in GitHub Desktop.
Greasemonkey: Easy fill-in preferences in HotCrp
// ==UserScript==
// @name Input preferences in HotCrp with one keypress
// @namespace myhotcrp
// @version 1.1
// @description Link the key presses 1,2,3,0,9 to the respective preferences. 9 is -1.
// @match https://*.hotcrp.com/*
// @author Maximilan Noppel
// @grant none
// ==/UserScript==
(function() {
'use strict';
const keyMap = {
'1': '1',
'2': '2',
'3': '3',
'0': '0',
'9': '-1'
};
// Helper to simulate events
function simulateKeyEvents(element, char) {
// Keydown
element.dispatchEvent(new KeyboardEvent('keydown', {
key: char,
code: 'Digit' + char,
keyCode: char.charCodeAt(0),
which: char.charCodeAt(0),
bubbles: true,
cancelable: true
}));
// Keypress
element.dispatchEvent(new KeyboardEvent('keypress', {
key: char,
code: 'Digit' + char,
keyCode: char.charCodeAt(0),
which: char.charCodeAt(0),
bubbles: true,
cancelable: true
}));
// Input event (to trigger any input listeners)
element.dispatchEvent(new InputEvent('input', {
bubbles: true,
cancelable: true,
data: char,
inputType: 'insertText'
}));
// Keyup
element.dispatchEvent(new KeyboardEvent('keyup', {
key: char,
code: 'Digit' + char,
keyCode: char.charCodeAt(0),
which: char.charCodeAt(0),
bubbles: true,
cancelable: true
}));
}
// Simulate pressing Enter key on the element
function simulateEnter(element) {
['keydown','keypress','keyup'].forEach(type => {
element.dispatchEvent(new KeyboardEvent(type, {
key: 'Enter',
code: 'Enter',
keyCode: 13,
which: 13,
bubbles: true,
cancelable: true
}));
});
}
window.addEventListener('keypress', function(event) {
console.log(event.key);
// Don't interfere if typing in inputs, textareas, or contenteditable
const tag = event.target.tagName.toLowerCase();
if (tag === 'input' || tag === 'textarea' || event.target.isContentEditable) return;
const val = keyMap[event.key];
if (val === undefined) return;
const field = document.getElementById('revprefform_d');
const nextLink = document.getElementById('n-next');
if (!field) {
console.warn('Field with id "revprefform_d" not found.');
return;
}
if (!nextLink) {
console.warn('Link with id "n-next" not found.');
return;
}
event.preventDefault(); // prevent default action for these keys
// Focus field
field.focus();
// Clear field value first
field.value = '';
// If val is -1, it's two chars (minus and 1), so simulate both separately
const chars = val.split('');
chars.forEach(c => simulateKeyEvents(field, c));
// After input, set the actual value to be safe
field.value = val;
// Simulate pressing Enter to submit input
simulateEnter(field);
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment