-
Star
(191)
You must be signed in to star a gist -
Fork
(47)
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); | |
| }) | |
| })() |
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.
@amunchet Just came here to say I love you for making this script. It's such a massive quality of life improvement!
used this in console to paste ssh key using right mouse click.
(function () {
const delay = 50; // Slow down typing to avoid missed characters
function loadjQuery(callback) {
if (typeof window.jQuery !== 'undefined') {
callback(window.jQuery);
} else {
const script = document.createElement('script');
script.src = "https://code.jquery.com/jquery-3.3.1.min.js";
script.onload = () => callback(window.jQuery);
document.head.appendChild(script);
}
}
function sendChar(el, char) {
if (char === '\n' || char === '\r') {
// Handle Enter
el.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter", code: "Enter", which: 13, keyCode: 13 }));
el.dispatchEvent(new KeyboardEvent("keyup", { key: "Enter", code: "Enter", which: 13, keyCode: 13 }));
return;
}
const needsShift = char.match(/[A-Z!@#$%^&*()_+{}:"<>?~|]/);
if (needsShift) {
el.dispatchEvent(new KeyboardEvent("keydown", { key: "Shift", code: "ShiftLeft", shiftKey: true }));
}
el.dispatchEvent(new KeyboardEvent("keydown", { key: char, code: undefined, shiftKey: !!needsShift }));
el.dispatchEvent(new KeyboardEvent("keyup", { key: char, code: undefined, shiftKey: !!needsShift }));
if (needsShift) {
el.dispatchEvent(new KeyboardEvent("keyup", { key: "Shift", code: "ShiftLeft", shiftKey: false }));
}
}
function sendString(text) {
const el = document.getElementById("canvas-id");
if (!el) {
console.warn("Canvas not found");
return;
}
text.split("").forEach((char, i) => {
setTimeout(() => sendChar(el, char), delay * i);
});
}
loadjQuery(($) => {
setTimeout(() => {
console.log("noVNC Paste active");
$("canvas").attr("id", "canvas-id");
$("canvas").on("mousedown", (e) => {
if (e.button === 2) { // Right-click
navigator.clipboard.readText().then(text => {
sendString(text);
});
}
});
}, 1000);
});
})();
The canvas finding logic is broken, use this for sendString() if you're using novnc and it'll work:
function sendString(text) {
var el = document.querySelector("#noVNC_container canvas")
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)
}, 100)
})
}
感谢作者的代码!
受此启发,我在 Claude 的帮助下基于原代码开发了一个增强版的 PVE 粘贴输入工具。 主要改进包括:
- 交互优化:增加了图形化界面(模态框),支持实时字符统计。
- 核心机制:重写了键盘事件模拟逻辑,更好地处理 Shift 组合键和特殊符号。
- 部署方式:除了油猴脚本,还支持 Nginx 注入方式,适合反向代理场景。
项目地址:https://github.com/cjpjxjx/pve-paste-input
Thanks for the code!
Inspired by this, I developed an enhanced PVE paste input tool with the help of Claude. Key improvements include:
- Better UI: Added a graphical interface (modal dialog) with real-time character counting.
- Core Mechanism: Rewrote the keyboard event simulation logic for better handling of Shift keys and special symbols.
- Deployment: Supports both Tampermonkey script and Nginx injection (suitable for reverse proxy setups).
it worked, thank you <3