]> git.proxmox.com Git - mirror_xterm.js.git/blob - src/handlers/Clipboard.ts
Properly prepare text for clipboard for context menu
[mirror_xterm.js.git] / src / handlers / Clipboard.ts
1 /**
2 * Clipboard handler module: exports methods for handling all clipboard-related events in the
3 * terminal.
4 * @module xterm/handlers/Clipboard
5 * @license MIT
6 */
7
8 import { ITerminal, ISelectionManager } from '../Interfaces';
9
10 interface IWindow extends Window {
11 clipboardData?: {
12 getData(format: string): string;
13 setData(format: string, data: string);
14 };
15 }
16
17 declare var window: IWindow;
18
19 /**
20 * Prepares text copied from terminal selection, to be saved in the clipboard by:
21 * 1. stripping all trailing white spaces
22 * 2. converting all non-breaking spaces to regular spaces
23 * @param {string} text The copied text that needs processing for storing in clipboard
24 * @returns {string}
25 */
26 export function prepareTextForClipboard(text: string): string {
27 let space = String.fromCharCode(32),
28 nonBreakingSpace = String.fromCharCode(160),
29 allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'),
30 processedText = text.split('\n').map(function (line) {
31 // Strip all trailing white spaces and convert all non-breaking spaces
32 // to regular spaces.
33 let processedLine = line.replace(/\s+$/g, '').replace(allNonBreakingSpaces, space);
34
35 return processedLine;
36 }).join('\n');
37
38 return processedText;
39 }
40
41 /**
42 * Prepares text to be pasted into the terminal by normalizing the line endings
43 * @param text The pasted text that needs processing before inserting into the terminal
44 */
45 export function prepareTextForTerminal(text: string, isMSWindows: boolean): string {
46 if (isMSWindows) {
47 return text.replace(/\r?\n/g, '\n');
48 }
49 return text;
50 }
51
52 /**
53 * Binds copy functionality to the given terminal.
54 * @param {ClipboardEvent} ev The original copy event to be handled
55 */
56 export function copyHandler(ev: ClipboardEvent, term: ITerminal, selectionManager: ISelectionManager) {
57 // We cast `window` to `any` type, because TypeScript has not declared the `clipboardData`
58 // property that we use below for Internet Explorer.
59 let text = prepareTextForClipboard(selectionManager.selectionText);
60
61 if (term.browser.isMSIE) {
62 window.clipboardData.setData('Text', text);
63 } else {
64 ev.clipboardData.setData('text/plain', text);
65 }
66
67 ev.preventDefault(); // Prevent or the original text will be copied.
68 }
69
70 /**
71 * Redirect the clipboard's data to the terminal's input handler.
72 * @param {ClipboardEvent} ev The original paste event to be handled
73 * @param {Terminal} term The terminal on which to apply the handled paste event
74 */
75 export function pasteHandler(ev: ClipboardEvent, term: ITerminal) {
76 ev.stopPropagation();
77
78 let text: string;
79
80 let dispatchPaste = function(text) {
81 text = prepareTextForTerminal(text, term.browser.isMSWindows);
82 term.handler(text);
83 term.textarea.value = '';
84 return term.cancel(ev);
85 };
86
87 if (term.browser.isMSIE) {
88 if (window.clipboardData) {
89 text = window.clipboardData.getData('Text');
90 dispatchPaste(text);
91 }
92 } else {
93 if (ev.clipboardData) {
94 text = ev.clipboardData.getData('text/plain');
95 dispatchPaste(text);
96 }
97 }
98 }
99
100 /**
101 * Bind to right-click event and allow right-click copy and paste.
102 * @param ev The original right click event to be handled
103 * @param term The terminal on which to apply the handled paste event
104 * @param selectionManager The terminal's selection manager.
105 */
106 export function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement, selectionManager: ISelectionManager) {
107 // Bring textarea at the cursor position
108 textarea.style.position = 'fixed';
109 textarea.style.width = '20px';
110 textarea.style.height = '20px';
111 textarea.style.left = (ev.clientX - 10) + 'px';
112 textarea.style.top = (ev.clientY - 10) + 'px';
113 textarea.style.zIndex = '1000';
114
115 // Get textarea ready to copy from the context menu
116 textarea.value = prepareTextForClipboard(selectionManager.selectionText);
117 textarea.focus();
118 textarea.select();
119
120 // Reset the terminal textarea's styling
121 setTimeout(function () {
122 textarea.style.position = null;
123 textarea.style.width = null;
124 textarea.style.height = null;
125 textarea.style.left = null;
126 textarea.style.top = null;
127 textarea.style.zIndex = null;
128 }, 4);
129 }