1

How can I allow users to copy the current selection when they right click outside of the selection?

Here is a script that lets users select cells in HTML tables. It converts the selected cells to tab separated values and puts that in an offscreen textarea, so when the user clicks "Copy" in their Edit menu, or presses Ctrl-C, they can copy and paste the selected cells to Google Docs or another spreadsheet.

But I find many users are instead copy and pasting by right clicking and selecting "Copy" in the context menu. But when they select a table and try this, the current selection in the offscreen textarea is deselected, and "Copy" doesn't appear in the context menu - at least not in recent Firefox and Chrome :-(

Is there any way I can keep the current selection selected when the user does a right click, so "Copy" appears in the native context menu?

I found one related question about Internet Explorer but it sounds in that case like the current selection is deselected when the user right clicks even inside the selection: Text deselected on right click in IE8

Community
  • 1
  • 1
user916968
  • 305
  • 3
  • 9
  • So, the user right-clicks *outside* the selection, and you want to allow them to select "copy" from the context menu? – MaxArt Apr 22 '13 at 22:07
  • Yes, exactly. To illustrate, see the demo on [this page](http://nottheoilrig.com/cellect). Select some cells in the table and then right click on the square region that appears. I want "Copy" to appear in that context menu. – user916968 Apr 23 '13 at 15:05

1 Answers1

3

The context menu is managed by the browser, which decides whether to add a Copy (along with Cut and Paste) command in it. It can happen only when the context menu is opened on an user selection.

You can add a listener for the contextmenu event, which you can cancel and you can therefore create your custom context menu - which is pretty cool, but you won't be able to access to the clipboard without the help of some fancy technology like Flash.

There's a (dirty) trick you can use, though. But the <textarea> trick is a trick anyway. Style it like this:

textarea {
    position: absolute;
    margin: 0;
    padding: 0;
    border: 0 none;
    opacity: 0;
}

Now you can add an event listener for the contextmenu event:

var textarea = document.getElementsByTagName("TEXTAREA")[0];

document.addEventListener("contextmenu", function(e) {
    textarea.style.zIndex = 10000; // must be high enough
    textarea.style.left = e.pageX + "px";
    textarea.style.top = e.pageY + "px";
    textarea.setSelectionRange(0, textarea.value.length);
    setTimeout(function() {
        textarea.style.zIndex = -10000; // must be low enough
    }, 10);
});

What you'd be doing here is to place the textarea right below the cursor and select its whole content, so that the cursor will actually be on the selection.

The textarea must be on top of all the other elements, so you have to set its z-index style property to a high value. But then you will not want a "ghost" floating on your page which may prevent the expected mouse behaviour, so you immediately after you push it behind all the other elements (hence the setTimeout).

There, you have a working Copy on the context menu.

I've tested it on Chrome only, sorry. Should work on other browsers I guess, you only have to test. Will not work on IE8 and lower (which use attachEvent instead of addEventListener, and have a totally different way to select the text - check it out) and definitely not in IE8 (which always prevents the context menu to appear if you set a contextmenu event listener - must use the mousedown event and check for right clicks).

Caveat: depending on where the user clicks, the textarea may go outside the bottom and right page boundaries, thus causing the page scrollbars to appear. You can try to resize the textarea to be 1px wide and tall, and setting overflow: hidden.

Well, this answer has been quite informative for my own self too. Hope you'll like it.

Edit: live test

MaxArt
  • 22,200
  • 10
  • 82
  • 81
  • Wow, clever trick, thank you! In FF with "contextmenu" handler to reposition textarea, context menu had no "Copy". Using "mousedown" handler worked in FF, but in Chrome current selection was deselected and "Copy" context menu item was disabled. Repositioning with "mousedown" and reselecting with "contextmenu" worked in FF and Chrome. I tried to detect if "contextmenu" is needed, because you mentioned a problem in IE, but synthetic "mousedown" event didn't deselect, so for now I register "contextmenu" if /chrome/i.test(navigator.userAgent) http://bit.ly/15HqjQe Can you think of a better way? – user916968 Apr 24 '13 at 18:07
  • @user916968 I've created [this fiddle](http://jsfiddle.net/sfzBB/) to test the snippet. It works fine in Chrome 28 dev, IE10 and IE10 in IE9 compat mode. It fails with Firefox 20 and Opera 12.15, though, and I guess you'll have to use the `mousedown` event. – MaxArt Apr 24 '13 at 22:01