mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 442186 - execCommand justify* fails on first line of contenteditable; r=ehsan
Given the way GetPromotedPoint / IsNodeInActiveEditor are designed, when the selection is in the first child element of the active editing host the selection is extended outside of editor node. As a result, `GetNodesFromSelection' (which is called at the beginning of `WillAlign') returns two nodes: 1. an empty text node, which is enclosed in a <div style="text-align: ***">; 2. the first child element, which is destroyed when it's a <div>; Proposed solution: #1 can be avoided by checking that the node is editable in `WillAlign'; #2 can be avoided by not dropping <div> blocks in `RemoveAlignment'. This is an opportunity to simplify `RemoveAlignment' a bit.
This commit is contained in:
parent
feedccf03c
commit
d46ef85530
@ -4724,6 +4724,10 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
||||
{
|
||||
// here's where we actually figure out what to do
|
||||
nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i];
|
||||
|
||||
// Ignore all non-editable nodes. Leave them be.
|
||||
if (!mHTMLEditor->IsEditable(curNode)) continue;
|
||||
|
||||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
@ -8704,7 +8708,23 @@ nsHTMLEditRules::RemoveAlignment(nsIDOMNode * aNode, const nsAString & aAlignTyp
|
||||
res = mHTMLEditor->NodeIsBlockStatic(child, &isBlock);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
if ((isBlock && !nsHTMLEditUtils::IsDiv(child)) || nsHTMLEditUtils::IsHR(child))
|
||||
if (nsEditor::NodeIsType(child, nsEditProperty::center))
|
||||
{
|
||||
// the current node is a CENTER element
|
||||
// first remove children's alignment
|
||||
res = RemoveAlignment(child, aAlignType, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// we may have to insert BRs in first and last position of element's children
|
||||
// if the nodes before/after are not blocks and not BRs
|
||||
res = MakeSureElemStartsOrEndsOnCR(child);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// now remove the CENTER container
|
||||
res = mHTMLEditor->RemoveContainer(child);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
else if (isBlock || nsHTMLEditUtils::IsHR(child))
|
||||
{
|
||||
// the current node is a block element
|
||||
nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(child);
|
||||
@ -8734,47 +8754,6 @@ nsHTMLEditRules::RemoveAlignment(nsIDOMNode * aNode, const nsAString & aAlignTyp
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
}
|
||||
else if (nsEditor::NodeIsType(child, nsEditProperty::center)
|
||||
|| nsHTMLEditUtils::IsDiv(child))
|
||||
{
|
||||
// this is a CENTER or a DIV element and we have to remove it
|
||||
// first remove children's alignment
|
||||
res = RemoveAlignment(child, aAlignType, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
if (useCSS && nsHTMLEditUtils::IsDiv(child))
|
||||
{
|
||||
// if we are in CSS mode and if the element is a DIV, let's remove it
|
||||
// if it does not carry any style hint (style attr, class or ID)
|
||||
nsAutoString dummyCssValue;
|
||||
res = mHTMLEditor->mHTMLCSSUtils->RemoveCSSInlineStyle(child, nsEditProperty::cssTextAlign, dummyCssValue);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsCOMPtr<nsIDOMElement> childElt = do_QueryInterface(child);
|
||||
PRBool hasStyleOrIdOrClass;
|
||||
res = mHTMLEditor->HasStyleOrIdOrClass(childElt, &hasStyleOrIdOrClass);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
if (!hasStyleOrIdOrClass)
|
||||
{
|
||||
// we may have to insert BRs in first and last position of DIV's children
|
||||
// if the nodes before/after are not blocks and not BRs
|
||||
res = MakeSureElemStartsOrEndsOnCR(child);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
res = mHTMLEditor->RemoveContainer(child);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we may have to insert BRs in first and last position of element's children
|
||||
// if the nodes before/after are not blocks and not BRs
|
||||
res = MakeSureElemStartsOrEndsOnCR(child);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// in HTML mode, let's remove the element
|
||||
res = mHTMLEditor->RemoveContainer(child);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
}
|
||||
child = tmp;
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -57,6 +57,7 @@ _TEST_FILES = \
|
||||
test_bug417418.html \
|
||||
test_bug432225.html \
|
||||
test_bug439808.html \
|
||||
test_bug442186.html \
|
||||
test_bug449243.html \
|
||||
test_bug455992.html \
|
||||
test_bug456244.html \
|
||||
|
102
editor/libeditor/html/tests/test_bug442186.html
Normal file
102
editor/libeditor/html/tests/test_bug442186.html
Normal file
@ -0,0 +1,102 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=442186
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 442186</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=442186">Mozilla Bug 442186</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<h2> two <div> containers </h2>
|
||||
<section contenteditable id="test1">
|
||||
<div> First paragraph with some text. </div>
|
||||
<div> Second paragraph with some text. </div>
|
||||
</section>
|
||||
|
||||
<h2> two paragraphs </h2>
|
||||
<section contenteditable id="test2">
|
||||
<p> First paragraph with some text. </p>
|
||||
<p> Second paragraph with some text. </p>
|
||||
</section>
|
||||
|
||||
<h2> one text node, one paragraph </h2>
|
||||
<section contenteditable id="test3">
|
||||
First paragraph with some text.
|
||||
<p> Second paragraph with some text. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 442186 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
function justify(textNode, pos) {
|
||||
if (!pos) pos = 10;
|
||||
|
||||
// put the caret on the requested character
|
||||
var range = document.createRange();
|
||||
var sel = window.getSelection();
|
||||
range.setStart(textNode, pos);
|
||||
range.setEnd(textNode, pos);
|
||||
sel.addRange(range);
|
||||
|
||||
// align
|
||||
document.execCommand("justifyright", false, null);
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
const test1 = document.getElementById("test1");
|
||||
const test2 = document.getElementById("test2");
|
||||
const test3 = document.getElementById("test3");
|
||||
|
||||
// #test1: two <div> containers
|
||||
const line1 = test1.querySelector("div").firstChild;
|
||||
test1.focus();
|
||||
justify(line1);
|
||||
is(test1.querySelectorAll("*").length, 2,
|
||||
"Aligning the first child should not create nor remove any element.");
|
||||
is(line1.parentNode.nodeName.toLowerCase(), "div",
|
||||
"Aligning the first <div> should not modify its node type.");
|
||||
is(line1.parentNode.style.textAlign, "right",
|
||||
"Aligning the first <div> should set a 'text-align: right' style rule.");
|
||||
|
||||
// #test2: two paragraphs
|
||||
const line2 = test2.querySelector("p").firstChild;
|
||||
test2.focus();
|
||||
justify(line2);
|
||||
is(test2.querySelectorAll("*").length, 2,
|
||||
"Aligning the first child should not create nor remove any element.");
|
||||
is(line2.parentNode.nodeName.toLowerCase(), "p",
|
||||
"Aligning the first paragraph should not modify its node type.");
|
||||
is(line2.parentNode.style.textAlign, "right",
|
||||
"Aligning the first paragraph should set a 'text-align: right' style rule.");
|
||||
|
||||
// #test3: one text node, two paragraphs
|
||||
const line3 = test3.firstChild;
|
||||
test3.focus();
|
||||
justify(line3);
|
||||
is(test3.querySelectorAll("*").length, 2,
|
||||
"Aligning the first child should create a block element.");
|
||||
is(line3.parentNode.nodeName.toLowerCase(), "div",
|
||||
"Aligning the first child should create a block element.");
|
||||
is(line3.parentNode.style.textAlign, "right",
|
||||
"Aligning the first line should set a 'text-align: right' style rule.");
|
||||
|
||||
// done
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user