Skip to content

Instantly share code, notes, and snippets.

@amunchet
Last active November 27, 2025 08:00
Show Gist options
  • Select an option

  • Save amunchet/4cfaf0274f3d238946f9f8f94fa9ee02 to your computer and use it in GitHub Desktop.

Select an option

Save amunchet/4cfaf0274f3d238946f9f8f94fa9ee02 to your computer and use it in GitHub Desktop.
Copy/Paste for noVNC Proxmox
// ==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);
})
})()
@bakatz
Copy link

bakatz commented Oct 17, 2025

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)
        })

    }

@cjpjxjx
Copy link

cjpjxjx commented Nov 27, 2025

感谢作者的代码!

受此启发,我在 Claude 的帮助下基于原代码开发了一个增强版的 PVE 粘贴输入工具。 主要改进包括:

  1. 交互优化:增加了图形化界面(模态框),支持实时字符统计。
  2. 核心机制:重写了键盘事件模拟逻辑,更好地处理 Shift 组合键和特殊符号。
  3. 部署方式:除了油猴脚本,还支持 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:

  1. Better UI: Added a graphical interface (modal dialog) with real-time character counting.
  2. Core Mechanism: Rewrote the keyboard event simulation logic for better handling of Shift keys and special symbols.
  3. Deployment: Supports both Tampermonkey script and Nginx injection (suitable for reverse proxy setups).

⚠️ Note: The project documentation and interface are currently in Chinese only.

Repo: https://github.com/cjpjxjx/pve-paste-input

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment