зеркало из https://github.com/mozilla/pjs.git
Bug 39098 - Elements with visibility:hidden, visibility:collapse, or display:none get copied to the clipboard. r=dbaron
This commit is contained in:
Родитель
c345de3323
Коммит
fe08c8398a
|
@ -61,7 +61,7 @@ interface nsIDocumentEncoderNodeFixup : nsISupports
|
|||
nsIDOMNode fixupNode(in nsIDOMNode aNode, out boolean aSerializeCloneKids);
|
||||
};
|
||||
|
||||
[scriptable, uuid(f85c5a20-258d-11db-a98b-0800200c9a66)]
|
||||
[scriptable, uuid(196a3aee-006e-4f8f-a420-e1c1b0958a26)]
|
||||
interface nsIDocumentEncoder : nsISupports
|
||||
{
|
||||
// Output methods flag bits. There are a frightening number of these,
|
||||
|
@ -215,6 +215,13 @@ interface nsIDocumentEncoder : nsISupports
|
|||
*/
|
||||
const unsigned long OutputDontRewriteEncodingDeclaration = (1 << 18);
|
||||
|
||||
/**
|
||||
* When using the HTML or XHTML serializer, skip elements that are not
|
||||
* visible when this flag is set. Elements are not visible when they
|
||||
* have CSS style display:none or visibility:collapse, for example.
|
||||
*/
|
||||
const unsigned long SkipInvisibleContent = (1 << 19);
|
||||
|
||||
/**
|
||||
* Initialize with a pointer to the document and the mime type.
|
||||
* @param aDocument Document to encode.
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include "nsString.h"
|
||||
|
||||
// Interfaces needed to be included
|
||||
#include "nsIVariant.h"
|
||||
#include "nsCopySupport.h"
|
||||
#include "nsIDOMNSUIEvent.h"
|
||||
#include "nsIDOMUIEvent.h"
|
||||
#include "nsISelection.h"
|
||||
|
@ -59,9 +59,7 @@
|
|||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMDocumentRange.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "nsIDOMHTMLAreaElement.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsITransferable.h"
|
||||
|
@ -75,14 +73,12 @@
|
|||
#include "nsIDocShell.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsRange.h"
|
||||
#include "nsIWebBrowserPersist.h"
|
||||
#include "nsEscape.h"
|
||||
|
@ -90,18 +86,50 @@
|
|||
#include "nsIMIMEService.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "imgIRequest.h"
|
||||
#include "nsContentCID.h"
|
||||
#include "nsDOMDataTransfer.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kHTMLConverterCID, NS_HTMLFORMATCONVERTER_CID);
|
||||
|
||||
// private clipboard data flavors for html copy, used by editor when pasting
|
||||
#define kHTMLContext "text/_moz_htmlcontext"
|
||||
#define kHTMLInfo "text/_moz_htmlinfo"
|
||||
|
||||
nsresult NS_NewDomSelection(nsISelection **aDomSelection);
|
||||
|
||||
// if inNode is null, use the selection from the window
|
||||
static nsresult
|
||||
GetTransferableForNodeOrSelection(nsIDOMWindow* aWindow,
|
||||
nsIContent* aNode,
|
||||
nsITransferable** aTransferable)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aWindow);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
aWindow->GetDocument(getter_AddRefs(domDoc));
|
||||
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
|
||||
if (node) {
|
||||
// Make a temporary selection with this node in a single range.
|
||||
rv = NS_NewDomSelection(getter_AddRefs(selection));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
rv = NS_NewRange(getter_AddRefs(range));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = range->SelectNode(node);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = selection->AddRange(range);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
aWindow->GetSelection(getter_AddRefs(selection));
|
||||
}
|
||||
|
||||
rv = nsCopySupport::GetTransferableForSelection(selection, doc,
|
||||
aTransferable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
class NS_STACK_CLASS DragDataProducer
|
||||
{
|
||||
|
@ -134,13 +162,6 @@ private:
|
|||
static void GetSelectedLink(nsISelection* inSelection,
|
||||
nsIContent **outLinkNode);
|
||||
|
||||
// if inNode is null, use the selection from the window
|
||||
static nsresult SerializeNodeOrSelection(nsIDOMWindow* inWindow,
|
||||
nsIContent* inNode,
|
||||
nsAString& outResultString,
|
||||
nsAString& outHTMLContext,
|
||||
nsAString& outHTMLInfo);
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> mWindow;
|
||||
nsCOMPtr<nsIContent> mTarget;
|
||||
nsCOMPtr<nsIContent> mSelectionTargetNode;
|
||||
|
@ -417,6 +438,7 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
|||
|
||||
*aDragNode = nsnull;
|
||||
|
||||
nsresult rv;
|
||||
nsIContent* dragNode = nsnull;
|
||||
|
||||
// find the selection to see what we could be dragging and if
|
||||
|
@ -663,24 +685,31 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
|||
nodeToSerialize = nsnull;
|
||||
}
|
||||
|
||||
SerializeNodeOrSelection(mWindow, nodeToSerialize,
|
||||
mHtmlString, mContextString, mInfoString);
|
||||
|
||||
nsCOMPtr<nsIFormatConverter> htmlConverter =
|
||||
do_CreateInstance(kHTMLConverterCID);
|
||||
NS_ENSURE_TRUE(htmlConverter, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsISupportsString> html =
|
||||
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
||||
NS_ENSURE_TRUE(html, NS_ERROR_FAILURE);
|
||||
html->SetData(mHtmlString);
|
||||
|
||||
nsCOMPtr<nsISupportsString> text;
|
||||
PRUint32 textLen;
|
||||
htmlConverter->Convert(kHTMLMime, html, mHtmlString.Length() * 2,
|
||||
kUnicodeMime, getter_AddRefs(text), &textLen);
|
||||
NS_ENSURE_TRUE(text, NS_ERROR_FAILURE);
|
||||
text->GetData(mTitleString);
|
||||
mHtmlString.Truncate();
|
||||
mContextString.Truncate();
|
||||
mInfoString.Truncate();
|
||||
mTitleString.Truncate();
|
||||
nsCOMPtr<nsITransferable> transferable;
|
||||
rv = ::GetTransferableForNodeOrSelection(mWindow, nodeToSerialize,
|
||||
getter_AddRefs(transferable));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsISupportsString> data;
|
||||
PRUint32 dataSize;
|
||||
rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(data), &dataSize);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
data->GetData(mHtmlString);
|
||||
}
|
||||
rv = transferable->GetTransferData(kHTMLContext, getter_AddRefs(data), &dataSize);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
data->GetData(mContextString);
|
||||
}
|
||||
rv = transferable->GetTransferData(kHTMLInfo, getter_AddRefs(data), &dataSize);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
data->GetData(mInfoString);
|
||||
}
|
||||
rv = transferable->GetTransferData(kUnicodeMime, getter_AddRefs(data), &dataSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv); // require plain text at a minimum
|
||||
data->GetData(mTitleString);
|
||||
}
|
||||
|
||||
// default text value is the URL
|
||||
|
@ -694,8 +723,8 @@ DragDataProducer::Produce(nsDOMDataTransfer* aDataTransfer,
|
|||
|
||||
// if there is no drag node, which will be the case for a selection, just
|
||||
// use the selection target node.
|
||||
nsresult rv = AddStringsToDataTransfer(
|
||||
dragNode ? dragNode : mSelectionTargetNode.get(), aDataTransfer);
|
||||
rv = AddStringsToDataTransfer(
|
||||
dragNode ? dragNode : mSelectionTargetNode.get(), aDataTransfer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_IF_ADDREF(*aDragNode = dragNode);
|
||||
|
@ -982,52 +1011,3 @@ DragDataProducer::GetSelectedLink(nsISelection* inSelection,
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
DragDataProducer::SerializeNodeOrSelection(nsIDOMWindow* inWindow,
|
||||
nsIContent* inNode,
|
||||
nsAString& outResultString,
|
||||
nsAString& outContext,
|
||||
nsAString& outInfo)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(inWindow);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDocumentEncoder> encoder =
|
||||
do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
inWindow->GetDocument(getter_AddRefs(domDoc));
|
||||
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
|
||||
|
||||
PRUint32 flags = nsIDocumentEncoder::OutputAbsoluteLinks |
|
||||
nsIDocumentEncoder::OutputEncodeHTMLEntities |
|
||||
nsIDocumentEncoder::OutputRaw;
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(inNode);
|
||||
if (node) {
|
||||
// make a range around this node
|
||||
rv = NS_NewRange(getter_AddRefs(range));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = range->SelectNode(node);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
inWindow->GetSelection(getter_AddRefs(selection));
|
||||
flags |= nsIDocumentEncoder::OutputSelectionOnly;
|
||||
}
|
||||
|
||||
rv = encoder->Init(domDoc, NS_LITERAL_STRING(kHTMLMime), flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (range) {
|
||||
encoder->SetRange(range);
|
||||
} else if (selection) {
|
||||
encoder->SetSelection(selection);
|
||||
}
|
||||
|
||||
return encoder->EncodeToStringWithContext(outContext, outInfo,
|
||||
outResultString);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Kathleen Brade <brade@netscape.com>
|
||||
* David Gardiner <david.gardiner@unisa.edu.au>
|
||||
* Mats Palmgren <matpal@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -134,7 +135,9 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
|
|||
// we want preformatted for the case where the selection is inside input/textarea
|
||||
// and we don't want pretty printing for others cases, to not have additionnal
|
||||
// line breaks which are then converted into spaces by the htmlConverter (see bug #524975)
|
||||
PRUint32 flags = nsIDocumentEncoder::OutputPreformatted | nsIDocumentEncoder::OutputRaw;
|
||||
PRUint32 flags = nsIDocumentEncoder::OutputPreformatted
|
||||
| nsIDocumentEncoder::OutputRaw
|
||||
| nsIDocumentEncoder::SkipInvisibleContent;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
|
||||
NS_ASSERTION(domDoc, "Need a document");
|
||||
|
@ -175,7 +178,7 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
|
|||
|
||||
mimeType.AssignLiteral(kHTMLMime);
|
||||
|
||||
flags = 0;
|
||||
flags = nsIDocumentEncoder::SkipInvisibleContent;
|
||||
|
||||
rv = docEncoder->Init(domDoc, mimeType, flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -420,7 +423,7 @@ nsCopySupport::GetContents(const nsACString& aMimeType, PRUint32 aFlags, nsISele
|
|||
docEncoder = do_CreateInstance(encoderContractID.get());
|
||||
NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
|
||||
|
||||
PRUint32 flags = aFlags;
|
||||
PRUint32 flags = aFlags | nsIDocumentEncoder::SkipInvisibleContent;
|
||||
|
||||
if (aMimeType.Equals("text/plain"))
|
||||
flags |= nsIDocumentEncoder::OutputPreformatted;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Mats Palmgren <matpal@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -50,7 +51,6 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContentSerializer.h"
|
||||
#include "nsIUnicodeEncoder.h"
|
||||
|
@ -69,11 +69,13 @@
|
|||
#include "nsGkAtoms.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "nsIParserService.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "nsITransferable.h" // for kUnicodeMime
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
@ -119,6 +121,29 @@ protected:
|
|||
|
||||
nsresult FlushText(nsAString& aString, PRBool aForce);
|
||||
|
||||
PRBool IsVisibleNode(nsINode* aNode)
|
||||
{
|
||||
NS_PRECONDITION(aNode, "");
|
||||
|
||||
if (mFlags & SkipInvisibleContent) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
|
||||
if (content) {
|
||||
nsIFrame* frame = content->GetPrimaryFrame();
|
||||
if (!frame) {
|
||||
if (aNode->IsNodeOfType(nsINode::eTEXT)) {
|
||||
// We have already checked that our parent is visible.
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
PRBool isVisible = frame->GetStyleVisibility()->IsVisible();
|
||||
if (!isVisible && aNode->IsNodeOfType(nsINode::eTEXT))
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool IsTag(nsIContent* aContent, nsIAtom* aAtom);
|
||||
|
||||
virtual PRBool IncludeInContext(nsINode *aNode);
|
||||
|
@ -269,8 +294,9 @@ nsDocumentEncoder::SerializeNodeStart(nsINode* aNode,
|
|||
nsAString& aStr,
|
||||
nsINode* aOriginalNode)
|
||||
{
|
||||
PRUint16 type;
|
||||
|
||||
if (!IsVisibleNode(aNode))
|
||||
return NS_OK;
|
||||
|
||||
nsINode* node = nsnull;
|
||||
nsCOMPtr<nsINode> fixedNodeKungfuDeathGrip;
|
||||
|
||||
|
@ -292,6 +318,7 @@ nsDocumentEncoder::SerializeNodeStart(nsINode* aNode,
|
|||
if (!node)
|
||||
node = aNode;
|
||||
|
||||
PRUint16 type;
|
||||
node->GetNodeType(&type);
|
||||
switch (type) {
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
|
@ -341,6 +368,9 @@ nsresult
|
|||
nsDocumentEncoder::SerializeNodeEnd(nsINode* aNode,
|
||||
nsAString& aStr)
|
||||
{
|
||||
if (!IsVisibleNode(aNode))
|
||||
return NS_OK;
|
||||
|
||||
if (aNode->IsElement()) {
|
||||
mSerializer->AppendElementEnd(static_cast<nsIContent*>(aNode), aStr);
|
||||
}
|
||||
|
@ -352,6 +382,9 @@ nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
|
|||
nsAString& aStr,
|
||||
PRBool aDontSerializeRoot)
|
||||
{
|
||||
if (!IsVisibleNode(aNode))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
PRBool serializeClonedChildren = PR_FALSE;
|
||||
nsINode* maybeFixedNode = nsnull;
|
||||
|
@ -656,19 +689,24 @@ nsDocumentEncoder::SerializeRangeNodes(nsIRange* aRange,
|
|||
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
|
||||
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv=NS_OK;
|
||||
|
||||
if (!IsVisibleNode(aNode))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// get start and end nodes for this recursion level
|
||||
nsCOMPtr<nsIContent> startNode, endNode;
|
||||
PRInt32 start = mStartRootIndex - aDepth;
|
||||
if (start >= 0 && (PRUint32)start <= mStartNodes.Length())
|
||||
startNode = mStartNodes[start];
|
||||
{
|
||||
PRInt32 start = mStartRootIndex - aDepth;
|
||||
if (start >= 0 && (PRUint32)start <= mStartNodes.Length())
|
||||
startNode = mStartNodes[start];
|
||||
|
||||
PRInt32 end = mEndRootIndex - aDepth;
|
||||
if (end >= 0 && (PRUint32)end <= mEndNodes.Length())
|
||||
endNode = mEndNodes[end];
|
||||
PRInt32 end = mEndRootIndex - aDepth;
|
||||
if (end >= 0 && (PRUint32)end <= mEndNodes.Length())
|
||||
endNode = mEndNodes[end];
|
||||
}
|
||||
|
||||
if ((startNode != content) && (endNode != content))
|
||||
if (startNode != content && endNode != content)
|
||||
{
|
||||
// node is completely contained in range. Serialize the whole subtree
|
||||
// rooted by this node.
|
||||
|
@ -858,6 +896,16 @@ nsDocumentEncoder::SerializeRangeToString(nsIRange *aRange,
|
|||
|
||||
if ((startParent == endParent) && IsTextNode(startParent))
|
||||
{
|
||||
if (mFlags & SkipInvisibleContent) {
|
||||
// Check that the parent is visible if we don't a frame.
|
||||
// IsVisibleNode() will do it when there's a frame.
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(startParent);
|
||||
if (content && !content->GetPrimaryFrame()) {
|
||||
nsIContent* parent = content->GetParent();
|
||||
if (!parent || !IsVisibleNode(parent))
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
rv = SerializeNodeStart(startParent, startOffset, endOffset, aOutputString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
@ -1080,7 +1128,7 @@ nsHTMLCopyEncoder::~nsHTMLCopyEncoder()
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCopyEncoder::Init(nsIDOMDocument* aDocument,
|
||||
const nsAString& aMimetype,
|
||||
const nsAString& aMimeType,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
if (!aDocument)
|
||||
|
@ -1094,7 +1142,7 @@ nsHTMLCopyEncoder::Init(nsIDOMDocument* aDocument,
|
|||
NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
|
||||
|
||||
mMimeType.AssignLiteral("text/html");
|
||||
|
||||
|
||||
// Make all links absolute when copying
|
||||
// (see related bugs #57296, #41924, #58646, #32768)
|
||||
mFlags = aFlags | OutputAbsoluteLinks;
|
||||
|
|
|
@ -30,89 +30,155 @@ function testCopyPaste () {
|
|||
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
|
||||
.getService(Components.interfaces.nsIClipboard);
|
||||
|
||||
var transferable, node;
|
||||
var data = {};
|
||||
var textarea = document.getElementById('input');
|
||||
|
||||
// ============ copy paste test from a simple text content to a textarea
|
||||
function copySelectionToClipboard() {
|
||||
documentViewer.copySelection();
|
||||
is(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), true);
|
||||
is(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), true);
|
||||
}
|
||||
function copyToClipboard(node) {
|
||||
textarea.blur();
|
||||
clipboard.emptyClipboard(1);
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
var r = document.createRange();
|
||||
r.selectNode(node);
|
||||
window.getSelection().addRange(r);
|
||||
copySelectionToClipboard();
|
||||
}
|
||||
function copyRangeToClipboard(startNode,startIndex,endNode,endIndex) {
|
||||
textarea.blur();
|
||||
clipboard.emptyClipboard(1);
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
var r = document.createRange();
|
||||
r.setStart(startNode,startIndex)
|
||||
r.setEnd(endNode,endIndex)
|
||||
window.getSelection().addRange(r);
|
||||
copySelectionToClipboard();
|
||||
}
|
||||
function copyChildrenToClipboard(id) {
|
||||
textarea.blur();
|
||||
clipboard.emptyClipboard(1);
|
||||
window.getSelection().selectAllChildren(document.getElementById(id));
|
||||
copySelectionToClipboard();
|
||||
}
|
||||
function getClipboardData(mime) {
|
||||
var transferable = Components.classes['@mozilla.org/widget/transferable;1']
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
transferable.addDataFlavor(mime);
|
||||
clipboard.getData(transferable, 1);
|
||||
var data = {};
|
||||
transferable.getTransferData(mime, data, {}) ;
|
||||
return data;
|
||||
}
|
||||
function testClipboardValue(mime, expected) {
|
||||
var data = getClipboardData(mime);
|
||||
is (data.value == null ? data.value :
|
||||
data.value.QueryInterface(Components.interfaces.nsISupportsString).data,
|
||||
expected,
|
||||
mime + " value in the clipboard");
|
||||
return data.value;
|
||||
}
|
||||
function testPasteText(expected) {
|
||||
textarea.value="";
|
||||
textarea.focus();
|
||||
textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement)
|
||||
.editor.paste(1);
|
||||
is(textarea.value, expected, "value of the textarea after the paste");
|
||||
}
|
||||
function testSelectionToString(expected) {
|
||||
is(window.getSelection().toString().replace(/\r\n/g,"\n"), expected, "Selection.toString");
|
||||
}
|
||||
function testInnerHTML(id, expected) {
|
||||
var value = document.getElementById(id).innerHTML;
|
||||
is(value, expected, id + ".innerHTML");
|
||||
}
|
||||
function testEmptyChildren(id) {
|
||||
copyChildrenToClipboard(id);
|
||||
testSelectionToString("");
|
||||
testClipboardValue("text/unicode", null);
|
||||
testClipboardValue("text/html", null);
|
||||
testPasteText("");
|
||||
}
|
||||
|
||||
// selection of the node
|
||||
node = document.getElementById('draggable');
|
||||
window.getSelection().selectAllChildren(node);
|
||||
copyChildrenToClipboard("draggable");
|
||||
testSelectionToString("This is a draggable bit of text.");
|
||||
testClipboardValue("text/unicode",
|
||||
"This is a draggable bit of text.");
|
||||
testClipboardValue("text/html",
|
||||
"<div id=\"draggable\" title=\"title to have a long HTML line\">This is a <em>draggable</em> bit of text.</div>");
|
||||
testPasteText("This is a draggable bit of text.");
|
||||
|
||||
// let's copy the selection
|
||||
documentViewer.copySelection();
|
||||
copyChildrenToClipboard("alist");
|
||||
testSelectionToString("bla\n\n * foo\n * bar\n\n");
|
||||
testClipboardValue("text/unicode", " bla\n\n * foo\n * bar\n\n");
|
||||
testClipboardValue("text/html", "<div id=\"alist\">\n bla\n <ul>\n <li>foo</li>\n \n <li>bar</li>\n </ul>\n </div>");
|
||||
testPasteText(" bla\n\n * foo\n * bar\n\n");
|
||||
|
||||
is(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), true);
|
||||
is(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), true);
|
||||
copyChildrenToClipboard("div4");
|
||||
testSelectionToString("Tt t t ");
|
||||
testClipboardValue("text/unicode", " Tt t t ");
|
||||
testClipboardValue("text/html", "<div id=\"div4\">\n T<textarea>t t t</textarea>\n</div>");
|
||||
testInnerHTML("div4", "\n T<textarea>t t t</textarea>\n");
|
||||
testPasteText(" Tt t t ");
|
||||
|
||||
// is the clipboard contain a text/unicode data ?
|
||||
transferable = Components.classes['@mozilla.org/widget/transferable;1']
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
transferable.addDataFlavor("text/unicode");
|
||||
clipboard.getData(transferable, 1);
|
||||
copyChildrenToClipboard("div5");
|
||||
testSelectionToString("T ");
|
||||
testClipboardValue("text/unicode", " T ");
|
||||
testClipboardValue("text/html", "<div id=\"div5\">\n T<textarea> </textarea>\n</div>");
|
||||
testInnerHTML("div5", "\n T<textarea> </textarea>\n");
|
||||
testPasteText(" T ");
|
||||
|
||||
transferable.getTransferData ("text/unicode", data, {} ) ;
|
||||
is (data.value.QueryInterface(Components.interfaces.nsISupportsString).data,
|
||||
"This is a draggable bit of text.",
|
||||
"text/unicode value in the clipboard");
|
||||
|
||||
// is the clipboard contain a text/html data ?
|
||||
transferable = Components.classes['@mozilla.org/widget/transferable;1']
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
transferable.addDataFlavor("text/html");
|
||||
clipboard.getData(transferable, 1);
|
||||
copyRangeToClipboard($("div6").childNodes[0],0, $("div6").childNodes[1],1);
|
||||
testSelectionToString("");
|
||||
// START Disabled due to bug 564688
|
||||
if (false) {
|
||||
testClipboardValue("text/unicode", "");
|
||||
testClipboardValue("text/html", "");
|
||||
}
|
||||
// END Disabled due to bug 564688
|
||||
testInnerHTML("div6", "div6");
|
||||
|
||||
transferable.getTransferData ("text/html", data, {} ) ;
|
||||
is (data.value.QueryInterface(Components.interfaces.nsISupportsString).data,
|
||||
"<div id=\"draggable\" title=\"title to have a long HTML line\">This is a <em>draggable</em> bit of text.</div>",
|
||||
"text/html value in the clipboard");
|
||||
|
||||
// let's paste now in the textarea and verify its content
|
||||
textarea.focus();
|
||||
textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement)
|
||||
.editor.paste(1);
|
||||
is(textarea.value, "This is a draggable bit of text.", "value of the textarea after the paste");
|
||||
copyRangeToClipboard($("div7").childNodes[0],0, $("div7").childNodes[0],4);
|
||||
testSelectionToString("");
|
||||
// START Disabled due to bug 564688
|
||||
if (false) {
|
||||
testClipboardValue("text/unicode", "");
|
||||
testClipboardValue("text/html", "");
|
||||
}
|
||||
// END Disabled due to bug 564688
|
||||
testInnerHTML("div7", "div7");
|
||||
|
||||
copyRangeToClipboard($("div8").childNodes[0],0, $("div8").childNodes[0],4);
|
||||
testSelectionToString("");
|
||||
// START Disabled due to bug 564688
|
||||
if (false) {
|
||||
testClipboardValue("text/unicode", "");
|
||||
testClipboardValue("text/html", "");
|
||||
}
|
||||
// END Disabled due to bug 564688
|
||||
testInnerHTML("div8", "div8");
|
||||
|
||||
// ============ copy paste test from a piece of HTML to a textarea
|
||||
textarea.blur();
|
||||
node = document.getElementById('alist');
|
||||
window.getSelection().selectAllChildren(node);
|
||||
documentViewer.copySelection();
|
||||
copyRangeToClipboard($("div9").childNodes[0],0, $("div9").childNodes[0],4);
|
||||
testSelectionToString("div9");
|
||||
testClipboardValue("text/unicode", "div9");
|
||||
testClipboardValue("text/html", "div9");
|
||||
testInnerHTML("div9", "div9");
|
||||
|
||||
is(clipboard.hasDataMatchingFlavors(["text/unicode"], 1,1), true);
|
||||
is(clipboard.hasDataMatchingFlavors(["text/html"], 1,1), true);
|
||||
copyToClipboard($("div10"));
|
||||
testSelectionToString("");
|
||||
testInnerHTML("div10", "div10");
|
||||
|
||||
// let's verify the clipboard content for the text/unicode flavor
|
||||
transferable = Components.classes['@mozilla.org/widget/transferable;1']
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
transferable.addDataFlavor("text/unicode");
|
||||
clipboard.getData(transferable, 1);
|
||||
data = {};
|
||||
transferable.getTransferData ("text/unicode", data, {} ) ;
|
||||
is (data.value.QueryInterface(Components.interfaces.nsISupportsString).data,
|
||||
" bla\n\n * foo\n * bar\n\n",
|
||||
"text/unicode value in the clipboard (html piece)");
|
||||
copyToClipboard($("div10").firstChild);
|
||||
testSelectionToString("");
|
||||
|
||||
// let's verify the clipboard content for the text/html flavor
|
||||
transferable = Components.classes['@mozilla.org/widget/transferable;1']
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
transferable.addDataFlavor("text/html");
|
||||
clipboard.getData(transferable, 1);
|
||||
data = {};
|
||||
transferable.getTransferData ("text/html", data, {} ) ;
|
||||
is (data.value.QueryInterface(Components.interfaces.nsISupportsString).data,
|
||||
"<div id=\"alist\">\n bla\n <ul>\n <li>foo</li>\n <li>bar</li>\n </ul>\n </div>",
|
||||
"text/html value in the clipboard (html piece)");
|
||||
|
||||
// let's paste now in the textarea and verify its content
|
||||
textarea.value="";
|
||||
textarea.focus();
|
||||
textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement)
|
||||
.editor.paste(1);
|
||||
is(textarea.value, " bla\n\n * foo\n * bar\n\n", "value of the textarea after the paste (html piece)");
|
||||
|
||||
copyRangeToClipboard($("div10").childNodes[0],0, $("div10").childNodes[0],1);
|
||||
testSelectionToString("");
|
||||
|
||||
copyRangeToClipboard($("div10").childNodes[1],0, $("div10").childNodes[1],1);
|
||||
testSelectionToString("");
|
||||
|
||||
// ============ copy/paste test from/to a textarea
|
||||
|
||||
|
@ -145,10 +211,37 @@ addLoadEvent(testCopyPaste);
|
|||
bla
|
||||
<ul>
|
||||
<li>foo</li>
|
||||
<li style="display: none;">baz</li>
|
||||
<li>bar</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="div4">
|
||||
T<textarea>t t t</textarea>
|
||||
</div>
|
||||
|
||||
<div id="div5">
|
||||
T<textarea> </textarea>
|
||||
</div>
|
||||
|
||||
<div id="div6" style="display:none"></div>
|
||||
<script>
|
||||
var x = $("div6")
|
||||
x.appendChild(document.createTextNode('di'))
|
||||
x.appendChild(document.createTextNode('v6'))
|
||||
</script>
|
||||
|
||||
<div id="div7" style="display:none">div7</div>
|
||||
<div id="div8" style="visibility:hidden">div8</div>
|
||||
<div style="visibility:hidden"><div id="div9" style="visibility:visible">div9</div></div>
|
||||
<div style="visibility:hidden"><div><div><div id="div10"></div></div></div></div>
|
||||
<script>
|
||||
var x = $("div10")
|
||||
x.appendChild(document.createTextNode('div'))
|
||||
x.appendChild(document.createTextNode('10'))
|
||||
</script>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1301,7 +1301,9 @@ nsFrameSelection::MoveCaret(PRUint32 aKeycode,
|
|||
NS_IMETHODIMP
|
||||
nsTypedSelection::ToString(PRUnichar **aReturn)
|
||||
{
|
||||
return ToStringWithFormat("text/plain", 0, 0, aReturn);
|
||||
return ToStringWithFormat("text/plain",
|
||||
nsIDocumentEncoder::SkipInvisibleContent,
|
||||
0, aReturn);
|
||||
}
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче