mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1258085 - Avoid empty whitespace nodes when editing
There are probably a lot more places that could use HandleEmptyText thrown in, but this covers a few simple ones.
This commit is contained in:
parent
b58b91c974
commit
d2127d6d42
@ -2030,6 +2030,9 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
||||
DeprecatedAbs(eo - so));
|
||||
*aHandled = true;
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
DeleteNodeIfCollapsedText(nodeAsText);
|
||||
|
||||
res = InsertBRIfNeeded(aSelection);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
@ -2471,6 +2474,18 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We might have left only collapsed whitespace in the start/end nodes
|
||||
{
|
||||
nsAutoTrackDOMPoint startTracker(mHTMLEditor->mRangeUpdater,
|
||||
address_of(startNode), &startOffset);
|
||||
nsAutoTrackDOMPoint endTracker(mHTMLEditor->mRangeUpdater,
|
||||
address_of(endNode), &endOffset);
|
||||
|
||||
DeleteNodeIfCollapsedText(*startNode);
|
||||
DeleteNodeIfCollapsedText(*endNode);
|
||||
}
|
||||
|
||||
// If we're joining blocks: if deleting forward the selection should be
|
||||
// collapsed to the end of the selection, if deleting backward the selection
|
||||
// should be collapsed to the beginning of the selection. But if we're not
|
||||
@ -2488,6 +2503,28 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* If aNode is a text node that contains only collapsed whitespace, delete it.
|
||||
* It doesn't serve any useful purpose, and we don't want it to confuse code
|
||||
* that doesn't correctly skip over it.
|
||||
*
|
||||
* If deleting the node fails (like if it's not editable), the caller should
|
||||
* proceed as usual, so don't return any errors.
|
||||
*/
|
||||
void
|
||||
nsHTMLEditRules::DeleteNodeIfCollapsedText(nsINode& aNode)
|
||||
{
|
||||
if (!aNode.GetAsText()) {
|
||||
return;
|
||||
}
|
||||
bool empty;
|
||||
nsresult res = mHTMLEditor->IsVisTextNode(aNode.AsContent(), &empty, false);
|
||||
NS_ENSURE_SUCCESS_VOID(res);
|
||||
if (empty) {
|
||||
mHTMLEditor->DeleteNode(&aNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************************
|
||||
* InsertBRIfNeeded: determines if a br is needed for current selection to not be spastic.
|
||||
|
@ -106,6 +106,7 @@ public:
|
||||
NS_IMETHOD DidDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength, nsresult aResult) override;
|
||||
NS_IMETHOD WillDeleteSelection(nsISelection *aSelection) override;
|
||||
NS_IMETHOD DidDeleteSelection(nsISelection *aSelection) override;
|
||||
void DeleteNodeIfCollapsedText(nsINode& aNode);
|
||||
|
||||
protected:
|
||||
virtual ~nsHTMLEditRules();
|
||||
|
@ -168,3 +168,4 @@ skip-if = toolkit == 'android'
|
||||
skip-if = toolkit == 'android' # chrome urls not available due to packaging
|
||||
[test_bug1247483.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug1258085.html]
|
||||
|
66
editor/libeditor/tests/test_bug1258085.html
Normal file
66
editor/libeditor/tests/test_bug1258085.html
Normal file
@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<title>Test for Bug 1186799</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<div contenteditable></div>
|
||||
<script>
|
||||
var div = document.querySelector("div");
|
||||
|
||||
function reset() {
|
||||
div.innerHTML = "x<br> y";
|
||||
div.focus();
|
||||
synthesizeKey("VK_DOWN", {});
|
||||
}
|
||||
|
||||
function checks(msg) {
|
||||
is(div.innerHTML, "x<br><br>",
|
||||
msg + ": Should add a second <br> to prevent collapse of first");
|
||||
is(div.childNodes.length, 3, msg + ": No empty text nodes allowed");
|
||||
ok(getSelection().isCollapsed, msg + ": Selection must be collapsed");
|
||||
is(getSelection().focusNode, div, msg + ": Focus must be in div");
|
||||
is(getSelection().focusOffset, 2,
|
||||
msg + ": Focus must be between the two <br>s");
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
// Put selection after the "y" and backspace
|
||||
reset();
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
checks("Collapsed backspace");
|
||||
|
||||
// Now do the same with delete
|
||||
reset();
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
checks("Collapsed delete");
|
||||
|
||||
// Forward selection
|
||||
reset();
|
||||
synthesizeKey("VK_RIGHT", {shiftKey: true});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
checks("Forward-selected backspace");
|
||||
|
||||
// Backward selection
|
||||
reset();
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_LEFT", {shiftKey: true});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
checks("Backward-selected backspace");
|
||||
|
||||
// Make sure we're not deleting if the whitespace isn't actually collapsed
|
||||
div.style.whiteSpace = "pre-wrap";
|
||||
reset();
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
if (div.innerHTML, "x<br> ", "pre-wrap: Don't delete uncollapsed space");
|
||||
ok(getSelection().isCollapsed, "pre-wrap: Selection must be collapsed");
|
||||
is(getSelection().focusNode, div.lastChild,
|
||||
"pre-wrap: Focus must be in final text node");
|
||||
is(getSelection().focusOffset, 1, "pre-wrap: Focus must be at end of node");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
@ -138,7 +138,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=772796
|
||||
/* Last not least, some simple edge case tests. */
|
||||
/*70*/[ "<div>test</div><pre>foobar\n</pre>baz", "<div>testfoobar\n</div>baz" ],
|
||||
/*71*/[ "<div>test</div><pre>\nfoo\nbar</pre>", "<div>testfoo\n</div><pre>bar</pre>" ],
|
||||
/*72*/[ "<div>test</div><pre>\n\nfoo\nbar</pre>", "<div>test\n</div><pre>foo\nbar</pre>" ],
|
||||
/*72*/[ "<div>test</div><pre>\n\nfoo\nbar</pre>", "<div>test</div><pre>foo\nbar</pre>", "<div>test\n</div><pre>foo\nbar</pre>" ],
|
||||
];
|
||||
|
||||
/** Test for Bug 772796 **/
|
||||
|
Loading…
Reference in New Issue
Block a user