From eefa0e654c1192e5c732a64b91000c72ca6e2199 Mon Sep 17 00:00:00 2001 From: pstjvn Date: Tue, 5 Jun 2012 14:01:46 +0300 Subject: [PATCH 1/3] Adds support for copy/middle button paste for Gecko/Firefox --- static/term.js | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/static/term.js b/static/term.js index 202eac55..dda863a6 100644 --- a/static/term.js +++ b/static/term.js @@ -36,7 +36,17 @@ var window = this , document = this.document; - + +/** + * If the browser is the targeted one + * @type {boolean} + */ +var isGecko = navigator.userAgent.indexOf('WebKit')==-1&&navigator.product=='Gecko'; +/** + * The text selection + * @type {string} + */ +var buffered_ = '' /** * EventEmitter */ @@ -324,11 +334,22 @@ Terminal.prototype.open = function() { on(this.element, 'mousedown', function() { self.focus(); }); + + // Hook our events only if the browser is the targeted one + if ( isGecko ) { + on(this.elements, 'mouseup', function(e){ + if ( e.button == 0) { + var selection = window.getSelection().toString(); + if ( selection != '') buffered_ = selection; + } + }, true); + } // This probably shouldn't work, // ... but it does. Firefox's paste // event seems to only work for textareas? on(this.element, 'mousedown', function(ev) { + var wait = false; var button = ev.button != null ? +ev.button : ev.which != null @@ -339,17 +360,24 @@ Terminal.prototype.open = function() { if (~navigator.userAgent.indexOf('MSIE')) { button = button === 1 ? 0 : button === 4 ? 1 : button; } - - if (button !== 2) return; + if ( isGecko && button == 1) { + wait = true; + } else { + if (button !== 2) return; + } self.element.contentEditable = 'true'; - setTimeout(function() { - self.element.contentEditable = 'inherit'; // 'false'; - }, 1); + if (!wait) { + setTimeout(function() { + self.element.contentEditable = 'inherit'; // 'false'; + }, 1); + } }, true); on(this.element, 'paste', function(ev) { - if (ev.clipboardData) { + if ( isGecko ) { + if ( buffered_ != '' ) self.send(buffered_); + } else if (ev.clipboardData) { self.send(ev.clipboardData.getData('text/plain')); } else if (window.clipboardData) { self.send(window.clipboardData.getData('Text')); From 242a629ee82736e75e550c8f6c07be021d59fc38 Mon Sep 17 00:00:00 2001 From: pstjvn Date: Tue, 5 Jun 2012 19:08:09 +0300 Subject: [PATCH 2/3] Re-implemented using content editable changes to allow pasting from any source. Not as aesthetically pleasing (the pasted content appears for a moment there), but works correctly for pasting from any source. Needs some testing on older hardware for the timeout in the timing of receiving DOMCharacterDataModified but works good on recent netbooks and recent PCs. --- static/term.js | 90 +++++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/static/term.js b/static/term.js index dda863a6..0df8df83 100644 --- a/static/term.js +++ b/static/term.js @@ -36,17 +36,9 @@ var window = this , document = this.document; - -/** - * If the browser is the targeted one - * @type {boolean} - */ + var isGecko = navigator.userAgent.indexOf('WebKit')==-1&&navigator.product=='Gecko'; -/** - * The text selection - * @type {string} - */ -var buffered_ = '' + /** * EventEmitter */ @@ -331,43 +323,66 @@ Terminal.prototype.open = function() { this.startBlink(); + var timer_; + var evt; + var process = function() { + var parent = evt.target.parentNode; + var text = parent.textContent; + parent.contentEditable = 'inherit'; + parent.blur(); + parent.innerHTML = parent.dataset.ohtml; + var a1 = parent.dataset.oc.split(''); + var a2 = text.split(''); + var fi = -1; + if ( a1.length != a2.length ) { + for (var i = 0; i < a1.length; i++) { + if ( a1[i] != a2[i] ){ + fi = i; + break; + } + } + self.send(text.substr(fi, a2.length - a1.length + 1)); + } + parent.removeEventListener('DOMCharacterDataModified',_handler, false); + delete parent.dataset.ohtml; + delete parent.dataset.oc; + parent.style.width = ''; + }; + var _handler = function(ev) { + clearTimeout(timer_); + evt = ev; + timer_ = setTimeout(process, 50); + }; + on(this.element, 'mousedown', function() { self.focus(); }); - - // Hook our events only if the browser is the targeted one - if ( isGecko ) { - on(this.elements, 'mouseup', function(e){ - if ( e.button == 0) { - var selection = window.getSelection().toString(); - if ( selection != '') buffered_ = selection; - } - }, true); - } // This probably shouldn't work, // ... but it does. Firefox's paste // event seems to only work for textareas? on(this.element, 'mousedown', function(ev) { - var wait = false; var button = ev.button != null ? +ev.button : ev.which != null ? ev.which - 1 : null; - - // Does IE9 do this? - if (~navigator.userAgent.indexOf('MSIE')) { - button = button === 1 ? 0 : button === 4 ? 1 : button; - } - if ( isGecko && button == 1) { - wait = true; + // Handle Gecko separately + if (isGecko && button == 1) { + ev.target.dataset.oc = ev.target.textContent; + ev.target.dataset.ohtml = ev.target.innerHTML; + ev.target.style.width = getComputedStyle(ev.target).width; + ev.target.addEventListener('DOMCharacterDataModified', _handler, false); + ev.target.contentEditable = true; } else { + // Does IE9 do this? + if (~navigator.userAgent.indexOf('MSIE')) { + button = button === 1 ? 0 : button === 4 ? 1 : button; + } + if (button !== 2) return; - } - self.element.contentEditable = 'true'; - if (!wait) { + self.element.contentEditable = 'true'; setTimeout(function() { self.element.contentEditable = 'inherit'; // 'false'; }, 1); @@ -375,17 +390,18 @@ Terminal.prototype.open = function() { }, true); on(this.element, 'paste', function(ev) { - if ( isGecko ) { - if ( buffered_ != '' ) self.send(buffered_); - } else if (ev.clipboardData) { + if (ev.clipboardData) { self.send(ev.clipboardData.getData('text/plain')); } else if (window.clipboardData) { self.send(window.clipboardData.getData('Text')); } // Not necessary. Do it anyway for good measure. self.element.contentEditable = 'inherit'; - return cancel(ev); - }); + // Gecko needs to receive the paste event + if ( !isGecko ) { + return cancel(ev); + } + }); this.bindMouse(); @@ -4030,4 +4046,4 @@ if (typeof module !== 'undefined') { }).call(function() { return this || (typeof window !== 'undefined' ? window : global); -}()); +}()); \ No newline at end of file From 105f46ca52630b7aec20e406ace4b99f4774c280 Mon Sep 17 00:00:00 2001 From: Peter StJ Date: Wed, 6 Jun 2012 13:55:46 +0300 Subject: [PATCH 3/3] Fixes withspace when sending to socket in Firefox --- static/term.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/term.js b/static/term.js index 0df8df83..1d73869d 100644 --- a/static/term.js +++ b/static/term.js @@ -341,7 +341,7 @@ Terminal.prototype.open = function() { break; } } - self.send(text.substr(fi, a2.length - a1.length + 1)); + self.send(text.substr(fi, a2.length - a1.length + 1).replace(/^[\s\xa0]+|[\s\xa0]+$/g, '').replace(/\xa0|\s/g, ' ')); } parent.removeEventListener('DOMCharacterDataModified',_handler, false); delete parent.dataset.ohtml; @@ -4046,4 +4046,4 @@ if (typeof module !== 'undefined') { }).call(function() { return this || (typeof window !== 'undefined' ? window : global); -}()); \ No newline at end of file +}());