]> git.proxmox.com Git - mirror_xterm.js.git/blob - src/handlers/Clipboard.ts
😱 Fix wrong event type and remove useless interface
[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 } 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 * Binds copy functionality to the given terminal.
43 * @param {ClipboardEvent} ev The original copy event to be handled
44 */
45 export function copyHandler(ev: ClipboardEvent, term: ITerminal) {
46 // We cast `window` to `any` type, because TypeScript has not declared the `clipboardData`
47 // property that we use below for Internet Explorer.
48 let copiedText = window.getSelection().toString(),
49 text = prepareTextForClipboard(copiedText);
50
51 if (term.browser.isMSIE) {
52 window.clipboardData.setData('Text', text);
53 } else {
54 ev.clipboardData.setData('text/plain', text);
55 }
56
57 ev.preventDefault(); // Prevent or the original text will be copied.
58 }
59
60 /**
61 * Redirect the clipboard's data to the terminal's input handler.
62 * @param {ClipboardEvent} ev The original paste event to be handled
63 * @param {Terminal} term The terminal on which to apply the handled paste event
64 */
65 export function pasteHandler(ev: ClipboardEvent, term: ITerminal) {
66 ev.stopPropagation();
67
68 let text: string;
69
70 let dispatchPaste = function(text) {
71 term.handler(text);
72 term.textarea.value = '';
73 return term.cancel(ev);
74 };
75
76 if (term.browser.isMSIE) {
77 if (window.clipboardData) {
78 text = window.clipboardData.getData('Text');
79 dispatchPaste(text);
80 }
81 } else {
82 if (ev.clipboardData) {
83 text = ev.clipboardData.getData('text/plain');
84 dispatchPaste(text);
85 }
86 }
87 }
88
89 /**
90 * Bind to right-click event and allow right-click copy and paste.
91 *
92 * **Logic**
93 * If text is selected and right-click happens on selected text, then
94 * do nothing to allow seamless copying.
95 * If no text is selected or right-click is outside of the selection
96 * area, then bring the terminal's input below the cursor, in order to
97 * trigger the event on the textarea and allow-right click paste, without
98 * caring about disappearing selection.
99 * @param {MouseEvent} ev The original right click event to be handled
100 * @param {Terminal} term The terminal on which to apply the handled paste event
101 */
102 export function rightClickHandler(ev: MouseEvent, term: ITerminal) {
103 let s = document.getSelection(),
104 selectedText = prepareTextForClipboard(s.toString()),
105 clickIsOnSelection = false,
106 x = ev.clientX,
107 y = ev.clientY;
108
109 if (s.rangeCount) {
110 let r = s.getRangeAt(0),
111 cr = r.getClientRects(),
112 i, rect;
113
114 for (i=0; i<cr.length; i++) {
115 rect = cr[i];
116 clickIsOnSelection = (
117 (x > rect.left) && (x < rect.right) &&
118 (y > rect.top) && (y < rect.bottom)
119 );
120
121 if (clickIsOnSelection) {
122 break;
123 }
124 }
125 // If we clicked on selection and selection is not a single space,
126 // then mark the right click as copy-only. We check for the single
127 // space selection, as this can happen when clicking on an &nbsp;
128 // and there is not much pointing in copying a single space.
129 if (selectedText.match(/^\s$/) || !selectedText.length) {
130 clickIsOnSelection = false;
131 }
132 }
133
134 // Bring textarea at the cursor position
135 if (!clickIsOnSelection) {
136 term.textarea.style.position = 'fixed';
137 term.textarea.style.width = '20px';
138 term.textarea.style.height = '20px';
139 term.textarea.style.left = (x - 10) + 'px';
140 term.textarea.style.top = (y - 10) + 'px';
141 term.textarea.style.zIndex = '1000';
142 term.textarea.focus();
143
144 // Reset the terminal textarea's styling
145 setTimeout(function () {
146 term.textarea.style.position = null;
147 term.textarea.style.width = null;
148 term.textarea.style.height = null;
149 term.textarea.style.left = null;
150 term.textarea.style.top = null;
151 term.textarea.style.zIndex = null;
152 }, 4);
153 }
154 }