85 lines
2.7 KiB
JavaScript
85 lines
2.7 KiB
JavaScript
export default class Clipboard {
|
|
/**
|
|
* @type {string}
|
|
*/
|
|
_remoteClipboard
|
|
constructor(target) {
|
|
this._target = target;
|
|
|
|
this._eventHandlers = {
|
|
'copy': this._handleCopy.bind(this),
|
|
'paste': this._handlePaste.bind(this)
|
|
};
|
|
|
|
// ===== EVENT HANDLERS =====
|
|
|
|
this.onpaste = () => {};
|
|
}
|
|
|
|
// ===== PRIVATE METHODS =====
|
|
|
|
_handleCopy(e) {
|
|
this._remoteClipboard = e.clipboardData.getData('text/plain');
|
|
this._copy(this._remoteClipboard)
|
|
}
|
|
/**
|
|
* Has a better browser support compared with navigator.clipboard.writeText.
|
|
* Also, no permission required.
|
|
*/
|
|
_copy(text) {
|
|
const textarea = document.createElement('textarea');
|
|
textarea.innerHTML = text;
|
|
document.body.appendChild(textarea);
|
|
textarea.select();
|
|
const result = document.execCommand('copy');
|
|
document.body.removeChild(textarea);
|
|
}
|
|
/**
|
|
* @param {ClipboardEvent} e
|
|
*/
|
|
_handlePaste(e) {
|
|
if(!this._isVncEvent()){
|
|
return;
|
|
}
|
|
if(e.clipboardData){
|
|
const localClipboard = e.clipboardData.getData('text/plain');
|
|
if(localClipboard === this._remoteClipboard){
|
|
this._pasteVncServerInternalClipboard();
|
|
return;
|
|
}
|
|
this.onpaste(localClipboard);
|
|
}
|
|
}
|
|
/**
|
|
* The vnc server clipboard can be non ascii text and server might only support ascii code.
|
|
* In that case, localClipboard received from the vnc server is garbled.
|
|
* For example, if you copied chinese text "你好" in the vnc server the local clipboard will be changed to "??".
|
|
* If you press Ctrl+V, the vnc server should paste "你好" instead of "??".
|
|
* So, we shouldn't send the local clipboard to the vnc server because the local clipboard is garbled in this case.
|
|
*/
|
|
_pasteVncServerInternalClipboard(){
|
|
this.onpaste("", false);
|
|
}
|
|
_isVncEvent(){
|
|
const isTargetFocused = document.activeElement === this._target;
|
|
return isTargetFocused;
|
|
}
|
|
|
|
// ===== PUBLIC METHODS =====
|
|
|
|
grab() {
|
|
if (!Clipboard.isSupported) return;
|
|
this._target.addEventListener('copy', this._eventHandlers.copy);
|
|
// _target can not listen the paste event.
|
|
document.body.addEventListener('paste', this._eventHandlers.paste);
|
|
}
|
|
|
|
ungrab() {
|
|
if (!Clipboard.isSupported) return;
|
|
this._target.removeEventListener('copy', this._eventHandlers.copy);
|
|
document.body.removeEventListener('paste', this._eventHandlers.paste);
|
|
}
|
|
}
|
|
|
|
Clipboard.isSupported = (navigator && navigator.clipboard) ? true : false;
|