Browser clipboard access
From Trephine
| « Script onload piggybacking | JavaScript copy to clipboard » |
[subscribe] Recent blog entries
- Simple prototypal inheritance new!
- Adventures in Rhino - setters and getters
- Site improvements - fighting with Disqus
- JavaScript task chaining
- JavaScript string building benchmarks
- Efficient JavaScript string building
- Alternative JavaScript worker thread API
- Implementing JavaScript worker threads
- Thread safe DOM manipulation
- Site improvements - CSS sprites
- Trephine worker threads made easy
- Pitfalls of multithreaded browser development
- Site improvements - reducing dependencies
- The unsplittability of XML
Live Demos
Browser clipboard access
Accessing the system clipboard is a notoriously difficult web problem. No major browser makes it easy, and only some even have APIs. Nevertheless, it is possible to access the system clipboard from the browser, given a sufficiently powerful plugin. This article shows you how.
Why use a plugin?
Unrestricted clipboard access would be a significant security concern (consider if you had credit card or password info in there), so it's understandable why browser makers take a hard line against programmatic clipboard access. Plugins, however, do not have to abide by the same security paradigms as the native browser.
In particular, signed Java applets have all the power of desktop Java, including access to the system clipboard. Trephine exposes this power to the web developer through a simple JavaScript API, which we'll use to read clipboard data.
Live demo
Without further ado, here's the executable JavaScript code:
// Setup steps to perform once trephine has loaded var setup = function(){ window.clipboard = { read: function() { var result = trephine.js( function() { var trans = java.awt.Toolkit.defaultToolkit.systemClipboard.getContents(null); var stringReader = trans.getTransferData(java.awt.datatransfer.DataFlavor.plainTextFlavor); var buf = new java.io.BufferedReader(stringReader), line, data = []; while ((line=buf.readLine())!=null) data[data.length] = line; return data.join("\n"); } ); if (result.error) throw result.error; return ( result.result ? result.result.toString() + '' : '' ); } }; alert('Setup complete! Now scroll down and try it out.'); }; // Load trephine, ask for privileges, then call setup() trephine.load({ onload: function() { trephine.askPermission( function(response) { if (response) setup(); else alert("Sorry, you must grant privileges to access the clipboard."); } ); } });
When you click the execute button at right, this code does the following:
- Loads trephine and prompts for elevated permissions,
- Creates a
clipboardobject with aread()function for extracting clipboard data.
Calling window.clipboard.read() will return any text in the system clipboard (if it contains text), or throws an exception on failure.
Here's an example to demonstrate:
try { var text = window.clipboard.read(); alert('Clipboard text: ' + text); } catch(err) { alert('Error reading text: ' + err.message); }
That's it!
How to use it in your code
Aside from the setup described above, you'll need to add trephine.js to your page as explained on the getting started page:
<script src="http://trephine.s3.amazonaws.com/trephine.js"></script>If you don't want to include the <script> tag directly in the page, you can load it dynamically. Bespin trepanation has a good example of how to achieve this, using script onload piggybacking to automatically perform the setup steps after the script is loaded.
How it works
The key logic behind reading from the clipboard is this:
var result = trephine.js( function() { var trans = java.awt.Toolkit.defaultToolkit.systemClipboard.getContents(null); var stringReader = trans.getTransferData(java.awt.datatransfer.DataFlavor.plainTextFlavor); var buf = new java.io.BufferedReader(stringReader), line, data = []; while ((line=buf.readLine())!=null) data[data.length] = line; return data.join("\n"); } );
The above defines an anonymous function containing JavaScript code to execute in the privileged Rhino context. The privileged code does the following:
- Grabs a reference to the system
Clipboard - Asks the clipboard for its contents (returned as a
Transferable) - Creates a
StringReaderfor extracting the clipboard data - Iterates over the lines of clipboard text, appending them to a data array
- Concatenates the data array and returns the results.
The trephine.js() function attempts to execute this code, returning a result object containing information about the success of the operation, any error thrown, and the return value.
It is the responsibility of the calling code to handle this response object and take appropriate action. In this case, the read() function re-throws any error encountered or simply returns the result on success.
Future directions
If you found this useful, please leave a comment! If there's interest, I'll write a follow up article on how to write to the clipboard, or extract other types of data (such as image data).
Trephine is supported on many platforms. If you have trouble running the demo on this page, please leave a comment, making sure to specify your operating system, OS version, browser, browser version and Java plugin version (if known). Thanks in advance!
Explicit public domain declaration
Just so there's no confusion: all of the code snippets on this page are provided "AS IS", without warranty of any kind, express or implied.
All of the code snippets on this page are hereby released into the public domain by the me, the copyright holder. This applies worldwide. Or in case this is not legally possible: The copyright holder grants any entity the right to use this work for any purpose, without any conditions, unless such conditions are required by law.
If you'd feel better with a "real" license, you're free to use code snippets on this page under the MIT license as described on the about page.
Any links back to this site are always appreciated, but not required. Enjoy!
--Jim R. Wilson (jimbojw) 16:19, 24 March 2009 (UTC)