As you might know, we have a feature on CopyPasteCharacter to let the user copy a character to their clipboard by just clicking on the character. An invisible Flash movie would do the copying using the ActionScript function System.setClipboard.

In October, Adobe updated the Flash Player to version 10, which included some security changes, like: “Setting the Clipboard will now have to be invoked through a button, keyboard shortcut, or some other event initiated by the user.”. This broke CopyPasteCharacter (and many other sites) for people running Flash 10. I had some ideas on how to solve workaround this a pretty long time ago but too little time to implement it until now.

We’re now having a fully working version which, since I couldn’t find any other solutions online, I thought could be useful for others/Google to know about.

The workaround I came up with is to use a hidden Flash movie which will get resized and moved to overlay the element/character where the user’s mouse is. This way, when the user clicks on the character, the Flash movie will receive the mouse event and therefore be allowed to set the system’s clipboard.

  1. The mouse roll overs a character.
  2. A JavaScript will resize and move the invisible Flash movie to match the character’s size and position
  3. The flash movie receives the mouseover and mouseouts so JavaScript can set the element’s class name (like a faked :hover selector)
  4. When (if?) the user clicks on the character, the click event will get received by the invisible Flash movie and not the document itself.
  5. The Flash movie asks JavaScript for the characters to copy (Clipboard#textToCopy) since it differs a bit depending on which element was clicked. Also, Flash tells JS if the the alt/option key was pressed (so the copy-multiple-characters-at-once feature works).
  6. The same #textToCopy function highlights the clicked element using the same code as we had for the Flash 9 version.

Here’s the code for the Flash movie (highlighted version)

import flash.external.*;

var text:String;

button.onRelease = function() {<br />
  text = String(ExternalInterface.call("Clipboard.textToCopy", Key.isDown(KEY.ALT))) || ' ';<br />
  System.setClipboard(text);<br />
  trace('copied [' + text + ']');<br />
}

button.onRollOver = function() {<br />
  ExternalInterface.call('Clipboard.onFlashButtonOver');<br />
}

button.onRollOut = function() {<br />
  ExternalInterface.call('Clipboard.onFlashButtonOut');<br />
}

The Clipboard class can be found here if you’re interested. It should keep the old behaviour for Flash 9 players but we had some problems with it in some browsers on Windows so right now all players get the updated code.

Note: This post has been lurking in my "Drafts" folder for about a month and shortly after we deployed the new code for Flash 10 a few weeks ago, I found the Zero Clipboard project which seems to use a similar approach as we did but as a stand alone library. I haven't looked at the code yet but it seems promising.