Using the Clipboard
This section provides information about cutting, copying and pasting to and from the clipboard.
Mozilla provides a number of interfaces for accessing the clipboard. The component '@mozilla.org/widget/clipboardhelper;1' can be used to copy text to the clipboard. This component implements the interface nsIClipboardHelper, which has a function copyString which can be used to copy a string.
const gClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"] .getService(Components.interfaces.nsIClipboardHelper); gClipboardHelper.copyString("Put me on the clipboard, please.");
This example will first create a clipboard helper and then copy a short string to the clipboard. This method only works to put strings on the clipboard. For other types of data, such as URLs or images, you will need to use a more complex method.
A component '@mozilla.org/widget/clipboard;1' and an interface nsIClipboard provide general access to the system clipboard. You can use it to copy and paste any type of data from your application to the clipboard. Three XPCOM objects are needed to handle clipboard operations. The first is an object that holds the data to put on the clipboard. The second is the clipboard object. The third is an object which is used to transfer the data from the first object to the clipboard. The clipboard model in Mozilla requires you to perform the following steps to copy data:
- Create an XPCOM wrapper for the data which you want to put on the clipboard. This is needed because you can put anything on the clipboard from text to images.
- Create a transferring object. This object can be the component "@mozilla.org/widget/transferable;1" which implements the interface nsITransferable.
- Tell the transferring object about the type of data being copied.
- Tell the transferring object about the data to copy.
- Create a clipboard object which refers to the system clipboard.
- Tell the clipboard object to copy the data using the transferring object.
You might wonder why a transferring object is needed instead of just putting the object directly on the clipboard. One reason is that some systems do not copy the data right away. Instead, they wait until the data is pasted. Another reason is that the transferable can hold multiple representations of the same data. For example, a piece of HTML can be represented in both its original HTML form and in plain text. If an application wants to get the data from the clipboard and doesn't understand HTML, it can use the plain text version. If it does understand HTML, it can grab that version. The transferring object will hold the clipboard contents until the application has decided what it needs. This allows the clipboard to be used by another application right away.
Let's break down the steps needed to copy data to the clipboard. First, we need to create an XPCOM object to wrap what we want to copy. We'll assume that we want to copy some text. We will use the interface nsISupportsString which can be used to represent strings (specifically, Unicode strings).
var copytext="Text to copy"; var str = Components.classes["@mozilla.org/supports-string;1"]. createInstance(Components.interfaces.nsISupportsString); str.data=copytext;
The first line holds the text that we want to copy. Next, the variable 'str' is assigned to a component that can be used to hold a string. The third line assigns the string to the component using the data property. Here, the string "Text to copy" will be copied but you can replace this with the text string that you want to copy. Now that we have the object to copy, a transferring object needs to be created:
var trans = Components.classes["@mozilla.org/widget/transferable;1"]. createInstance(Components.interfaces.nsITransferable); trans.addDataFlavor("text/unicode"); trans.setTransferData("text/unicode",str,copytext.length * 2);
The first line gets the transferring component which implements nsITransferable. Next, we need to tell the transferable what type of data we want to use. The type of data is referred to as a data flavor. The function addDataFlavor is used to tell the transferable that it needs to transfer data of a certain flavour. In this case, we are transferring the flavor "text/unicode" which is a Unicode string. Then, the function setTransferData is called which copies the data from the string into the transferable. This function takes three parameters. The first is the flavor we are setting, the second is the object holding the string and the third is the length of the data, in bytes. Here, the length is multiplied by two because we are using a Unicode string which requires two bytes per character.
You can repeat the last two lines and call addDataFlavor and setTransferData for multiple flavors. That way, you could have a text version and an HTML version of the content. The Transferable object will hold its own copy of the data. When you've added all the flavors you want, you can put it all on the clipboard at once. The transferable object will hold all of the data that you want until you're ready to put it on the clipboard.
Next, we need to create a clipboard object that refers to the system clipboard.
var clipid = Components.interfaces.nsIClipboard; var clip = Components.classes["@mozilla.org/widget/clipboard;1"].getService(clipid); clip.setData(trans,null,clipid.kGlobalClipboard);
We get the system clipboard object and store it in the clip variable. We can copy the data to the clipboard by calling the function setData. The first parameter of this function is the transferable. The second parameter can usually be set to null but you could set it to a nsIClipboardOwner so that you can tell when the data you've copied is overwritten by another copy operation. Call setData only when you're ready to copy to the system clipboard.
The third parameter to setData (and the parameter to emptyClipboard) indicates which clipboard buffer to use. The above code uses the constant kGlobalConstant for this, which refers to the global clipboard. This would be the same one that cut and paste operations from the Edit menu typically use. If you use kSelectionClipboard instead, you will copy into the selection buffer, which is generally only available on Unix systems.
This multi-step process has resulted in text being copied on the clipboard. We can cut to the clipboard instead of copying by doing a copy and then deleting the original data. Normally, the text would be in a document or textbox. The code is put together below, with additional error checking:
var copytext="Text to copy"; var str = Components.classes["@mozilla.org/supports-string;1"]. createInstance(Components.interfaces.nsISupportsString); if (!str) return false; str.data = copytext; var trans = Components.classes["@mozilla.org/widget/transferable;1"]. createInstance(Components.interfaces.nsITransferable); if (!trans) return false; trans.addDataFlavor("text/unicode"); trans.setTransferData("text/unicode",str,copytext.length * 2); var clipid = Components.interfaces.nsIClipboard; var clip = Components.classes["@mozilla.org/widget/clipboard;1"].getService(clipid); if (!clip) return false; clip.setData(trans,null,clipid.kGlobalClipboard);
Pasting Clipboard Contents
To paste data from the clipboard we can use a similar process, except we use getData instead of setData and getTransferData instead of setTransferData. Here are the steps to pasting:
- Create a clipboard object which refers to the system clipboard.
- Create a transferring object which implements the nsITransferable interface.
- Tell the transferring object about the flavor of data you want to get.
- Retrieve the data from the clipboard and put it in the transferable.
- Get the data from the transferring object.
The first steps are similar to that used for copying:
var clip = Components.classes["@mozilla.org/widget/clipboard;1"]. getService(Components.interfaces.nsIClipboard); if (!clip) return false; var trans = Components.classes["@mozilla.org/widget/transferable;1"]. createInstance(Components.interfaces.nsITransferable); if (!trans) return false; trans.addDataFlavor("text/unicode");
This code gets the system clipboard object and a transferable object. The flavor is added to the transferable. Next, we need to get the data from the clipboard:
clip.getData(trans,clip.kGlobalClipboard); var str = new Object(); var strLength = new Object(); trans.getTransferData("text/unicode",str,strLength);
Then we use getTransferData to retrieve the data from the transferable. We specify the flavor we would like to get. The data will be converted if it is not of the desired flavor and a conversion between the actual and desired flavor is possible. If you originally copied data of multiple flavors onto the clipboard, you can retrieve the data in the best format necessary. For example, a textbox would accept text/unicode (or text/plain) while a Composer window might accept HTML and image data.
if (str) str = str.value.QueryInterface(Components.interfaces.nsISupportsString); if (str) pastetext = str.data.substring(0,strLength.value / 2);
We assign the string to the variable pastetext. We can then put that into a textbox or other location as necessary.
(Next) In the next section, we'll find out how to create elements that support drag and drop.