Files
webkeyboard/html/index.html
T
2025-05-28 18:16:00 -04:00

394 lines
8.9 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>Web Keyboard</title>
<style>
div.container > div {
display: inline-block;
}
div#indicators {
text-align: center;
vertical-align: top;
font-size: 1.2em;
}
div#indicators .on {
background-color: #40ff40;
}
div#indicators .off {
background-color: #dddddd;
}
div#keyboard {
background-color: #000000;
}
div.key {
text-align:center;
vertical-align: top;
display: inline-block;
background-color: #dddddd;
margin: 1px;
width: 3em;
height: 3.5em;
font-size: 0.8em;
}
div.pressed {
background-color: #ff4040;
}
div.blank {
opacity: 0;
}
div.info div {
font-size: 1.5em;
display: inline-block;
margin: 1em;
}
div#macros div {
width: 9em;
display: inline-block;
background-color: #dddddd;
margin: 1em;
text-align: center;
}
div#macros .mousedown{
background-color: #4040ff;
}
div#status_frames {
visibility: hidden;
}
div.menu {
display: inline-block;
padding: 1em;
background-color: #dddddd;
}
div.menu a {
text-decoration: none;
color: #0000ff;
}
div.menu a:hover {
text-decoration: underline;
}
</style>
<script>
var keys = [];
var fetchqueue = [];
var curLed = 0;
const indicator_list = [
{id: "num", label: "NumLock"},
{id: "caps", label: "CapsLock"},
{id: "scroll", label: "ScrollLock"}
];
const macro_list = [
{id: "power", label: "Power", keys: ["WakeUp"]},
{id: "reset", label: "CTRL+ALT+DEL", keys: ["ControlLeft","AltLeft","Delete"]},
{id: "close", label: "ALT+F4", keys: ["AltLeft", "F4"]},
{id: "cycle", label: "ALT+Tab", keys: ["AltLeft", "Tab"]}
];
const key_list = [
[
{id: "Escape", label: "ESC", width: 2},
{id: "F1", label: "F1"},
{id: "F2", label: "F2"},
{id: "F3", label: "F3"},
{id: "F4", label: "F4"},
{id: "F5", label: "F5"},
{id: "F6", label: "F6"},
{id: "F7", label: "F7"},
{id: "F8", label: "F8"},
{id: "F9", label: "F9"},
{id: "F10", label: "F10"},
{id: "F11", label: "F11"},
{id: "F12", label: "F12"},
{id: "", label: ""},
{id: "PrintScreen", label: "Print<br>Screen"},
{id: "ScrollLock", label: "Scroll<br>Lock"},
{id: "Pause", label: "Pause"}
],
[
{id: "Backquote", label: "~<br>`"},
{id: "Digit1", label: "!<br>1"},
{id: "Digit2", label: "@<br>2"},
{id: "Digit3", label: "#<br>3"},
{id: "Digit4", label: "$<br>4"},
{id: "Digit5", label: "%<br>5"},
{id: "Digit6", label: "^<br>6"},
{id: "Digit7", label: "&<br>7"},
{id: "Digit8", label: "*<br>8"},
{id: "Digit9", label: "(<br>9"},
{id: "Digit0", label: ")<br>0"},
{id: "Minus", label: "_<br>-"},
{id: "Equal", label: "+<br>="},
{id: "Backspace", label: "Backspace", width: 2},
{id: "Insert", label: "Insert" },
{id: "Home", label: "Home" },
{id: "PageUp", label: "Page<br>Up"},
{id: "NumLock", label: "Num"},
{id: "NumpadDivide", label: "/"},
{id: "NumpadMultiply", label: "*"},
{id: "NumpadSubtract", label: "-"}
],
[
{id: "Tab", label: "Tab", width: 1.5},
{id: "KeyQ", label: "Q"},
{id: "KeyW", label: "W"},
{id: "KeyE", label: "E"},
{id: "KeyR", label: "R"},
{id: "KeyT", label: "T"},
{id: "KeyY", label: "Y"},
{id: "KeyU", label: "U"},
{id: "KeyI", label: "I"},
{id: "KeyO", label: "O"},
{id: "KeyP", label: "P"},
{id: "BracketLeft", label: "{<br>["},
{id: "BracketRight", label: "}<br>]"},
{id: "Backslash", label: "|<br>\\", width: 1.5},
{id: "Delete", label: "Delete"},
{id: "End", label: "End"},
{id: "PageDown", label: "Page<br>Down"},
{id: "Numpad7", label: "Home<br>7"},
{id: "Numpad8", label: "Up<br>8"},
{id: "Numpad9", label: "PgUp<br>9"},
{id: "NumpadAdd", label: "+", height: 2}
],
[
{id: "CapsLock", label: "Caps<br>Lock", width: 2},
{id: "KeyA", label: "A"},
{id: "KeyS", label: "S"},
{id: "KeyD", label: "D"},
{id: "KeyF", label: "F"},
{id: "KeyG", label: "G"},
{id: "KeyH", label: "H"},
{id: "KeyJ", label: "J"},
{id: "KeyK", label: "K"},
{id: "KeyL", label: "L"},
{id: "Semicolon", label: ":<br>;"},
{id: "Quote", label: "\"<br>\'"},
{id: "Enter", label: "Enter", width: 2},
{id: "", label: "", width: 3.17},
{id: "Numpad4", label: "Left<br>4"},
{id: "Numpad5", label: "5"},
{id: "Numpad6", label: "Right<br>6"}
],
[
{id: "ShiftLeft", label: "Shift", width: 2.5},
{id: "KeyZ", label: "Z"},
{id: "KeyX", label: "X"},
{id: "KeyC", label: "C"},
{id: "KeyV", label: "V"},
{id: "KeyB", label: "B"},
{id: "KeyN", label: "N"},
{id: "KeyM", label: "M"},
{id: "Comma", label: "\<<br>,"},
{id: "Period", label: "\><br>."},
{id: "Slash", label: "?<br>/"},
{id: "ShiftRight", label: "Shift", width: 2.6},
{id: "", label: ""},
{id: "ArrowUp", label: "Up"},
{id: "", label: ""},
{id: "Numpad1", label: "End<br>1"},
{id: "Numpad2", label: "Down<br>2"},
{id: "Numpad3", label: "PgDn<br>3"},
{id: "NumpadEnter", label: "Enter", height: 2}
],
[
{id: "ControlLeft", label: "Control", width: 2},
{id: "MetaLeft", label: "Meta"},
{id: "AltLeft", label: "Alt", width: 1.5},
{id: "Space", label: "Space", width: 6.4},
{id: "AltRight", label: "Alt", width: 1.5},
{id: "MetaRight", label: "Meta"},
{id: "ControlRight", label: "Control", width: 2},
{id: "ArrowLeft", label: "Left"},
{id: "ArrowDown", label: "Down"},
{id: "ArrowRight", label: "Right"},
{id: "Numpad0", label: "Ins<br>0", width: 2},
{id: "NumpadDecimal", label: "Del<br>."}
],
];
window.setInterval("refreshIndicators();",2000);
window.addEventListener("keydown", onKeyDown, true);
window.addEventListener("keyup", onKeyUp, true);
window.onload = (event) => {
createMacros("macros");
createKeys("keyboard");
}
function onKeyDown(event) {
if (event.defaultPrevented) {
return; // Do nothing if the event was already processed
}
pressKey(event.code);
// Cancel the default action to avoid it being handled twice
event.preventDefault();
}
function pressKey(code) {
if (keys.includes(code)) { return; }
keys.push(code);
sendKeys(keys);
}
function onKeyUp(event) {
if (event.defaultPrevented) {
return; // Do nothing if the event was already processed
}
releaseKey(event.code);
// Cancel the default action to avoid it being handled twice
event.preventDefault();
}
function releaseKey(code) {
if (keys.includes(code)) {
keys.splice(keys.indexOf(code),1);
}
sendKeys(keys);
}
function sendKeys(curKeys) {
const url="sendkeys.cgi?keys=".concat(curKeys);
fetchqueue.push(url);
console.log(fetchqueue);
document.getElementById("downKeys")
.innerHTML = curKeys;
prev_keys = document.getElementsByClassName("pressed");
for (let key of curKeys) {
keyDiv = document.getElementById(key);
keyDiv.classList.add("pressed");
}
for (let key of prev_keys) {
if (!curKeys.includes(key.id)) {
key.classList.remove("pressed");
}
}
if (fetchqueue.length == 1) {
runQueue();
}
}
async function runQueue() {
const url = fetchqueue[0];
await fetch(url);
fetchqueue.shift();
if (fetchqueue.length > 0) {
runQueue();
}
}
function updateIndicators() {
let indicatorFrame = document.getElementById("indicatorFrame");
let indicatorDiv = document.getElementById("indicators");
indicatorDiv.innerHTML = indicatorFrame.contentDocument.body.innerHTML;
}
function refreshIndicators() {
let indicatorFrame = document.getElementById("indicatorFrame");
indicatorFrame.contentWindow.location.reload(true);
}
function createKeys(keyboard_id) {
let keyboardDiv = document.getElementById(keyboard_id);
for (let row of key_list) {
let newRow = document.createElement("div");
keyboardDiv.appendChild(newRow);
for (let key of row) {
let newDiv = document.createElement("div");
if (key.id) {
newDiv.id = key.id;
newDiv.innerHTML = key.label;
newDiv.className = "key";
newDiv.addEventListener("mousedown", function () {
pressKey(key.id); });
newDiv.addEventListener("mouseup", function () {
releaseKey(key.id); });
} else {
newDiv.className = "key blank";
}
newRow.appendChild(newDiv);
if (key.width) {
newDiv.style = "width:" + (key.width*newDiv.clientWidth ) + "px;";
}
if (key.height) {
newDiv.style = "height:" + (key.height*newDiv.clientHeight ) + "px; float: right;";
}
}
}
}
function createMacros(macro_id) {
let macroDiv = document.getElementById(macro_id);
for (let macro of macro_list) {
let newDiv = document.createElement("div");
newDiv.id = macro.id;
newDiv.textContent = macro.label;
newDiv.addEventListener("mousedown", function () {
sendKeys(macro.keys); });
newDiv.addEventListener("mouseup", function () {
sendKeys([]); });
macroDiv.appendChild(newDiv);
}
}
</script>
</head>
<body>
<div class="container">
<div id="keyboard"></div>
<div id="indicators"></div>
</div>
<div id="macros"></div>
<div class="info">
<div>Currently pressed keys:</div>
<div id="downKeys"></div>
</div>
<div>
<div class="menu">
<a href="wifi.shtml">Configure Wi-Fi</a>
</div>
<div class="menu">
<a href="reboot.cgi">Reboot</a>
</div>
</div>
<div id="status_frames">
<iframe id="indicatorFrame" src="indicators.shtml"
onload="updateIndicators();"></iframe>
</div>
</body>
</html>