javascript cut/copy/paste to clipboard: how did Google solve it?

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?


Solution 1:

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.

Solution 2:

[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.)

Solution 3:

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.

Solution 4:

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