]> git.proxmox.com Git - mirror_xterm.js.git/blame - src/handlers/Clipboard.js
Fix right-click for Firefox and IE
[mirror_xterm.js.git] / src / handlers / Clipboard.js
CommitLineData
42a1e4ef
PK
1/**
2 * xterm.js: xterm, in the browser
3 * Copyright (c) 2016, SourceLair Private Company <www.sourcelair.com> (MIT License)
4 */
5
a224acb5
PK
6/**
7 * Clipboard handler module. This module contains methods for handling all
8 * clipboard-related events appropriately in the terminal.
9 * @module xterm/handlers/Clipboard
10 */
11
42a1e4ef
PK
12/**
13 * Prepares text copied from terminal selection, to be saved in the clipboard by:
14 * 1. stripping all trailing white spaces
15 * 2. converting all non-breaking spaces to regular spaces
16 * @param {string} text The copied text that needs processing for storing in clipboard
17 * @returns {string}
42a1e4ef
PK
18 */
19function prepareTextForClipboard(text) {
20 var space = String.fromCharCode(32),
21 nonBreakingSpace = String.fromCharCode(160),
22 allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'),
23 processedText = text.split('\n').map(function (line) {
24 // Strip all trailing white spaces and convert all non-breaking spaces
25 // to regular spaces.
26 var processedLine = line.replace(/\s+$/g, '').replace(allNonBreakingSpaces, space);
27
28 return processedLine;
29 }).join('\n');
30
31 return processedText;
32}
33
34/**
35 * Binds copy functionality to the given terminal.
a224acb5 36 * @param {ClipboardEvent} ev The original copy event to be handled
42a1e4ef
PK
37 */
38function copyHandler (ev) {
39 var copiedText = window.getSelection().toString(),
40 text = prepareTextForClipboard(copiedText);
41
a6f04733 42 ev.clipboardData.setData('text/plain', text);
42a1e4ef
PK
43 ev.preventDefault(); // Prevent or the original text will be copied.
44}
45
46/**
a224acb5
PK
47 * Redirect the clipboard's data to the terminal's input handler.
48 * @param {ClipboardEvent} ev The original paste event to be handled
49 * @param {Terminal} term The terminal on which to apply the handled paste event
42a1e4ef
PK
50 */
51function pasteHandler(ev, term) {
52 ev.stopPropagation();
77ca1549 53
54 var dispatchPaste = function(text) {
42a1e4ef
PK
55 term.handler(text);
56 term.textarea.value = '';
57 return term.cancel(ev);
77ca1549 58 };
59
60 var userAgent = window.navigator.userAgent.toLowerCase();
61 if (userAgent.match(/msie|MSIE/) || userAgent.match(/(T|t)rident/)) {
62 if (window.clipboardData) {
63 var text = window.clipboardData.getData('Text');
64 dispatchPaste(text);
65 }
66 } else {
67 if (ev.clipboardData) {
68 var text = ev.clipboardData.getData('text/plain');
69 dispatchPaste(text);
70 }
42a1e4ef
PK
71 }
72}
73
a224acb5
PK
74/**
75 * Bind to right-click event and allow right-click copy and paste.
76 *
77 * **Logic**
78 * If text is selected and right-click happens on selected text, then
79 * do nothing to allow seamless copying.
80 * If no text is selected or right-click is outside of the selection
81 * area, then bring the terminal's input below the cursor, in order to
82 * trigger the event on the textarea and allow-right click paste, without
83 * caring about disappearing selection.
84 * @param {ClipboardEvent} ev The original paste event to be handled
85 * @param {Terminal} term The terminal on which to apply the handled paste event
86 */
87function rightClickHandler(ev, term) {
42a1e4ef 88 var s = document.getSelection(),
35637797 89 selectedText = prepareTextForClipboard(s.toString()),
00dcb4f6 90 clickIsOnSelection = false;
42a1e4ef 91
00dcb4f6
PK
92 if (s.rangeCount) {
93 var r = s.getRangeAt(0),
94 cr = r.getClientRects(),
95 x = ev.clientX,
96 y = ev.clientY,
97 i, rect;
42a1e4ef 98
00dcb4f6
PK
99 for (i=0; i<cr.length; i++) {
100 rect = cr[i];
101 clickIsOnSelection = (
102 (x > rect.left) && (x < rect.right) &&
103 (y > rect.top) && (y < rect.bottom)
104 );
35637797
PK
105
106 if (clickIsOnSelection) {
00dcb4f6
PK
107 break;
108 }
42a1e4ef 109 }
35637797
PK
110 // If we clicked on selection and selection is not a single space,
111 // then mark the right click as copy-only. We check for the single
112 // space selection, as this can happen when clicking on an &nbsp;
113 // and there is not much pointing in copying a single space.
114 if (selectedText.match(/^\s$/) || !selectedText.length) {
115 clickIsOnSelection = false;
116 }
42a1e4ef
PK
117 }
118
119 // Bring textarea at the cursor position
120 if (!clickIsOnSelection) {
121 term.textarea.style.position = 'fixed';
35637797
PK
122 term.textarea.style.width = '20px';
123 term.textarea.style.height = '20px';
124 term.textarea.style.left = (x - 10) + 'px';
125 term.textarea.style.top = (y - 10) + 'px';
42a1e4ef
PK
126 term.textarea.style.zIndex = 1000;
127 term.textarea.focus();
128
129 // Reset the terminal textarea's styling
130 setTimeout(function () {
131 term.textarea.style.position = null;
132 term.textarea.style.width = null;
133 term.textarea.style.height = null;
134 term.textarea.style.left = null;
135 term.textarea.style.top = null;
136 term.textarea.style.zIndex = null;
35637797 137 }, 4);
42a1e4ef
PK
138 }
139}
140
141export {
142 prepareTextForClipboard, copyHandler, pasteHandler, rightClickHandler
143};