-
Star
(152)
You must be signed in to star a gist -
Fork
(39)
You must be signed in to fork a gist
-
-
Save amunchet/4cfaf0274f3d238946f9f8f94fa9ee02 to your computer and use it in GitHub Desktop.
// ==UserScript== | |
// @name noVNC Paste for Proxmox | |
// @namespace http://tampermonkey.net/ | |
// @version 0.2a | |
// @description Pastes text into a noVNC window (for use with Proxmox specifically) | |
// @author Chester Enright | |
// @match https://* | |
// @include /^.*novnc.*/ | |
// @require http://code.jquery.com/jquery-3.3.1.min.js | |
// @grant none | |
// ==/UserScript== | |
const delay = 1 | |
;(function () { | |
'use strict' | |
window.sendString = function(text) { | |
var el = document.getElementById("canvas-id") | |
text.split("").forEach(x=>{ | |
setTimeout(()=>{ | |
var needs_shift = x.match(/[A-Z!@#$%^&*()_+{}:\"<>?~|]/) | |
let evt | |
if (needs_shift) { | |
evt = new KeyboardEvent("keydown", {keyCode: 16}) | |
el.dispatchEvent(evt) | |
evt = new KeyboardEvent("keydown", {key: x, shiftKey: true}) | |
el.dispatchEvent(evt) | |
evt = new KeyboardEvent("keyup", {keyCode: 16}) | |
el.dispatchEvent(evt) | |
}else{ | |
evt = new KeyboardEvent("keydown", {key: x}) | |
} | |
el.dispatchEvent(evt) | |
}, delay) | |
}) | |
} | |
$(document).ready(function() { | |
setTimeout(()=>{ | |
console.log("Starting up noVNC Copy/Paste (for Proxmox)") | |
$("canvas").attr("id", "canvas-id") | |
$("canvas").on("mousedown", (e)=>{ | |
if(e.button == 2){ // Right Click | |
navigator.clipboard.readText().then(text =>{ | |
window.sendString(text) | |
}) | |
} | |
}) | |
}, 1000); | |
}) | |
})() |
Hello all,
Thank you for this excellent script !
I forked your script to adapt french mac keyboard like this one :
I have to work more to be able to add all the keys but it's a good start.
Working key in french mac keyboard :
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890*=-_+&"(;/
Not working for now : :)[]{}!\'
.....
const keyMap = {
'a': { key: 'q', keyCode: 65 }, 'b': { key: 'b', keyCode: 66 }, 'c': { key: 'c', keyCode: 67 },
'd': { key: 'd', keyCode: 68 }, 'e': { key: 'e', keyCode: 69 }, 'f': { key: 'f', keyCode: 70 },
'g': { key: 'g', keyCode: 71 }, 'h': { key: 'h', keyCode: 72 }, 'i': { key: 'i', keyCode: 73 },
'j': { key: 'j', keyCode: 74 }, 'k': { key: 'k', keyCode: 75 }, 'l': { key: 'l', keyCode: 76 },
'm': { key: ':', keyCode: 191 }, 'n': { key: 'n', keyCode: 78 }, 'o': { key: 'o', keyCode: 79 },
'p': { key: 'p', keyCode: 80 }, 'q': { key: 'a', keyCode: 81 }, 'r': { key: 'r', keyCode: 82 },
's': { key: 's', keyCode: 83 }, 't': { key: 't', keyCode: 84 }, 'u': { key: 'u', keyCode: 85 },
'v': { key: 'v', keyCode: 86 }, 'w': { key: 'z', keyCode: 87 }, 'x': { key: 'x', keyCode: 88 },
'y': { key: 'y', keyCode: 89 }, 'z': { key: 'w', keyCode: 90 },
'A': { key: 'Q', keyCode: 65, shiftKey: true }, 'B': { key: 'B', keyCode: 66, shiftKey: true },
'C': { key: 'C', keyCode: 67, shiftKey: true }, 'D': { key: 'D', keyCode: 68, shiftKey: true },
'E': { key: 'E', keyCode: 69, shiftKey: true }, 'F': { key: 'F', keyCode: 70, shiftKey: true },
'G': { key: 'G', keyCode: 71, shiftKey: true }, 'H': { key: 'H', keyCode: 72, shiftKey: true },
'I': { key: 'I', keyCode: 73, shiftKey: true }, 'J': { key: 'J', keyCode: 74, shiftKey: true },
'K': { key: 'K', keyCode: 75, shiftKey: true }, 'L': { key: 'L', keyCode: 76, shiftKey: true },
'M': { key: ':', keyCode: 220, shiftKey: true }, 'N': { key: 'N', keyCode: 78, shiftKey: true },
'O': { key: 'O', keyCode: 79, shiftKey: true }, 'P': { key: 'P', keyCode: 80, shiftKey: true },
'Q': { key: 'A', keyCode: 81, shiftKey: true }, 'R': { key: 'R', keyCode: 82, shiftKey: true },
'S': { key: 'S', keyCode: 83, shiftKey: true }, 'T': { key: 'T', keyCode: 84, shiftKey: true },
'U': { key: 'U', keyCode: 85, shiftKey: true }, 'V': { key: 'V', keyCode: 86, shiftKey: true },
'W': { key: 'Z', keyCode: 87, shiftKey: true }, 'X': { key: 'X', keyCode: 88, shiftKey: true },
'Y': { key: 'Y', keyCode: 89, shiftKey: true }, 'Z': { key: 'W', keyCode: 90, shiftKey: true },
'1': { key: '&', keyCode: 49, shiftKey: true }, '2': { key: 'é', keyCode: 50, shiftKey: true },
'3': { key: '"', keyCode: 51, shiftKey: true }, '4': { key: '\'', keyCode: 52, shiftKey: true },
'5': { key: '(', keyCode: 53, shiftKey: true }, '6': { key: '§', keyCode: 54, shiftKey: true },
'7': { key: 'è', keyCode: 55, shiftKey: true }, '8': { key: '!', keyCode: 56, shiftKey: true },
'9': { key: 'ç', keyCode: 57, shiftKey: true }, '0': { key: 'à', keyCode: 48, shiftKey: true },
'=': { key: '=', keyCode: 187 }, // OK
'(': { key: '(', keyCode: 53, }, // OK
'&': { key: '&', keyCode: 49,}, // OK
';': { key: ',', keyCode: 188 }, // OK
'"': { key: '"', keyCode: 51, }, // OK
'+': { key: '+', keyCode: 187, shiftKey: true }, // OK
'_': { key: '_', keyCode: 56 }, // OK
'*': { key: '\\', keyCode: 220}, // OK
'-': { key: '^', keyCode: 219 }, // OK
'/': { key: '.', keyCode: 188, shiftKey: true }, // OK
/* '/': { key: '/', keyCode: 191 },
':': { key: '/', keyCode: 186 },
')': { key: '°', keyCode: 48 },
'[': { key: '^', keyCode: 219 },
']': { key: '$', keyCode: 221 },
'{': { key: '^', keyCode: 219 },
'}': { key: '4', keyCode: 221 },
'!': { key: '', keyCode: 56 },
'\'': { key: '4', keyCode: 52 }, */
};
For anyone interested, I removed the clipboard dependency by changing:
Thank you too @flightless22, I used your code too.
merci beaucoup <3 you're the best @pesposito
I have forked this script and edited it to work with French AZERTY Keyboards (Windows default French Keyboard)
Hope this help my fellow French users
For some reason the "|" symbol wasn't pasting properly for me, so I did this:
// ==UserScript==
// @name noVNC Paste for Proxmox
// @namespace http://tampermonkey.net/
// @version 0.2a
// @description Pastes text into a noVNC window (for use with Proxmox specifically)
// @author Chester Enright
// @match https://*
// @include /^.*novnc.*/
// @require http://code.jquery.com/jquery-3.3.1.min.js
// @grant none
// ==/UserScript==
const delay = 1
;(function () {
'use strict'
window.sendString = function(text) {
var el = document.getElementById("canvas-id")
text.split("").forEach(x=>{
setTimeout(()=>{
var needs_shift = x.match(/[A-Z!@#$%^&*()_+{}:"<>?~|]/)
let evt
if (needs_shift) {
switch (x) {
case '|':
evt = new KeyboardEvent("keydown", {which: 16, keyCode: 16, shiftKey: true, key: "Shift"})
el.dispatchEvent(evt)
evt = new KeyboardEvent("keydown", {which: 220, keyCode: 220, shiftKey: true, key: "|"})
el.dispatchEvent(evt)
evt = new KeyboardEvent("keyup", {which: 16, keyCode: 16, shiftKey: false, key: "Shift"})
el.dispatchEvent(evt)
break;
default:
evt = new KeyboardEvent("keydown", {which: 16, keyCode: 16, shiftKey: true, key: "Shift"})
el.dispatchEvent(evt)
evt = new KeyboardEvent("keydown", {shiftKey: true, key: x})
el.dispatchEvent(evt)
evt = new KeyboardEvent("keyup", {which: 16, keyCode: 16, shiftKey: false, key: "Shift"})
el.dispatchEvent(evt)
break;
}
/**/
}else{
evt = new KeyboardEvent("keydown", {key: x})
el.dispatchEvent(evt)
evt = new KeyboardEvent("keyup", {key: x})
el.dispatchEvent(evt)
}
}, delay)
})
}
$(document).ready(function() {
setTimeout(()=>{
console.log("Starting up noVNC Copy/Paste (for Proxmox)")
$("canvas").attr("id", "canvas-id")
$("canvas").on("mousedown", (e)=>{
if(e.button == 2){ // Right Click
navigator.clipboard.readText().then(text =>{
window.sendString(text)
})
}
})
}, 1000);
})
})()
I hope this would be helpful for somebody
Did some modifications (mostly with LLMs, yet tested massively and haven't found any bugs) to correctly work with new lines, symbols etc:
(function () {
'use strict';
let capsLockOn = false;
const KEY_DELAY = 50;
const SHIFT_NEEDED = /[A-Z!@#$%^&*()_+{}:"<>?~|]/;
function simulateKeyEvent(el, eventType, key, options = {}) {
const evt = new KeyboardEvent(eventType, { key, ...options });
el.dispatchEvent(evt);
}
window.sendString = function(text) {
const el = document.getElementById("novnc-canvas");
if (!el) {
console.error("Canvas element not found");
return;
}
text.split('').forEach((char, index) => {
setTimeout(() => {
if (char === '\n') {
// Simulate "Enter" key press for line breaks
simulateKeyEvent(el, "keydown", "Enter");
simulateKeyEvent(el, "keyup", "Enter");
} else {
const needsShift = SHIFT_NEEDED.test(char);
const isUpperCase = char >= 'A' && char <= 'Z';
if (needsShift) {
simulateKeyEvent(el, "keydown", "Shift", { keyCode: 16 });
}
if (isUpperCase && capsLockOn) {
simulateKeyEvent(el, "keydown", char.toLowerCase());
simulateKeyEvent(el, "keyup", char.toLowerCase());
} else {
simulateKeyEvent(el, "keydown", char);
simulateKeyEvent(el, "keyup", char);
}
if (needsShift) {
simulateKeyEvent(el, "keyup", "Shift", { keyCode: 16 });
}
if (char === "CapsLock") {
capsLockOn = !capsLockOn;
console.log("Caps Lock state changed:", capsLockOn);
}
}
}, index * KEY_DELAY);
});
};
function waitForCanvas() {
return new Promise((resolve) => {
const checkCanvas = () => {
const canvas = $("canvas");
if (canvas.length > 0) {
canvas.attr("id", "novnc-canvas");
resolve(canvas);
} else {
setTimeout(checkCanvas, 500);
}
};
checkCanvas();
});
}
async function setupNoVNCPaste() {
try {
console.log("Starting up noVNC Copy/Paste (for Proxmox) - Improved Version with Line Breaks");
const canvas = await waitForCanvas();
canvas.on("mousedown", (e) => {
if (e.button == 2) { // Right Click
navigator.clipboard.readText()
.then(text => {
window.sendString(text);
})
.catch(err => {
console.error("Failed to read clipboard:", err);
});
}
});
console.log("noVNC Copy/Paste setup completed");
} catch (error) {
console.error("Error setting up noVNC Copy/Paste:", error);
}
}
$(document).ready(setupNoVNCPaste);
})();
Forked and updated it for German Mac Keyboard.
Added Async writing to be able to paste walls of text.
Tried many mapping variants, but mapping the whole keyboard worked best.
https://gist.github.com/JonasKrausch/3c64e4ca9f4a9bdde66a91759f24e574
it worked, thank you <3
Is anyone else having a problem with carriage returns? I have a multi-line copy that is pasted into one line on Proxmox. Sometimes, the leading character of the next line is omitted, too.
@Laz2047 I would try the version above by @zakhar-kogan - it might handle carriage returns a bit better (I haven't actually tried it myself). The original version was just meant to paste in long passwords or single line items, so I didn't really consider multi-lines.
Thank you. I'll check it out.
Hi
Any updates on this?
I'd really love such a feature, as with the current code I can barely even use it.
Edit:

Swiss Keyboard Layout is even better: