Tuesday, May 29, 2012

How to copy to the clipboard in JavaScript?


What is the best way to copy text to the clipboard? (multi-browser)



I have tried:




function copyToClipboard(text)
{
if (window.clipboardData) // Internet Explorer
{
window.clipboardData.setData("Text", text);
}
else
{
unsafeWindow.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
const clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
clipboardHelper.copyString(text);
}
}



but in Internet Explorer it gives a syntax error. In Firefox, it says "unsafeWindow is not defined".


Source: Tips4all

18 comments:

  1. Nice library that works in Flash 10:

    https://github.com/jonrohan/ZeroClipboard

    ReplyDelete
  2. Automatic copying to clipboard may be dangerous, therefore most browsers (except IE) make it very difficult. Personally, I use the following simple trick:


    function copyToClipboard (text) {
    window.prompt ("Copy to clipboard: Ctrl+C, Enter", text);
    }

    The user is presented with the prompt box, where the text to be copied is already selected. Now it's enough to press Ctrl+C and Enter (to close the box) -- and voila!

    Now the clipboard copy operation is SAFE, because the user does it manually (but in a pretty straightforward way). Of course, works in all browsers.

    ReplyDelete
  3. If you want a really simple solution (takes less than 5 minutes to integrate) and looks good right out of the box then Clippy is a nice alternative to some of the more complex ones above.

    http://github.com/mojombo/clippy

    It's the same copy solution used but Github. Example Flash embed code below:

    <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
    width="110"
    height="14"
    id="clippy" >
    <param name="movie" value="/flash/clippy.swf"/>
    <param name="allowScriptAccess" value="always" />
    <param name="quality" value="high" />
    <param name="scale" value="noscale" />
    <param NAME="FlashVars" value="text=#{text}">
    <param name="bgcolor" value="#{bgcolor}">
    <embed src="/flash/clippy.swf"
    width="110"
    height="14"
    name="clippy"
    quality="high"
    allowScriptAccess="always"
    type="application/x-shockwave-flash"
    pluginspage="http://www.macromedia.com/go/getflashplayer"
    FlashVars="text=#{text}"
    bgcolor="#{bgcolor}"
    />
    </object>

    ReplyDelete
  4. With the following workaround, it will work in both IE and FireFox:

    First, download this swf file: http://www.logiclabz.com/postimg/clipboard.rar

    Then, use the following function to add text to the client's Clipboard:

    function copy_to_clipboard(text) {
    if (window.clipboardData) {
    window.clipboardData.setData('text', text);
    } else {
    var clipboarddiv = document.getElementById('divclipboardswf');
    if (!clipboarddiv) {
    clipboarddiv = document.createElement('div');
    clipboarddiv.setAttribute("name", "divclipboardswf");
    clipboarddiv.setAttribute("id", "divclipboardswf");
    document.body.appendChild(clipboarddiv);
    }
    clipboarddiv.innerHTML = '<embed src="clipboard.swf" FlashVars="clipboard=' + encodeURIComponent(text) + '" width="0" height="0" type="application/x-shockwave-flash"></embed>';
    }
    alert('The text is copied to your clipboard...');
    }


    Reference: http://www.logiclabz.com/javascript/copy-to-clipboard-with-javascript-on-mozilla-firefox-and-ie.aspx

    ReplyDelete
  5. This long blog post contains a lot of ways to do this: Accessing the System Clipboard with JavaScript – A Holy Grail?

    ReplyDelete
  6. Reading and modifying the clipboard from a webpage raises security and privacy concerns. However, in Internet Explorer, it is possible to do it. I found this example snippet:

    <script type="text/javascript">
    function select_all(obj) {
    var text_val=eval(obj);
    text_val.focus();
    text_val.select();
    if (!document.all) return; // IE only
    r = text_val.createTextRange();
    r.execCommand('copy');
    }
    </script>
    <input value="http://www.sajithmr.com"
    onclick="select_all(this)" name="url" type="text" />

    ReplyDelete
  7. In browsers other than IE you need to use a small flash object to manipulate the clipboard, e.g.


    http://www.rodsdot.com/ee/cross_browser_clipboard_copy_with_pop_over_message.asp
    http://ajaxian.com/archives/auto-copy-to-clipboard

    ReplyDelete
  8. The other methods will copy plain text to the clipboard. To copy HTML (ie, you can paste results into a WSIWYG editor), you can do the following in IE ONLY. This is is fundamentally different from the other methods, as the browser actually visibly selects the content.

    // create an editable DIV and append the HTML content you want copied
    var editableDiv = document.createElement("div");
    with (editableDiv) {
    contentEditable = true;
    }
    editableDiv.appendChild(someContentElement);

    // select the editable content and copy it to the clipboard
    var r = document.body.createTextRange();
    r.moveToElementText(editableDiv);
    r.select();
    r.execCommand("Copy");

    // deselect, so the browser doesn't leave the element visibly selected
    r.moveToElementText(someHiddenDiv);
    r.select();

    ReplyDelete
  9. As of Flash 10, you can only copy to clipboard if the action originates from user interaction with a Flash object. (Read related section from Adobe's Flash 10 announcement)

    The solution is to overly a flash object above the Copy button, or whatever element initiates the copy. Zero Clipboard is currently the best library with this implementation. Experienced Flash developers may just want to make their own library.

    ReplyDelete
  10. From one of the projects I've been working on, a jQuery copy-to-clipboard plugin that utilizes the Zero Clipboard library.

    It is easier to use than the native Zero Clipboard plugin if you're a heavy jQuery user.

    ReplyDelete
  11. Looks like you took the code from Greasemonkey\JavaScript Copy to Clipboard button or the original source of this snippet...

    This code was for Greasemonkey, hence the unsafeWindow. And I guess the syntax error in IE comes from the const keyword which is specific to Firefox (replace it with var).

    ReplyDelete
  12. I also suggest jQuery Clipboard Copy Plugins:

    $("#elmID").copy();

    ReplyDelete
  13. This is an expansion of @Chase's answer, with the advantage that it will work for IMAGE and TABLE elements, not just DIVs on IE9.

    if (document.createRange) {
    // IE9 and modern browsers
    var r = document.createRange();
    r.setStartBefore(to_copy);
    r.setEndAfter(to_copy);
    r.selectNode(to_copy);
    var sel = window.getSelection();
    sel.addRange(r);
    document.execCommand('Copy'); // does nothing on FF
    } else {
    // IE 8 and earlier. This stuff won't work on IE9.
    // (unless forced into a backward compatibility mode,
    // or selecting plain divs, not img or table).
    var r = document.body.createTextRange();
    r.moveToElementText(to_copy);
    r.select()
    r.execCommand('Copy');
    }

    ReplyDelete
  14. It seems I misread the question, but for reference, you can extract a range of the DOM (not to clipboard; compatible with all modern browsers), and combine it with the oncopy and onpaste and onbeforepaste events to get clipboard behaviour. Here's the code to achieve this:

    function clipBoard(sCommand) {
    var oRange=contentDocument.createRange();
    oRange.setStart(startNode, startOffset);
    oRange.setEnd(endNode, endOffset);
    /* This is where the actual selection happens.
    in the above, startNode and endNode are dom nodes defining the beginning
    and end of the "selection" respectively. startOffset and endOffset are
    constants that are defined as follows:

    END_TO_END: 2
    END_TO_START: 3
    NODE_AFTER: 1
    NODE_BEFORE: 0
    NODE_BEFORE_AND_AFTER: 2
    NODE_INSIDE: 3
    START_TO_END: 1
    START_TO_START: 0

    and would be used like oRange.START_TO_END */
    switch(sCommand) {
    case "cut":
    this.oFragment=oRange.extractContents();
    oRange.collapse();
    break;
    case "copy":
    this.oFragment=oRange.cloneContents();
    break;
    case "paste":
    oRange.deleteContents();
    var cloneFragment=this.oFragment.cloneNode(true)
    oRange.insertNode(cloneFragment);
    oRange.collapse();
    break;
    }
    }

    ReplyDelete
  15. I had the same problem building a custom grid edit from (something like Excel) and compatibility with Excel. I had to support selecting multiple cells, copying and pasting.

    Solution: create a textarea where you will be inserting data for the user to copy (for me when the user is selecting cells), set focus on it (for example, when user press Ctrl) and select the whole text.

    So, when the user hit Ctrl + C he gets copied cells he selected. After testing just resizing the textarea to 1 pixel (I didn't test if it will be working on display:none). It works nicely on all browsers, and it is transparent to the user.

    Pasting - you could do same like this (differs on your target) - keep focus on textarea and catch paste events using onpaste (in my project I use textareas in cells to edit).

    I can't paste an example (commercial project), but you got the idea.

    ReplyDelete
  16. As far as I know that only works in Internet Explorer.

    See also Dynamic Tools - JavaScript Copy To Clipboard, but it requires the user to change the configuration first and even then it doesn't seems to work.

    ReplyDelete
  17. Building upon Jarek Milewski's answer (which I upvoted, because it is elegant and pure JavaScript), I have created the following script, which allows you to copy the (one-line) script to your browser's address bar and hit [ENTER] to run at any time from any web page.

    javascript: window.prompt ("Copy to clipboard: Ctrl+C, Enter", location.href);location.href = location.href;


    This will allow the user to easily copy the current URL. Also, notice the last statement:

    location.href = location.href;


    That causes the browser to navigate back to the proper page, since (without that statement) most browsers will attempt to create a page that has the value of the button that the user clicked.

    Try it, it's interesting and cool that you can run from the address bar.

    ReplyDelete
  18. I found another nice solution LMCButton - small animated flash cross browser button. One JavaScript functions and swf button. Simple options (caption, custom JavaScript). Link: http://www.lettersmarket.com/view_blog/a-3-copy_to_clipboard_lmcbutton.html

    ReplyDelete