Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Middle mouse button paste in gecko #31

Open
wants to merge 3 commits into from

3 participants

pstjvn Christopher Jeffrey (JJ) Daniel Risacher
pstjvn

This is a naive/lazy implementation for gecko middle mouse paste.

Gecko prohibits access to clipboard data in paste events. There are two solutions for this: either Flash or making diff to the content before the paste event and after it.

Because of how the terminal works (i.e. it expects text only, not html) a more simple solution would be to detect selection in the page and save the text of the selection and then use it in the case of paste event. It will not cover the case where the user wants to paste text from the clipboard, but is still useful because it can store selections from other windows/tabs in the same page.

pstjvn added some commits
pstjvn pstjvn Adds support for copy/middle button paste for Gecko/Firefox eefa0e6
pstjvn pstjvn Re-implemented using content editable changes to allow pasting from a…
…ny 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.
242a629
pstjvn

I see an issue with the second attempt: If I paste text with space in it the bash interpreter does not seem to like it.
For example I paste 'telnet 192.168.0.9' (which in code is
Terminal.prototype.send('whatever I pasted as text string');
). However when I press enter the bash interpreter thinks the whole string is one command (i.e. 'telnet\ 192.168.0.9') and thus cannot interpret it. Any idea why this is happening? I see that exactly the same code path is executed with the webkit approach of handling clipboad data.

Christopher Jeffrey (JJ)
Owner

There are two solutions for this:
.

either Flash

No.

making diff to the content before the paste event and after it

What you have looks interesting. I kind to want to fool around with it a bit first.

I see an issue with the second attempt

Hmm, I'll see if I can figure it out once I try it.

Daniel Risacher

Bump, +1, etc.

It really helps me to be able to paste into tty.js. I would love to see something like this in the main project so I don't have to re-apply the patch every time I upgrade tty.js.

It is a little flaky, though. Sometimes it pastes twice, for no adequately explained reason.

Daniel Risacher

I spent some time today trying to get this working again with current tty.js and current Firefox. The reason I was getting things pasted twice (2 months ago) was that the regular paste handler was running as well as the code from @pstjvn. It seems that Firefox 25.0.1 and Nightly now support right-click paste events for divs if they have contentEditable == true.

See this gist for a user.js file that patches up bindPaste() and adds a new mousedown listener: https://gist.github.com/risacher/7837761

This seems to work in Firefox, Chrome, and Safari - but I'm not sure I'm testing all the cases that are supposed to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 5, 2012
  1. pstjvn
  2. pstjvn

    Re-implemented using content editable changes to allow pasting from a…

    pstjvn authored
    …ny 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.
Commits on Jun 6, 2012
  1. pstjvn
This page is out of date. Refresh to see the latest.
Showing with 56 additions and 12 deletions.
  1. +56 −12 static/term.js
68 static/term.js
View
@@ -37,6 +37,8 @@
var window = this
, document = this.document;
+var isGecko = navigator.userAgent.indexOf('WebKit')==-1&&navigator.product=='Gecko';
+
/**
* EventEmitter
*/
@@ -321,6 +323,37 @@ 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).replace(/^[\s\xa0]+|[\s\xa0]+$/g, '').replace(/\xa0|\s/g, ' '));
+ }
+ 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();
});
@@ -334,18 +367,26 @@ Terminal.prototype.open = function() {
: ev.which != null
? ev.which - 1
: null;
+ // 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;
+ }
- // Does IE9 do this?
- if (~navigator.userAgent.indexOf('MSIE')) {
- button = button === 1 ? 0 : button === 4 ? 1 : button;
- }
-
- if (button !== 2) return;
+ if (button !== 2) return;
- self.element.contentEditable = 'true';
- setTimeout(function() {
- self.element.contentEditable = 'inherit'; // 'false';
- }, 1);
+ self.element.contentEditable = 'true';
+ setTimeout(function() {
+ self.element.contentEditable = 'inherit'; // 'false';
+ }, 1);
+ }
}, true);
on(this.element, 'paste', function(ev) {
@@ -356,8 +397,11 @@ Terminal.prototype.open = function() {
}
// 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();
Something went wrong with that request. Please try again.