mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Move clipboard into its own module
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* xterm.js: xterm, in the browser
|
||||
* Copyright (c) 2016, SourceLair Private Company <www.sourcelair.com> (MIT License)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prepares text copied from terminal selection, to be saved in the clipboard by:
|
||||
* 1. stripping all trailing white spaces
|
||||
* 2. converting all non-breaking spaces to regular spaces
|
||||
* @param {string} text The copied text that needs processing for storing in clipboard
|
||||
* @returns {string}
|
||||
* @static
|
||||
*/
|
||||
function prepareTextForClipboard(text) {
|
||||
var space = String.fromCharCode(32),
|
||||
nonBreakingSpace = String.fromCharCode(160),
|
||||
allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'),
|
||||
processedText = text.split('\n').map(function (line) {
|
||||
// Strip all trailing white spaces and convert all non-breaking spaces
|
||||
// to regular spaces.
|
||||
var processedLine = line.replace(/\s+$/g, '').replace(allNonBreakingSpaces, space);
|
||||
|
||||
return processedLine;
|
||||
}).join('\n');
|
||||
|
||||
return processedText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds copy functionality to the given terminal.
|
||||
* @static
|
||||
*/
|
||||
function copyHandler (ev) {
|
||||
var copiedText = window.getSelection().toString(),
|
||||
text = prepareTextForClipboard(copiedText);
|
||||
|
||||
ev.preventDefault(); // Prevent or the original text will be copied.
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to paste event and allow both keyboard and right-click pasting, without having the
|
||||
* contentEditable value set to true.
|
||||
*/
|
||||
function pasteHandler(ev, term) {
|
||||
ev.stopPropagation();
|
||||
if (ev.clipboardData) {
|
||||
var text = ev.clipboardData.getData('text/plain');
|
||||
term.handler(text);
|
||||
term.textarea.value = '';
|
||||
return term.cancel(ev);
|
||||
}
|
||||
}
|
||||
|
||||
function rightClickHandler(ev) {
|
||||
var s = document.getSelection(),
|
||||
sText = prepareTextForClipboard(s.toString()),
|
||||
r = s.getRangeAt(0);
|
||||
|
||||
var x = ev.clientX,
|
||||
y = ev.clientY;
|
||||
|
||||
var cr = r.getClientRects(),
|
||||
clickIsOnSelection = false,
|
||||
i, rect;
|
||||
|
||||
for (i=0; i<cr.length; i++) {
|
||||
rect = cr[i];
|
||||
clickIsOnSelection = (
|
||||
(x > rect.left) && (x < rect.right) &&
|
||||
(y > rect.top) && (y < rect.bottom)
|
||||
);
|
||||
// If we clicked on selection and selection is not a single space,
|
||||
// then mark the right click as copy-only. We check for the single
|
||||
// space selection, as this can happen when clicking on an
|
||||
// and there is not much pointing in copying a single space.
|
||||
// Single space is char
|
||||
if (clickIsOnSelection && (sText !== ' ')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Bring textarea at the cursor position
|
||||
if (!clickIsOnSelection) {
|
||||
term.textarea.style.position = 'fixed';
|
||||
term.textarea.style.width = '10px';
|
||||
term.textarea.style.height = '10px';
|
||||
term.textarea.style.left = x + 'px';
|
||||
term.textarea.style.top = y + 'px';
|
||||
term.textarea.style.zIndex = 1000;
|
||||
term.textarea.focus();
|
||||
|
||||
// Reset the terminal textarea's styling
|
||||
setTimeout(function () {
|
||||
term.textarea.style.position = null;
|
||||
term.textarea.style.width = null;
|
||||
term.textarea.style.height = null;
|
||||
term.textarea.style.left = null;
|
||||
term.textarea.style.top = null;
|
||||
term.textarea.style.zIndex = null;
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
prepareTextForClipboard, copyHandler, pasteHandler, rightClickHandler
|
||||
};
|
||||
+10
-102
@@ -34,6 +34,7 @@
|
||||
import { CompositionHelper } from './CompositionHelper.js';
|
||||
import { EventEmitter } from './EventEmitter.js';
|
||||
import { Viewport } from './Viewport.js';
|
||||
import { rightClickHandler, pasteHandler, copyHandler } from './handlers/Clipboard.js';
|
||||
|
||||
/**
|
||||
* Terminal Emulation References:
|
||||
@@ -431,52 +432,20 @@ Terminal.bindBlur = function (term) {
|
||||
* Initialize default behavior
|
||||
*/
|
||||
Terminal.prototype.initGlobal = function() {
|
||||
Terminal.bindPaste(this);
|
||||
var term = this;
|
||||
|
||||
Terminal.bindKeys(this);
|
||||
Terminal.bindCopy(this);
|
||||
Terminal.bindFocus(this);
|
||||
Terminal.bindBlur(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Bind to paste event and allow both keyboard and right-click pasting, without having the
|
||||
* contentEditable value set to true.
|
||||
*/
|
||||
Terminal.bindPaste = function(term) {
|
||||
on([term.textarea, term.element], 'paste', function(ev) {
|
||||
ev.stopPropagation();
|
||||
if (ev.clipboardData) {
|
||||
var text = ev.clipboardData.getData('text/plain');
|
||||
term.handler(text);
|
||||
term.textarea.value = '';
|
||||
return term.cancel(ev);
|
||||
}
|
||||
// Bind clipboard functionality
|
||||
on(this.element, 'copy', copyHandler);
|
||||
on(this.textarea, 'paste', function (ev) {
|
||||
pasteHandler.call(this, ev, term);
|
||||
});
|
||||
on(this.element, 'contextmenu', function (ev) {
|
||||
rightClickHandler.call(this, ev, term);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepares text copied from terminal selection, to be saved in the clipboard by:
|
||||
* 1. stripping all trailing white spaces
|
||||
* 2. converting all non-breaking spaces to regular spaces
|
||||
* @param {string} text The copied text that needs processing for storing in clipboard
|
||||
* @returns {string}
|
||||
* @static
|
||||
*/
|
||||
Terminal.prepareCopiedTextForClipboard = function (text) {
|
||||
var space = String.fromCharCode(32),
|
||||
nonBreakingSpace = String.fromCharCode(160),
|
||||
allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'),
|
||||
processedText = text.split('\n').map(function (line) {
|
||||
/**
|
||||
* Strip all trailing white spaces and convert all non-breaking spaces to regular
|
||||
* spaces.
|
||||
*/
|
||||
var processedLine = line.replace(/\s+$/g, '').replace(allNonBreakingSpaces, space);
|
||||
|
||||
return processedLine;
|
||||
}).join('\n');
|
||||
|
||||
return processedText;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -515,16 +484,6 @@ Terminal.bindKeys = function(term) {
|
||||
term.on('refresh', term.compositionHelper.updateCompositionElements.bind(term.compositionHelper));
|
||||
};
|
||||
|
||||
/**
|
||||
* Binds copy functionality to the given terminal.
|
||||
* @static
|
||||
*/
|
||||
Terminal.bindCopy = function(term) {
|
||||
on(term.element, 'copy', function(ev) {
|
||||
return; // temporary
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Insert the given row to the terminal or produce a new one
|
||||
@@ -967,57 +926,6 @@ Terminal.prototype.bindMouse = function() {
|
||||
};
|
||||
}
|
||||
|
||||
// Handle right-click
|
||||
on(el, 'contextmenu', function (ev) {
|
||||
var s = document.getSelection(),
|
||||
sText = Terminal.prepareCopiedTextForClipboard(s.toString()),
|
||||
r = s.getRangeAt(0);
|
||||
|
||||
var x = ev.clientX,
|
||||
y = ev.clientY;
|
||||
|
||||
var cr = r.getClientRects(),
|
||||
clickIsOnSelection = false,
|
||||
i, rect;
|
||||
|
||||
for (i=0; i<cr.length; i++) {
|
||||
rect = cr[i];
|
||||
clickIsOnSelection = (
|
||||
(x > rect.left) && (x < rect.right) &&
|
||||
(y > rect.top) && (y < rect.bottom)
|
||||
)
|
||||
// If we clicked on selection and selection is not a single space,
|
||||
// then mark the right click as copy-only. We check for the single
|
||||
// space selection, as this can happen when clicking on an
|
||||
// and there is not much pointing in copying a single space.
|
||||
// Single space is char
|
||||
if (clickIsOnSelection && (sText !== ' ')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Bring textarea at the cursor position
|
||||
if (!clickIsOnSelection) {
|
||||
term.textarea.style.position = 'fixed';
|
||||
term.textarea.style.width = '10px';
|
||||
term.textarea.style.height = '10px';
|
||||
term.textarea.style.left = x + 'px';
|
||||
term.textarea.style.top = y + 'px';
|
||||
term.textarea.style.zIndex = 1000;
|
||||
term.textarea.focus();
|
||||
|
||||
// Reset the terminal textarea's styling
|
||||
setTimeout(function () {
|
||||
term.textarea.style.position = null;
|
||||
term.textarea.style.width = null;
|
||||
term.textarea.style.height = null;
|
||||
term.textarea.style.left = null;
|
||||
term.textarea.style.top = null;
|
||||
term.textarea.style.zIndex = null;
|
||||
}, 1);
|
||||
}
|
||||
});
|
||||
|
||||
on(el, 'mousedown', function(ev) {
|
||||
if (!self.mouseEvents) return;
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
var assert = require('chai').assert;
|
||||
var Terminal = require('../src/xterm');
|
||||
var Clipboard = require('../src/handlers/Clipboard');
|
||||
|
||||
|
||||
describe('evaluateCopiedTextProcessing', function () {
|
||||
it('should strip trailing whitespaces and replace nbsps with spaces', function () {
|
||||
var nonBreakingSpace = String.fromCharCode(160),
|
||||
copiedText = 'echo' + nonBreakingSpace + 'hello' + nonBreakingSpace,
|
||||
processedText = Clipboard.prepareTextForClipboard(copiedText);
|
||||
|
||||
// No trailing spaces
|
||||
assert.equal(processedText.match(/\s+$/), null);
|
||||
|
||||
// No non-breaking space
|
||||
assert.equal(processedText.indexOf(nonBreakingSpace), -1);
|
||||
});
|
||||
});
|
||||
@@ -245,20 +245,6 @@ describe('xterm.js', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('evaluateCopiedTextProcessing', function () {
|
||||
it('should strip trailing whitespaces and replace nbsps with spaces', function () {
|
||||
var nonBreakingSpace = String.fromCharCode(160),
|
||||
copiedText = 'echo' + nonBreakingSpace + 'hello' + nonBreakingSpace,
|
||||
processedText = Terminal.prepareCopiedTextForClipboard(copiedText);
|
||||
|
||||
// No trailing spaces
|
||||
assert.equal(processedText.match(/\s+$/), null);
|
||||
|
||||
// No non-breaking space
|
||||
assert.equal(processedText.indexOf(nonBreakingSpace), -1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Third level shift', function() {
|
||||
var evKeyDown = {
|
||||
preventDefault: function() {},
|
||||
|
||||
Reference in New Issue
Block a user