зеркало из https://github.com/mozilla/gecko-dev.git
Bug 551704 - Part 3: Don't copy invisible BR nodes to the clipboard for editable elements, to make us more compatible with WebKit and Opera; r=bzbarsky a=blocking-betaN+
This commit is contained in:
Родитель
aaa5654ff3
Коммит
45318ab728
|
@ -68,6 +68,10 @@
|
||||||
#include "nsLWBrkCIID.h"
|
#include "nsLWBrkCIID.h"
|
||||||
#include "nsIScriptElement.h"
|
#include "nsIScriptElement.h"
|
||||||
#include "nsAttrName.h"
|
#include "nsAttrName.h"
|
||||||
|
#include "nsIDocShell.h"
|
||||||
|
#include "nsIEditorDocShell.h"
|
||||||
|
#include "nsIEditor.h"
|
||||||
|
#include "nsIHTMLEditor.h"
|
||||||
|
|
||||||
static const PRInt32 kLongLineLen = 128;
|
static const PRInt32 kLongLineLen = 128;
|
||||||
|
|
||||||
|
@ -81,6 +85,40 @@ nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer)
|
||||||
return CallQueryInterface(it, aSerializer);
|
return CallQueryInterface(it, aSerializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PRBool
|
||||||
|
IsInvisibleBreak(nsIContent *aNode, nsIAtom *aTag) {
|
||||||
|
// xxxehsan: we should probably figure out a way to determine
|
||||||
|
// if a BR node is visible without using the editor.
|
||||||
|
if (aTag != nsGkAtoms::br || !aNode->IsEditable()) {
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the editor associated with the document
|
||||||
|
nsIDocument *doc = aNode->GetCurrentDoc();
|
||||||
|
if (doc) {
|
||||||
|
nsPIDOMWindow *window = doc->GetWindow();
|
||||||
|
if (window) {
|
||||||
|
nsIDocShell *docShell = window->GetDocShell();
|
||||||
|
if (docShell) {
|
||||||
|
nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell);
|
||||||
|
if (editorDocShell) {
|
||||||
|
nsCOMPtr<nsIEditor> editor;
|
||||||
|
editorDocShell->GetEditor(getter_AddRefs(editor));
|
||||||
|
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
|
||||||
|
if (htmlEditor) {
|
||||||
|
PRBool isVisible = PR_FALSE;
|
||||||
|
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);
|
||||||
|
htmlEditor->BreakIsVisible(domNode, &isVisible);
|
||||||
|
return !isVisible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
nsHTMLContentSerializer::nsHTMLContentSerializer()
|
nsHTMLContentSerializer::nsHTMLContentSerializer()
|
||||||
{
|
{
|
||||||
mIsHTMLSerializer = PR_TRUE;
|
mIsHTMLSerializer = PR_TRUE;
|
||||||
|
@ -204,6 +242,12 @@ nsHTMLContentSerializer::AppendElementStart(nsIContent *aElement,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIAtom *name = content->Tag();
|
nsIAtom *name = content->Tag();
|
||||||
|
|
||||||
|
if ((mFlags & nsIDocumentEncoder::OutputPreformatted) &&
|
||||||
|
IsInvisibleBreak(content, name)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
PRBool lineBreakBeforeOpen = LineBreakBeforeOpen(content->GetNameSpaceID(), name);
|
PRBool lineBreakBeforeOpen = LineBreakBeforeOpen(content->GetNameSpaceID(), name);
|
||||||
|
|
||||||
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
|
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
|
||||||
|
|
|
@ -51,7 +51,7 @@ interface nsIContentFilter;
|
||||||
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_EDITOR, 1)
|
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_EDITOR, 1)
|
||||||
|
|
||||||
%}
|
%}
|
||||||
[scriptable, uuid(afc36593-5787-4420-93d9-b2c0ccbf0cad)]
|
[scriptable, uuid(c964b8b0-e9e8-11df-9492-0800200c9a66)]
|
||||||
|
|
||||||
interface nsIHTMLEditor : nsISupports
|
interface nsIHTMLEditor : nsISupports
|
||||||
{
|
{
|
||||||
|
@ -608,5 +608,10 @@ interface nsIHTMLEditor : nsISupports
|
||||||
* @return true if CR in a paragraph creates a new paragraph
|
* @return true if CR in a paragraph creates a new paragraph
|
||||||
*/
|
*/
|
||||||
attribute boolean returnInParagraphCreatesNewParagraph;
|
attribute boolean returnInParagraphCreatesNewParagraph;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a BR node is visible to the user.
|
||||||
|
*/
|
||||||
|
boolean breakIsVisible(in nsIDOMNode aNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1342,6 +1342,16 @@ PRBool nsHTMLEditor::IsVisBreak(nsIDOMNode *aNode)
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsHTMLEditor::BreakIsVisible(nsIDOMNode *aNode, PRBool *aIsVisible)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aNode && aIsVisible);
|
||||||
|
|
||||||
|
*aIsVisible = IsVisBreak(aNode);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsHTMLEditor::GetIsDocumentEditable(PRBool *aIsDocumentEditable)
|
nsHTMLEditor::GetIsDocumentEditable(PRBool *aIsDocumentEditable)
|
||||||
|
|
|
@ -15,17 +15,90 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=551704
|
||||||
<p id="display"></p>
|
<p id="display"></p>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<div id="preformatted" style="white-space: pre" contenteditable>a b</div>
|
<div id="preformatted" style="white-space: pre" contenteditable>a b</div>
|
||||||
|
<div id="test1" contenteditable><br></div>
|
||||||
|
<div id="test2" contenteditable>a<br></div>
|
||||||
|
<div id="test3" contenteditable style="white-space: pre"><br></div>
|
||||||
|
<div id="test4" contenteditable style="white-space: pre">a<br></div>
|
||||||
|
<div id="test5" contenteditable></div>
|
||||||
|
<div id="test6" contenteditable>a</div>
|
||||||
|
<div id="test7" contenteditable style="white-space: pre"></div>
|
||||||
|
<div id="test8" contenteditable style="white-space: pre">a</div>
|
||||||
</div>
|
</div>
|
||||||
<pre id="test">
|
<pre id="test">
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function testLineBreak(div, type, expectedText, expectedHTML, callback)
|
||||||
|
{
|
||||||
|
div.focus();
|
||||||
|
getSelection().collapse(div, 0);
|
||||||
|
type();
|
||||||
|
is(div.innerHTML, expectedHTML, "The expected HTML after editing should be correct");
|
||||||
|
SimpleTest.waitForClipboard(expectedText,
|
||||||
|
function() {
|
||||||
|
getSelection().selectAllChildren(div);
|
||||||
|
synthesizeKey("C", {accelKey: true});
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
var t = document.createElement("textarea");
|
||||||
|
document.body.appendChild(t);
|
||||||
|
t.focus();
|
||||||
|
synthesizeKey("V", {accelKey: true});
|
||||||
|
is(t.value, expectedText, "The expected text should be copied to the clipboard");
|
||||||
|
callback();
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeABCDEF() {
|
||||||
|
synthesizeKey("a", {});
|
||||||
|
typeBCDEF_chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeBCDEF() {
|
||||||
|
synthesizeKey("VK_RIGHT", {});
|
||||||
|
typeBCDEF_chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeBCDEF_chars() {
|
||||||
|
synthesizeKey("b", {});
|
||||||
|
synthesizeKey("c", {});
|
||||||
|
synthesizeKey("VK_ENTER", {});
|
||||||
|
synthesizeKey("d", {});
|
||||||
|
synthesizeKey("e", {});
|
||||||
|
synthesizeKey("f", {});
|
||||||
|
}
|
||||||
|
|
||||||
/** Test for Bug 551704 **/
|
/** Test for Bug 551704 **/
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
addLoadEvent(function() {
|
SimpleTest.waitForFocus(function() {
|
||||||
var preformatted = document.getElementById("preformatted");
|
var preformatted = document.getElementById("preformatted");
|
||||||
is(preformatted.innerHTML, "a\nb", "No BR node should be injected for preformatted editable fields");
|
is(preformatted.innerHTML, "a\nb", "No BR node should be injected for preformatted editable fields");
|
||||||
|
|
||||||
SimpleTest.finish();
|
var divs = [];
|
||||||
|
for (var i = 0; i < 8; ++i) {
|
||||||
|
divs[i] = document.getElementById("test" + (i+1));
|
||||||
|
}
|
||||||
|
var current = 0;
|
||||||
|
function doNextTest() {
|
||||||
|
if (current == divs.length) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var div = divs[current++];
|
||||||
|
if (div.textContent == "a") {
|
||||||
|
var type = typeBCDEF;
|
||||||
|
} else {
|
||||||
|
var type = typeABCDEF;
|
||||||
|
}
|
||||||
|
var expectedHTML = "abc<br>def<br>";
|
||||||
|
var expectedText = "abc\ndef";
|
||||||
|
testLineBreak(div, type, expectedText, expectedHTML, doNextTest);
|
||||||
|
}
|
||||||
|
|
||||||
|
doNextTest();
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче