Created
August 28, 2025 18:13
-
-
Save noppelmax/32d01c8d160f19b3d0bf2c5298c761a4 to your computer and use it in GitHub Desktop.
Greasemonkey: Easy fill-in preferences in HotCrp
This file contains hidden or 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
// ==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