26

Yes, this question has been asked again and again: how to copy and paste from and to the system clipboard with javascript? I have found only partial solutions and hacks so far. The reason that it has been asked so often in the past is that there still is no working solution. However, I saw that Google Docs actually has a working solution now for both keyboard events as well as buttons. So, it is possible, but how do they do it? Software Salad article, Accessing the System Clipboard with JavaScript – A Holy Grail?, gives a nice overview of the problem (but it's a few years old).

In short:

  • you can use keyboard events ctrl+x, ctrl+c, ctrl+v to either copy text from a hidden textarea with prepared data, or catch pasted text in a hidden field and then do something with it

  • you can use some hack via Flash or maybe a Java Applet to copy something to the system clipboard without need for user approval.

  • you can use a "real" solution with clipboardData.setData for IE and execCommand for other browsers, which depends on approval of the user.

Any idea how Google has tackled the clipboard problem?

Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
Jos de Jong
  • 6,602
  • 3
  • 38
  • 58
  • What browser are you using? With Chrome, I am at least getting this error when using Copy/Paste from the menu: http://imgur.com/8L5CR Which in turn would imply that they *haven't* tackled the problem. – Niklas Mar 11 '12 at 19:51
  • You are right, now I see they don't use the system clipboard (except for regular key events), but have created a Web Clipboard coupled to your account. – Jos de Jong Mar 11 '12 at 20:04

5 Answers5

27

I know that question was posted long ago, but I needed to check how google does that, so maybe someone will find that useful.

Actually google uses also system clipboard but it's a bit tricky. In case when you use keyboard shortcut you can catch copy/paste/cut event on e.g. window:

window.addEventListener('copy', function (ev) {
    console.log('copy event');
    // you can set clipboard data here, e.g.
    ev.clipboardData.setData('text/plain', 'some text pushed to clipboard');
    // you need to prevent default behaviour here, otherwise browser will overwrite your content with currently selected 
    ev.preventDefault();
});

live example for keyboard shortcut: http://jsfiddle.net/tyk9U/

Unfortunately this is only solution for keyboard shortcut and there is a problem with context menu, because you can't access clipboard data without native (trusted) copy/cut/paste event. But google does interesting trick. There is API document.execCommand() that allows you to run commands for contenteditable element and there is the command 'copy' which you can trigger it via document.execCommand('copy'). But when you try this in console in Chrome it will return false. I spent a bit of time investigating that and it turned out that they have Chrome extension installed, called "Google Drive" (go to chrome://apps/ and you can see it there) that enables clipboard access for domains drive.google.com and docs.google.com. Open some document or spreadsheet and type in console document.execCommand('copy') - it will return true. When you uninstall the extension you won't be able to use clipboard operations from context menu.

You can create such application for yourself with very simple manifest file (details here https://developer.chrome.com/apps/first_app):

{
    "manifest_version": 2,
    "name": "App name",
    "description": "App description",
    "version": "1.0",
    "app": {
        "urls": [
            "http://your.app.url.here/"
        ],
        "launch": {
            "web_url": "http://your.app.url.here/"
        }
    },
    "icons": {
        "128": "x-128.png"
    },
    "permissions": [
        "clipboardRead",
        "clipboardWrite"
    ]
}

"permissions" field here enables clipboard operations.

Now when you have this enabled you can do document.execCommand('copy') and it will work (will return true). But this is not everything - document.execCommand('copy') in chrome triggers copy event and you can catch it with the same code that is used for catching keyboard clipboard shortcuts. This is now Google does it.

Of course this description is valid only for Chrome.

Daniel Imms
  • 47,944
  • 19
  • 150
  • 166
Mateusz W
  • 1,981
  • 1
  • 14
  • 16
  • 1
    I was trying to test this answer and realized I couldn't reproduce simply by disabling the chrome extensions. I had to fully uninstall it. As another point. You can run document.execCommand('copy') as long its run in response to a valid user click event. I haven't been able to figure out if you can trap that event yourself though. Do you know if you have to have an extension to capture the ClipBoardEvent triggered by document.execCommand('copy')? The spec made me believe that the execCommand implementation didn't fire off an event. – Jason T. Dec 11 '15 at 03:51
  • @JasonT. that has changed recently - take a look here https://developers.google.com/web/updates/2015/04/cut-and-copy-commands – Mateusz W Dec 11 '15 at 09:38
12

[Note: This answer was accurate at the time it was written, and correctly answered the OP's question. However, technology has evolved since then; if you are interested in supporting copy-and-paste in your web app, please see the other, more recent answers on this page. —ruakh]


However, I saw that Google Docs actually has a working solution now for both keyboard events as well as buttons.

No, it doesn't. Not really. For keyboard events, Google Docs doesn't do anything; it simply doesn't block the browser's default copy-and-paste feature; so, users can copy and paste freely without Google Docs getting in the way. For buttons, Google Docs doesn't support the system clipboard, but its own "web clipboard" that is entirely within Google Docs. You can't use the toolbar buttons to copy text for pasting into another program on your computer, or to paste text that has been copied from another program on your computer.

For more information about this, see "Copying and pasting in Google Docs". (That's user-oriented rather than developer-oriented, but it does a decent job making clear what is and is not supported.)

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • 3
    Aha, now I get it. Google has created a "Web Clipboard", which allows you to copy/paste from any browser window to any browser window. So you don't use the system clipboard, but a web clipboard coupled to your account. Thanks. – Jos de Jong Mar 11 '12 at 20:02
  • @JosdeJong: Yes, exactly. :-) – ruakh Mar 11 '12 at 20:03
  • This answer has just helped me help someone trying to copy'n'paste from MS Excel to a Google spreadsheet. Thank you :-) – Stewart Jun 15 '12 at 10:35
  • @ruakh you're not entirely correct here. Try to copy some text from google docs with button (not keyboard) and paste it into other application - it works. Text gets copied to system clipboard (you can also install some kind of clipboard viewer to see that it's true). Take a look at my response below - they use Chrome extension installed by default in Chrome, and that way they are able to read from and write to system clipboard. – Mateusz W Aug 20 '14 at 14:06
  • 1
    @MateuszW: My answer is from almost a year and a half ago. I believe that it was accurate at the time; note that the help page I linked to has now been changed to say "You can use keyboard shortcuts [...]", which was not the case when I posted my answer. – ruakh Aug 20 '14 at 15:59
  • I disabled all of my browser extensions in Chrome and somehow the system copy/paste still works with Google Doc's menu buttons. Also, I can open console run document.execCommand('copy') and it returns true. Even in incognito mode, which no extensions are authorized for... same result. – Ecropolis Apr 23 '15 at 18:07
  • Yeah I can copy bitmap i mspaint and paste it using right-click custom context menu in google docs. So this answer is not accurate anymore. – Tomas M Dec 26 '15 at 10:09
  • FYI update: web clipboard will be gone as of 9/13/17. https://gsuiteupdates.googleblog.com/2017/05/web-clipboard-to-be-removed-from-google.html – Malik A. Rumi Aug 23 '17 at 02:37
4

As an addition to what others have already posted in this thread I've created a fully working example that demonstrates keyboard shortcut approach (CTRL+C or CMD+C on Mac OS X) as well as custom button approach which triggers the copy action.

Full demo can be found here: http://jsfiddle.net/rve7d/

I found Mateusz W answer very useful while trying to create this demo but he hasn't taken into consideration support for IE which behaves slightly different and uses different data types as a first parameter.

if(window.clipboardData) {
    // use just 'Text' or 'Url' as a first param otherwise strange exception is thrown
    window.clipboardData.setData('Text', 'Text that will be copied to CB');        
} else if(ev.originalEvent.clipboardData) {
    ev.originalEvent.clipboardData.setData('text/plain', 'Text that will be copied to CB');      
} else {
    alert('Clipboard Data are not supported in this browser. Sorry.');
}

PS: I needed this functionality for our custom Spreadsheet View component and on the way analysed the source code of Google Spreadsheets so my solution mostly conforms to their solution.

Marek Suscak
  • 1,086
  • 10
  • 25
3

The google uses a very simple but cool method. By using firebug you will get to know that the html code which is loaded has a text area in begining of size 1. What google doc does is that when user selects text and presses ctrl+c, it captures the event and by some technique gets the text which is selected in the doc container and sets the value of text area to that content. Than it focuses and selects the text area. Now it releases the ctrl+c event. But now the text is selected in text area so when the event is realeased the browser copies the text in text area and thus we get the copied text

coder hacker
  • 4,819
  • 1
  • 25
  • 50
0
<p>COPY : </p>
<p>Email me at <a class="js-emaillink" href="mailto:matt@example.co.uk">matt@example.co.uk</a></p>
<p><button class="js-emailcopybtn" value="clipboard" >clipboard</button></p>
<textarea rows="10" cols = "12"></textarea>
<p>CUT: </p>
<p><textarea class="js-cuttextarea">Hello I'm some text</textarea></p>
<p><button class="js-textareacutbtn" disable>Cut Textarea</button></p>
<script>
//copy clipboard
var copyEmailBtn = document.querySelector('.js-emailcopybtn');
copyEmailBtn.addEventListener('click', function(event) {
  // Выборка ссылки с электронной почтой
  var emailLink = document.querySelector('.js-emaillink');
  var range = document.createRange();
  range.selectNode(emailLink);
  window.getSelection().addRange(range);
  try {
    // Теперь, когда мы выбрали текст ссылки, выполним команду копирования
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copy email command was ' + msg);
  } catch(err) {
    console.log('Oops, unable to copy');
  }
  // Снятие выделения - ВНИМАНИЕ: вы должны использовать
  // removeRange(range) когда это возможно
  window.getSelection().removeAllRanges();
});
//cut
var cutTextareaBtn = document.querySelector('.js-textareacutbtn');
cutTextareaBtn.addEventListener('click', function(event) {
  var cutTextarea = document.querySelector('.js-cuttextarea');
  cutTextarea.select();
  try {
    var successful = document.execCommand('cut');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Cutting text command was ' + msg);
  } catch(err) {
    console.log('Oops, unable to cut');
  }
});
</script>
Piyin
  • 1,823
  • 1
  • 16
  • 23
zloctb
  • 10,592
  • 8
  • 70
  • 89