Manually revert textarea changes

This commit is contained in:
Daniel Imms
2016-07-12 16:03:31 -07:00
parent 39edbfb655
commit fc7b22dc48
2 changed files with 101 additions and 150 deletions
+17
View File
@@ -47,6 +47,23 @@
outline: none;
}
.terminal .xterm-helpers {
position: absolute;
top: 0;
}
.terminal .xterm-helper-textarea {
/*
* HACK: to fix IE's blinking cursor
* Move textarea out of the screen to the far left, so that the cursor is not visible.
*/
text-indent: -9999em;
opacity: 0;
width: 0;
height: 0;
z-index: -10;
}
.terminal .terminal-cursor {
background-color: #fff;
color: #000;
+84 -150
View File
@@ -108,8 +108,8 @@
var self = this;
function on() {
var args = Array.prototype.slice.call(arguments);
self.removeListener(type, on);
return listener.apply(self, args);
this.removeListener(type, on);
return listener.apply(this, args);
}
on.listener = listener;
return this.on(type, on);
@@ -434,7 +434,17 @@
* @public
*/
Terminal.prototype.focus = function() {
return this.element.focus();
if (document.activeElement === this.textarea) {
return;
}
if (this.sendFocus) {
this.send('\x1b[I');
}
this.showCursor();
this.textarea.focus();
Terminal.focus = this;
};
/**
@@ -460,7 +470,17 @@
* @public
*/
Terminal.prototype.blur = function() {
return this.element.blur();
if (Terminal.focus !== this) {
return;
}
this.cursorState = 0;
this.refresh(this.y, this.y);
this.textarea.blur();
if (this.sendFocus) {
this.send('\x1b[0]');
}
Terminal.focus = null;
};
/**
@@ -482,48 +502,9 @@
* Initialize default behavior
*/
Terminal.prototype.initGlobal = function() {
Terminal.bindKeys(this);
Terminal.bindPaste(this);
Terminal.bindKeys(this);
Terminal.bindCopy(this);
Terminal.bindCut(this);
Terminal.bindDrop(this);
Terminal.bindFocus(this);
Terminal.bindBlur(this);
};
/**
* Clears all selected text, inside the terminal.
*/
Terminal.prototype.clearSelection = function() {
var selectionBaseNode = window.getSelection().baseNode;
if (selectionBaseNode && (this.element.contains(selectionBaseNode.parentElement))) {
window.getSelection().removeAllRanges();
}
};
/**
* This function temporarily enables (leases) the contentEditable value of the terminal, which
* should be set back to false within 5 seconds at most.
*/
Terminal.prototype.leaseContentEditable = function (ms, callback) {
var term = this;
term.element.contentEditable = true;
/**
* Blur and re-focus instantly. This is due to a weird focus state on Chrome, when setting
* contentEditable to true on a focused element.
*/
term.blur();
term.focus();
setTimeout(function () {
term.element.contentEditable = false;
if (typeof callback == 'function') {
callback.call(term);
}
}, ms || 5000);
};
/**
@@ -531,70 +512,15 @@
* contentEditable value set to true.
*/
Terminal.bindPaste = function(term) {
on(term.element, 'paste', function(ev) {
on([term.textarea, term.element], 'paste', function(ev) {
ev.stopPropagation();
if (ev.clipboardData) {
var text = ev.clipboardData.getData('text/plain');
term.emit('paste', text, ev);
term.handler(text);
/**
* Cancel the paste event, or else things will be pasted twice:
* 1. by the terminal handler
* 2. by the browser, because of the contentEditable value being true
*/
term.cancel(ev, true);
/**
* After the paste event is completed, always set the contentEditable value to false.
*/
term.element.contentEditable = false;
term.textarea.value = '';
return term.cancel(ev);
}
});
/**
* Hack pasting with keyboard, in order to make it work without contentEditable.
* When a user types Ctrl + Shift + V or Shift + Insert on a non Mac or Cmd + V on a Mac,
* lease the contentEditable value as true.
*/
on(term.element, 'keydown', function (ev) {
var isEditable = term.element.contentEditable === "true";
/**
* If on a Mac, lease the contentEditable value temporarily, when the user presses
* the Cmd button, in a keydown event order to paste frictionlessly.
*/
if (term.isMac && ev.metaKey && !isEditable) {
term.leaseContentEditable(5000);
}
if (!term.isMac && !isEditable) {
if ((ev.keyCode == 45 && ev.shiftKey && !ev.ctrlKey) || // Shift + Insert
(ev.keyCode == 86 && ev.shiftKey && ev.ctrlKey)) { // Ctrl + Shict + V
term.leaseContentEditable();
}
}
});
/**
* Hack pasting with right-click in order to allow right-click paste, by leasing the
* contentEditable value as true.
*/
on(term.element, 'contextmenu', function (ev) {
term.leaseContentEditable();
});
};
/*
* Apply key handling to the terminal
*/
Terminal.bindKeys = function(term) {
on(term.element, 'keydown', function(ev) {
term.keyDown(ev);
}, true);
on(term.element, 'keypress', function(ev) {
term.keyPress(ev);
}, true);
};
/**
@@ -622,48 +548,44 @@
return processedText;
};
/**
* Apply key handling to the terminal
*/
Terminal.bindKeys = function(term) {
on(term.element, 'keydown', function(ev) {
if (document.activeElement != this) {
return;
}
term.keyDown(ev);
}, true);
on(term.element, 'keypress', function(ev) {
if (document.activeElement != this) {
return;
}
term.keyPress(ev);
}, true);
on(term.element, 'keyup', term.focus.bind(term));
on(term.textarea, 'keydown', function(ev) {
term.keyDown(ev);
}, true);
on(term.textarea, 'keypress', function(ev) {
term.keyPress(ev);
// Truncate the textarea's value, since it is not needed
this.value = '';
}, true);
};
/**
* Binds copy functionality to the given terminal.
* @static
*/
Terminal.bindCopy = function(term) {
on(term.element, 'copy', function(ev) {
var copiedText = window.getSelection().toString(),
text = Terminal.prepareCopiedTextForClipboard(copiedText);
ev.clipboardData.setData('text/plain', text);
ev.preventDefault();
});
};
/**
* Cancel the cut event completely
*/
Terminal.bindCut = function(term) {
on(term.element, 'cut', function (ev) {
ev.preventDefault();
});
};
Terminal.bindDrop = function (term) {
/*
* Do not perform the "drop" event. Altering the contents of the
* terminal with drag n drop is unwanted behavior.
*/
on(term.element, 'drop', function (ev) {
term.cancel(ev, true);
});
};
Terminal.click = function (term) {
/*
* Do not perform the "drop" event. Altering the contents of the
* terminal with drag n drop is unwanted behavior.
*/
on(term.element, 'click', function (ev) {
term.cancel(ev, true);
return; // temporary
});
};
@@ -740,7 +662,6 @@
this.element.classList.add('xterm');
this.element.classList.add('xterm-theme-' + this.theme);
this.element.setAttribute('tabindex', 0);
this.element.spellcheck = false;
/*
* Create the container that will hold the lines of the terminal and then
@@ -751,6 +672,27 @@
this.element.appendChild(this.rowContainer);
this.children = [];
/*
* Create the container that will hold helpers like the textarea for
* capturing DOM Events. Then produce the helpers.
*/
this.helperContainer = document.createElement('div');
this.helperContainer.classList.add('xterm-helpers');
this.element.appendChild(this.helperContainer);
this.textarea = document.createElement('textarea');
this.textarea.classList.add('xterm-helper-textarea');
this.textarea.setAttribute('autocorrect', 'off');
this.textarea.setAttribute('autocapitalize', 'off');
this.textarea.setAttribute('spellcheck', 'false');
this.textarea.tabIndex = 0;
this.textarea.onfocus = function() {
self.emit('focus', {terminal: self});
}
this.textarea.onblur = function() {
self.emit('blur', {terminal: self});
}
this.helperContainer.appendChild(this.textarea);
for (; i < this.rows; i++) {
this.insertRow();
}
@@ -2757,6 +2699,8 @@
Terminal.prototype.keyPress = function(ev) {
var key;
this.cancel(ev);
if (ev.charCode) {
key = ev.charCode;
} else if (ev.which == null) {
@@ -2775,21 +2719,11 @@
key = String.fromCharCode(key);
/**
* When a key is pressed and a character is sent to the terminal, then clear any text
* selected in the terminal.
*/
if (key) {
this.clearSelection();
}
this.emit('keypress', key, ev);
this.emit('key', key, ev);
this.showCursor();
this.handler(key);
this.cancel(ev, true);
return false;
};