This section provides information about cutting, copying and pasting to and from the clipboard.
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.
Mozilla 提供很多剪贴板的接口。可使用 nsIClipboardHelper 接口的方法 copyString ,实现对字符串的拷贝。
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.
以上方法只提供了拷贝一个字符串的功能,如实现拷贝其他类型数据,如 URLS 或者图片,需使用其他较复杂的方法。
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:
nsIClipboard 接口提供了系统剪贴板的入口。可使用该接口拷贝粘贴任何类型的数据到剪贴板中。不过,需要三种XPCOM对象来实现该功能。第一,拷贝的源数据对象;第二,剪贴板对象;第三,粘贴目标对象。
可使用一下步骤来拷贝数据:
- 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. 将要拷贝的数据封装到xpcom对象中。这样就可以把各种类型的数据填充到剪贴板了。
- Create a transferring object. This object can be the component
@mozilla.org/widget/transferable;1
which implements the interface nsITransferable.创建一个传输对象,需实现 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.
为什么要借用传输对象,而不是直接将对象放置于剪贴板中呢?原因之一,一些系统并不是立即拷贝数据,相反,它们在数据被粘贴时才进行拷贝;原因之二,传输对象可持有同一数据的多种表示形式。如:一份HTML数据可表示为原始HTML格式或者是纯文本格式。当应用程序需要拷贝该数据却不能识别HTML时,它可使用纯文本格式;如果识别,则抓取HTML格式。传输对象将持有该剪贴板数据,直到程序决定如何使用它们时。这样,剪贴板可方便其他应用程序使用。
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).
以下将分步实现将数据拷贝到剪贴板中。
首先,创建封装拷贝数据的XPCOM对象。这里用 nsISupportsString 接口表征字符串(特别是 Unicode 字符串)。
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.
创建传输对象组件;告知传输对象要传输的类型,用 addDataFlavor 指定;使用 setTransferData 方法来设置传输的数据:包括数据类型,数据内容,以及数据长度。
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 kGlobalClipboard
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);
The complete function shown below copies some text to the clipboard as HTML, as well as making it a clickable Hyperlink. So we've added a text flavor and an HTML flavor of the content. The Transferable
object will hold both flavors.
copyLinkToClipboard : function(copyURL,copyLabel) { // generate the Unicode and HTML versions of the Link var textUnicode = copyURL; var textHtml = ("<a href=\"" + copyURL + "\">" + copyLabel + "</a>"); // make a copy of the Unicode var str = Components.classes["@mozilla.org/supports-string;1"]. createInstance(Components.interfaces.nsISupportsString); if (!str) return false; // couldn't get string obj str.data = textUnicode; // unicode string? // make a copy of the HTML var htmlstring = Components.classes["@mozilla.org/supports-string;1"]. createInstance(Components.interfaces.nsISupportsString); if (!htmlstring) return false; // couldn't get string obj htmlstring.data = textHtml; // add Unicode & HTML flavors to the transferable widget var trans = Components.classes["@mozilla.org/widget/transferable;1"]. createInstance(Components.interfaces.nsITransferable); if (!trans) return false; //no transferable widget found trans.addDataFlavor("text/unicode"); trans.setTransferData("text/unicode", str, textUnicode.length * 2); // *2 because it's unicode trans.addDataFlavor("text/html"); trans.setTransferData("text/html", htmlstring, textHtml.length * 2); // *2 because it's unicode // copy the transferable widget! var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]. getService(Components.interfaces.nsIClipboard); if (!clipboard) return false; // couldn't get the clipboard clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard); return true; },
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);
The first line performs the opposite of getData
. The data currently on the system clipboard is placed into the transferable. Next we create two JavaScript objects which will hold the data and the length of the data. Note that we have no idea what type of data is currently on the clipboard. It may have been placed there by another application. This is why we use generic Objects for str
and 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.
The variable str
now holds the data from the clipboard. We need to convert the data back into a JavaScript string from an XPCOM object. The code below can be used for this purpose:
if (str) str = str.value.QueryInterface(Components.interfaces.nsISupportsString); if (str) pastetext = str.data.substring(0, strLength.value / 2);
Because the data from the transferable is a nsISupportsString, we need to convert it into a JavaScript string. The property value
of the object filled in by getTransferData
, which is str
in this case, provides the actual value of the object.
We assign the string to the variable pastetext
. We can then put that into a textbox or other location as necessary.