/**
* xterm.js: xterm, in the browser
- * Copyright (c) 2014, SourceLair Limited <www.sourcelair.com> (MIT License)
+ * Copyright (c) 2014-2014, SourceLair Private Company <www.sourcelair.com> (MIT License)
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
* https://github.com/chjj/term.js
*
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:
* Creates a new `Terminal` object.
*
* @param {object} options An object containing a set of options, the available options are:
- * - cursorBlink (boolean): Whether the terminal cursor blinks
+ * - `cursorBlink` (boolean): Whether the terminal cursor blinks
+ * - `cols` (number): The number of columns of the terminal (horizontal size)
+ * - `rows` (number): The number of rows of the terminal (vertical size)
*
* @public
* @class Xterm Xterm
this.cols = options.cols || options.geometry[0];
this.rows = options.rows || options.geometry[1];
+ this.geometry = [this.cols, this.rows];
if (options.handler) {
this.on('data', options.handler);
* 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;
};
/**
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
Terminal.loadAddon = function(addon, callback) {
if (typeof exports === 'object' && typeof module === 'object') {
// CommonJS
- return require(__dirname + '/../addons/' + addon);
+ return require('./addons/' + addon + '/' + addon);
} else if (typeof define == 'function') {
// RequireJS
- return require(['../addons/' + addon + '/' + addon], callback);
+ return require(['./addons/' + addon + '/' + addon], callback);
} else {
console.error('Cannot load a module without a CommonJS or RequireJS environment.');
return false;
};
}
- // 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;
this.refresh(0, this.rows - 1);
};
+/**
+ * Scroll the display of the terminal by a number of pages.
+ * @param {number} pageCount The number of pages to scroll (negative scrolls up).
+ */
+Terminal.prototype.scrollPages = function(pageCount) {
+ this.scrollDisp(pageCount * (this.rows - 1));
+}
+
+/**
+ * Scrolls the display of the terminal to the top.
+ */
+Terminal.prototype.scrollToTop = function() {
+ this.scrollDisp(-this.ydisp);
+}
+
+/**
+ * Scrolls the display of the terminal to the bottom.
+ */
+Terminal.prototype.scrollToBottom = function() {
+ this.scrollDisp(this.ybase - this.ydisp);
+}
+
/**
* Writes text to the terminal.
* @param {string} text The text to write to the terminal.
this.normal = null;
+ this.geometry = [this.cols, this.rows];
this.emit('resize', {terminal: this, cols: x, rows: y});
};
/**
- * Emit the 'data' event and populate the given data.
- * @param {string} data The data to populate in the event.
- */
+ * Emit the 'data' event and populate the given data.
+ * @param {string} data The data to populate in the event.
+ */
Terminal.prototype.handler = function(data) {
this.emit('data', data);
};
/**
- * CSI Ps T Scroll down Ps lines (default = 1) (SD).
- */
+ * CSI Ps T Scroll down Ps lines (default = 1) (SD).
+ */
Terminal.prototype.scrollDown = function(params) {
var param = params[0] || 1;
while (param--) {