Skip to content

Instantly share code, notes, and snippets.

@JonasKrausch
Forked from amunchet/noVNCCopyPasteProxmox.user.js
Last active October 30, 2024 17:12
Show Gist options
  • Save JonasKrausch/3c64e4ca9f4a9bdde66a91759f24e574 to your computer and use it in GitHub Desktop.
Save JonasKrausch/3c64e4ca9f4a9bdde66a91759f24e574 to your computer and use it in GitHub Desktop.
Paste Text into noVNC Proxmox (MacOS DE Keyboard)
// ==UserScript==
// @name noVNC Paste for Proxmox (German Mac Keyboard)
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Pastes text into a noVNC window (for use with Proxmox specifically) using German Mac keyboard layout
// @author Jonas Krausch
// @match https://*
// @require http://code.jquery.com/jquery-3.3.1.min.js
// @include /^.*novnc.*/
// @icon https://www.google.com/s2/favicons?sz=64&domain=proxmox.com
// @grant none
// ==/UserScript==
const delay = 50;
(async function () {
'use strict';
// Function to handle each character with async/await
async function pasteCharacter(char) {
return new Promise(resolve => {
setTimeout(() => {
if (char === "\n") {
char = "Enter";
}
const el = document.getElementById("canvas-id");
let evt;
const specialChar = germanKeyboardMap[char];
if (specialChar) {
// Handle Alt key if required
if (specialChar.altKey) {
evt = new KeyboardEvent("keydown", { key: 'Alt', code: 'AltLeft', which: 18, altKey: true });
el.dispatchEvent(evt);
}
// Handle Shift key if required
if (specialChar.shiftKey) {
evt = new KeyboardEvent("keydown", { key: 'Shift', code: 'ShiftLeft', which: 16, shiftKey: true });
el.dispatchEvent(evt);
}
// Key down and up for actual character
evt = new KeyboardEvent("keydown", { key: specialChar.key, code: specialChar.code, which: specialChar.which });
el.dispatchEvent(evt);
evt = new KeyboardEvent("keyup", { key: specialChar.key, code: specialChar.code, which: specialChar.which });
el.dispatchEvent(evt);
// Release Shift if used
if (specialChar.shiftKey) {
evt = new KeyboardEvent("keyup", { key: 'Shift', code: 'ShiftLeft', which: 16, shiftKey: true });
el.dispatchEvent(evt);
}
// Release Alt if used
if (specialChar.altKey) {
evt = new KeyboardEvent("keyup", { key: 'Alt', code: 'AltLeft', which: 18, altKey: true });
el.dispatchEvent(evt);
}
} else {
console.warn(`Character ->${char}<- not mapped`);
}
resolve(); // Resolve the promise after handling character
}, delay);
});
}
async function sendString(text) {
for (const char of text.split("")) {
await pasteCharacter(char); // Wait for each character to be processed
}
}
$(document).ready(function () {
setTimeout(() => {
console.log("Starting up noVNC Copy/Paste (for Proxmox, German Mac Keyboard)");
$("canvas").attr("id", "canvas-id");
$("canvas").on("mousedown", (e) => {
if (e.button == 2) { // Right Click
console.log("Right-click detected. Attempting to paste clipboard text.");
navigator.clipboard.readText().then(text => {
console.log(`Clipboard text: ${text}`);
sendString(text); // Use the async function to paste text
}).catch(err => {
console.error("Failed to read clipboard:", err);
});
}
});
}, 1000);
});
// Character map for German Mac Keyboard
const germanKeyboardMap = {
'a': { key: 'a', code: 'KeyA', which: 65 }, 'b': { key: 'b', code: 'KeyB', which: 66 },
'c': { key: 'c', code: 'KeyC', which: 67 }, 'd': { key: 'd', code: 'KeyD', which: 68 },
'e': { key: 'e', code: 'KeyE', which: 69 }, 'f': { key: 'f', code: 'KeyF', which: 70 },
'g': { key: 'g', code: 'KeyG', which: 71 }, 'h': { key: 'h', code: 'KeyH', which: 72 },
'i': { key: 'i', code: 'KeyI', which: 73 }, 'j': { key: 'j', code: 'KeyJ', which: 74 },
'k': { key: 'k', code: 'KeyK', which: 75 }, 'l': { key: 'l', code: 'KeyL', which: 76 },
'm': { key: 'm', code: 'KeyM', which: 77 }, 'n': { key: 'n', code: 'KeyN', which: 78 },
'o': { key: 'o', code: 'KeyO', which: 79 }, 'p': { key: 'p', code: 'KeyP', which: 80 },
'q': { key: 'q', code: 'KeyQ', which: 81 }, 'r': { key: 'r', code: 'KeyR', which: 82 },
's': { key: 's', code: 'KeyS', which: 83 }, 't': { key: 't', code: 'KeyT', which: 84 },
'u': { key: 'u', code: 'KeyU', which: 85 }, 'v': { key: 'v', code: 'KeyV', which: 86 },
'w': { key: 'w', code: 'KeyW', which: 87 }, 'x': { key: 'x', code: 'KeyX', which: 88 },
'y': { key: 'y', code: 'KeyY', which: 89 }, 'z': { key: 'z', code: 'KeyZ', which: 90 },
'A': { key: 'A', code: 'KeyA', which: 65, shiftKey: true }, 'B': { key: 'B', code: 'KeyB', which: 66, shiftKey: true },
'C': { key: 'C', code: 'KeyC', which: 67, shiftKey: true }, 'D': { key: 'D', code: 'KeyD', which: 68, shiftKey: true },
'E': { key: 'E', code: 'KeyE', which: 69, shiftKey: true }, 'F': { key: 'F', code: 'KeyF', which: 70, shiftKey: true },
'G': { key: 'G', code: 'KeyG', which: 71, shiftKey: true }, 'H': { key: 'H', code: 'KeyH', which: 72, shiftKey: true },
'I': { key: 'I', code: 'KeyI', which: 73, shiftKey: true }, 'J': { key: 'J', code: 'KeyJ', which: 74, shiftKey: true },
'K': { key: 'K', code: 'KeyK', which: 75, shiftKey: true }, 'L': { key: 'L', code: 'KeyL', which: 76, shiftKey: true },
'M': { key: 'M', code: 'KeyM', which: 77, shiftKey: true }, 'N': { key: 'N', code: 'KeyN', which: 78, shiftKey: true },
'O': { key: 'O', code: 'KeyO', which: 79, shiftKey: true }, 'P': { key: 'P', code: 'KeyP', which: 80, shiftKey: true },
'Q': { key: 'Q', code: 'KeyQ', which: 81, shiftKey: true }, 'R': { key: 'R', code: 'KeyR', which: 82, shiftKey: true },
'S': { key: 'S', code: 'KeyS', which: 83, shiftKey: true }, 'T': { key: 'T', code: 'KeyT', which: 84, shiftKey: true },
'U': { key: 'U', code: 'KeyU', which: 85, shiftKey: true }, 'V': { key: 'V', code: 'KeyV', which: 86, shiftKey: true },
'W': { key: 'W', code: 'KeyW', which: 87, shiftKey: true }, 'X': { key: 'X', code: 'KeyX', which: 88, shiftKey: true },
'Y': { key: 'Y', code: 'KeyY', which: 89, shiftKey: true }, 'Z': { key: 'Z', code: 'KeyZ', which: 90, shiftKey: true },
'0': { key: '0', code: 'Digit0', which: 48 }, '1': { key: '1', code: 'Digit1', which: 49 },
'2': { key: '2', code: 'Digit2', which: 50 }, '3': { key: '3', code: 'Digit3', which: 51 },
'4': { key: '4', code: 'Digit4', which: 52 }, '5': { key: '5', code: 'Digit5', which: 53 },
'6': { key: '6', code: 'Digit6', which: 54 }, '7': { key: '7', code: 'Digit7', which: 55 },
'8': { key: '8', code: 'Digit8', which: 56 }, '9': { key: '9', code: 'Digit9', which: 57 },
'!': { key: '!', code: 'Digit1', which: 49, shiftKey: true }, '"': { key: '"', code: 'Digit2', which: 50, shiftKey: true },
'§': { key: '§', code: 'Digit3', which: 51, shiftKey: true }, '$': { key: '$', code: 'Digit4', which: 52, shiftKey: true },
'%': { key: '%', code: 'Digit5', which: 53, shiftKey: true }, '&': { key: '&', code: 'Digit6', which: 54, shiftKey: true },
'/': { key: '/', code: 'Digit7', which: 55, shiftKey: true }, '(': { key: '(', code: 'Digit8', which: 56, shiftKey: true },
')': { key: ')', code: 'Digit9', which: 57, shiftKey: true }, '=': { key: '=', code: 'Digit0', which: 48, shiftKey: true },
'?': { key: '?', code: 'Minus', which: 191, shiftKey: true },
'ä': { key: 'ä', code: 'Quote', which: 222 }, 'Ä': { key: 'Ä', code: 'Quote', which: 222, shiftKey: true },
'ö': { key: 'ö', code: 'Semicolon', which: 186 }, 'Ö': { key: 'Ö', code: 'Semicolon', which: 186, shiftKey: true },
'ü': { key: 'ü', code: 'BracketLeft', which: 219 }, 'Ü': { key: 'Ü', code: 'BracketLeft', which: 219, shiftKey: true },
'ß': { key: 'ß', code: 'Minus', which: 189 },
',': { key: ',', code: 'Comma', which: 188 }, ';': { key: ';', code: 'Comma', which: 186, shiftKey: true },
'.': { key: '.', code: 'Period', which: 190 }, ':': { key: ':', code: 'Period', which: 190, shiftKey: true },
'-': { key: '-', code: 'Slash', which: 189 }, '_': { key: '_', code: 'Slash', which: 189, shiftKey: true },
'+': { key: '+', code: 'BracketRight', which: 187 }, '*' : { key: '*', code: 'BracketRight', which: 187, shiftKey: true },
'#': { key: '#', code: 'Backslash', which: 220 }, '\'': { key: '\'', code: 'Backslash', which: 222, shiftKey: true },
'´': { key: '´', code: 'Equal', which: 187 }, '`': { key: '`', code: 'Equal', which: 187, shiftKey: true },
'@': { key: '@', code: 'KeyL', which: 76, altKey: true }, '€': { key: '€', code: 'KeyE', which: 69, shiftKey: true, altKey: true },
'~': { key: '~', code: 'KeyN', which: 78, shiftKey: true, altKey: true }, '\\': { key: '\\', code: 'Minux', which: 55, altKey: true },
'^': { key: '^', code: 'IntlBackslash', which: 192 }, '°': { key: '°', code: 'IntlBackslash', which: 192, shiftKey: true },
'<': { key: '<', code: 'Backquote', which: 188 }, '>': { key: '>', code: 'Backquote', which: 190, shiftKey: true },
'{': { key: '{', code: 'Digit8', which: 56, altKey: true }, '}': { key: '}', code: 'Digit9', which: 57, altKey: true },
'|' : { key: '|', code: 'Digit7', which: 55, altKey: true },
'[': { key: '[', code: 'Digit5', which: 53, altKey: true }, ']': { key: ']', code: 'Digit6', which: 54, altKey: true },
' ': { key: ' ', code: 'Space', which: 32 },
'Enter': { key: 'Enter', code: 'Enter', which: 13 }
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment