Cross-Browser approach to Copy content to Clipboard with javascript

rahul's picture

Before anything else, here is a sample demonstration of what I am discussing in this blog post. Enter some text in the textbox, and click the Flash's Copy icon below. You should have the text on your system clipboard. The .swf file for the same is attached with the post. Feel free to use it anywhere you like.

 

This is one of those topics, that has been blogged and written about furiously on the web. So, when I myself needed this functionality, I expected to find something useful on the web easily. And I thought I immediately hit the jackpot when a quick Google search threw up tons of pages for exactly what I was looking. However, it was not to be so, as I found out later.

Almost every solution that the Google search revealed worked, but the problem was only on Internet Explorer, not on other browsers and certainly not on Firefox. Some more research into the issue led me to pages like this, this and this, which clearly mention that FF considers it a security issue for Clipboard to be accessible to a web page. The crux of the matter was that you either need to explicitly enable Clipboard access to web pages in Firefox, or install add-ons that enable Clipboard access to web pages. As can be seen, none of these was a viable approach, as you do not expect the audience at large to configure settings or install add-ons on a page's request.

I was almost desperate that someone should have found a cross-browser solution of implementing this, as the problem is way too common. The tons of links I searched and followed took me no-where, everyone worked on IE but not on FF out-of-the-box.

I was wondering whether it is at all feasible to accomplish this, when something different struck my mind. Remember, Syntax Highlighter, the good old and wonderful syntax highlighting plugin from from Alex Gorbatchev (that it used on this site also for making the code stand-out and readable). The plugin put a toolbar on every piece of code, that had along with others a Copy button to copy the code. And as far as I knew, it worked on every browser, I had tested it on. Finally, I felt a way out here.

I immediately began debugging my own site's markup through Firebug to see how Syntax Highlighter handled Clipboard copying. And I was immediately stumped to see that it uses Flash for this purpose. Some more research revealed that it uses the Flash's System.setClipboard method for access to Clipboard.

Having figured out this, it should have been easy from here on. But again, it was not so. I immediately created a Flash movie, and enabled it to interact with javascript through Flash's ExternalInterface. What I thought of achieving was to embed a 1x1 pixel Flash movie into a page, and call a Flash javascript exported method from javascript to access Clipboard.

It did not take much time to assemble code, but the code did not work. I tried everything, from tweaking markup to browser settings to ActionScript code, but it simply did not work. Then I came across this post on adobe.com, which clearly spelt out that explicit user interaction is required in Flash 10 for successful access to clipboard (I tried bypassing this by manually raising Click Event on a button, and accessing Clipboard in the handler, needless to say, it failed).

So, in the end, it boiled down to this. The Flash movie itself required to have a UI against which User action would allow me to access clipboard. It was better than having nothing at all.

Now coming on to the coding part, you simple need to embed the Flash movie normally into a web page. Here's how I do it on this page:

 

<object id='clipboard' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0' width='16' height='16' align='middle'>
	<param name='allowScriptAccess' value='always' />
	<param name='allowFullScreen' value='false' />
	<param name='movie' value='clipboard.swf' />
	<param name='quality' value='high' />
	<param name='bgcolor' value='#ffffff' />
	<param name='wmode' value='transparent' />
	<param name='flashvars' value='callback=f1' />
	<embed src='clipboard.swf' flashvars='callback=f1' quality='high' bgcolor='#ffffff' width='16' height='16' wmode='transparent' name='clipboard' align='middle' allowscriptaccess='always' allowfullscreen='false' type='application/x-shockwave-flash' pluginspage='http://www.adobe.com/go/getflashplayer' />
</object>

 

There are 2 important things above. One, the Flash has been granted script access vis allowScriptAccess="true". Second, the content for copying normally would come from your page, and the movie is not aware of the content to place in clipboard. Therefore, you specify a callback method in the flashvars for the movie. This should be a fully-qualified reference to a method name in your javascript that should return a string which would be copied onto the clipboard. Here's the javascript method used on this page:

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }function f1() { var s = document.getElementById('text1').value; var div = document.createElement('div'); div.innerText = '"' + s + '" copied to clipboard.'; document.body.appendChild(div); if (window.clipboardData) window.clipboardData.setData('text', s); else return (s); } {/syntaxhighlighter}

What you should particularly note above is that IE provides out-of-the box window.clipboardData.setData method for putting data on the clipboard, which has been used. The Flash approach is used for all other browsers which do not support this. The user interaction still has to be through the Flash movie by clicking against it for everything to be able to work in a cross-browser fashion.

Use the comment form below to discuss any issue you face using this approach. I have tested it on IE, FF & Chrome, and it works!!

The html file attached below together with the clipboard Flash movie was used to create the example on the page above.

UPDATE:

  • Oct 24, 2010 - I later needed to pass custom parameters to the callback function also. So, enhanced the clipboard flash movie to support another flashvar called: callbackArg. You can use this to pass a string to the flash movie which the movie forwards to the javascript callback method when you click on the movie. Here's a sample code html for the same:
    <object id='clipboard' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0' width='16' height='16' align='middle'>
    	<param name='allowScriptAccess' value='always' />
    	<param name='allowFullScreen' value='false' />
    	<param name='movie' value='../resources/flash/clipboard.swf' />
    	<param name='quality' value='high' />
    	<param name='bgcolor' value='#ffffff' />
    	<param name='flashvars' value='callback=f1&callbackArg=MyCallbackArg' />
    	<embed src='../resources/flash/clipboard.swf' flashvars='callback=f1&callbackArg=MyCallbackArgument' quality='high' bgcolor='#ffffff' width='16' height='16' name='clipboard' align='middle' allowscriptaccess='always' allowfullscreen='false' type='application/x-shockwave-flash' pluginspage='http://www.adobe.com/go/getflashplayer' />
    </object>
    

    If you need to have multiple parameters for the callback method, or non-string argument, you can easily serialize those parameters as json, url encode them, and then set them as the callbackArg for the movie. then in your callback method, you would first url decode them and then deserialize them from json.
    For Json serialization, you can pick code from here or here, and for url encoding/decoding, you can use the browser's native encodeURIComponent and decodeURIComponent methods.
AttachmentSize
Clipboard.swf2.51 KB
Clipboard.htm1.67 KB

Comments

thank's for sharing

i wonder, if i want to use it without click the copy button,

but directly attach listener on html tag

like <a href='some text to copy' >clipboard</a>

how can i deal with it ? 

By ovi (not verified)
rahul's picture

Hi ovi, If you read the blog post carefully, I have answered this in the post itself. My approach is based on the use of a Flash movie and you could have achieved your objective prior to Flash 10 (i.e. in Flash 9 and earlier).

However, as per security changes in Flash 10 (read this post), user interaction is necessary for setting data on the system clipboard.

The Flash file attached above actually provides a method to call from javascript to do exactly what you are intending, but I did not discuss it in the blog, as any system would receive Flash 10 on a fresh install, and a majority of existing installs have automatic update enabled for Flash Player.

So, there's no point in discussing that option as that would work in only a limited number of cases. 

By rahul

Add new comment