mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
Bug 1422234 - part 1: HTMLEditRules::ReturnInParagraph() should adjust split point if caret position is positioned at edge of anchor element r=m_kato
When Enter key is pressed at start or end of <a href="foo"> element, we shouldn't split it (in other words, we shouldn't create empty <a href="foo"> element in new paragraph) because users must not want to keep editing *same* link in new paragraph in most cases. This patch adjusts HTMLEditRules::ReturnInParagraph() selection start point locally when it gets selection. If caret is at start of an <a href="foo"> element, moves caret to before the element. If caret is at end of an <a href="foo"> element, moves to after the element. MozReview-Commit-ID: 3L3eDzc6Dk --HG-- extra : rebase_source : dfb22486d2709e84ef7ec1eee3a9bfdef11cbe99
This commit is contained in:
parent
7f8c5cae44
commit
dc245c4fee
@ -14,6 +14,7 @@
|
||||
#include "mozilla/dom/Text.h"
|
||||
#include "nsAtom.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsINode.h"
|
||||
@ -399,6 +400,26 @@ public:
|
||||
mIsChildInitialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* SetAfter() sets mChild to next sibling of aChild.
|
||||
*/
|
||||
void
|
||||
SetAfter(const nsINode* aChild)
|
||||
{
|
||||
MOZ_ASSERT(aChild);
|
||||
nsIContent* nextSibling = aChild->GetNextSibling();
|
||||
if (nextSibling) {
|
||||
Set(nextSibling);
|
||||
return;
|
||||
}
|
||||
nsINode* parentNode = aChild->GetParentNode();
|
||||
if (NS_WARN_IF(!parentNode)) {
|
||||
Clear();
|
||||
return;
|
||||
}
|
||||
SetToEndOf(parentNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear() makes the instance not point anywhere.
|
||||
*/
|
||||
@ -586,6 +607,23 @@ public:
|
||||
return mOffset.value() == mParent->Length();
|
||||
}
|
||||
|
||||
bool
|
||||
IsBRElementAtEndOfContainer() const
|
||||
{
|
||||
if (NS_WARN_IF(!mParent)) {
|
||||
return false;
|
||||
}
|
||||
if (!mParent->IsContainerNode()) {
|
||||
return false;
|
||||
}
|
||||
const_cast<SelfType*>(this)->EnsureChild();
|
||||
if (!mChild ||
|
||||
mChild->GetNextSibling()) {
|
||||
return false;
|
||||
}
|
||||
return mChild->IsHTMLElement(nsGkAtoms::br);
|
||||
}
|
||||
|
||||
// Convenience methods for switching between the two types
|
||||
// of EditorDOMPointBase.
|
||||
EditorDOMPointBase<nsINode*, nsIContent*>
|
||||
|
@ -6883,6 +6883,71 @@ HTMLEditRules::ReturnInParagraph(Selection& aSelection,
|
||||
}
|
||||
MOZ_ASSERT(atStartOfSelection.IsSetAndValid());
|
||||
|
||||
// We shouldn't create new anchor element which has non-empty href unless
|
||||
// splitting middle of it because we assume that users don't want to create
|
||||
// *same* anchor element across two or more paragraphs in most cases.
|
||||
// So, adjust selection start if it's edge of anchor element(s).
|
||||
// XXX We don't support whitespace collapsing in these cases since it needs
|
||||
// some additional work with WSRunObject but it's not usual case.
|
||||
// E.g., |<a href="foo"><b>foo []</b> </a>|
|
||||
if (atStartOfSelection.IsStartOfContainer()) {
|
||||
for (nsIContent* container = atStartOfSelection.GetContainerAsContent();
|
||||
container && container != &aParentDivOrP;
|
||||
container = container->GetParent()) {
|
||||
if (HTMLEditUtils::IsLink(container)) {
|
||||
// Found link should be only in right node. So, we shouldn't split it.
|
||||
atStartOfSelection.Set(container);
|
||||
// Even if we found an anchor element, don't break because DOM API
|
||||
// allows to nest anchor elements.
|
||||
}
|
||||
// If the container is middle of its parent, stop adjusting split point.
|
||||
if (container->GetPreviousSibling()) {
|
||||
// XXX Should we check if previous sibling is visible content?
|
||||
// E.g., should we ignore comment node, invisible <br> element?
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// We also need to check if selection is at invisible <br> element at end
|
||||
// of an <a href="foo"> element because editor inserts a <br> element when
|
||||
// user types Enter key after a whitespace which is at middle of
|
||||
// <a href="foo"> element and when setting selection at end of the element,
|
||||
// selection becomes referring the <br> element. We may need to change this
|
||||
// behavior later if it'd be standardized.
|
||||
else if (atStartOfSelection.IsEndOfContainer() ||
|
||||
atStartOfSelection.IsBRElementAtEndOfContainer()) {
|
||||
// If there are 2 <br> elements, the first <br> element is visible. E.g.,
|
||||
// |<a href="foo"><b>boo[]<br></b><br></a>|, we should split the <a>
|
||||
// element. Otherwise, E.g., |<a href="foo"><b>boo[]<br></b></a>|,
|
||||
// we should not split the <a> element and ignore inline elements in it.
|
||||
bool foundBRElement = atStartOfSelection.IsBRElementAtEndOfContainer();
|
||||
for (nsIContent* container = atStartOfSelection.GetContainerAsContent();
|
||||
container && container != &aParentDivOrP;
|
||||
container = container->GetParent()) {
|
||||
if (HTMLEditUtils::IsLink(container)) {
|
||||
// Found link should be only in left node. So, we shouldn't split it.
|
||||
atStartOfSelection.SetAfter(container);
|
||||
// Even if we found an anchor element, don't break because DOM API
|
||||
// allows to nest anchor elements.
|
||||
}
|
||||
// If the container is middle of its parent, stop adjusting split point.
|
||||
if (nsIContent* nextSibling = container->GetNextSibling()) {
|
||||
if (foundBRElement) {
|
||||
// If we've already found a <br> element, we assume found node is
|
||||
// visible <br> or something other node.
|
||||
// XXX Should we check if non-text data node like comment?
|
||||
break;
|
||||
}
|
||||
|
||||
// XXX Should we check if non-text data node like comment?
|
||||
if (!nextSibling->IsHTMLElement(nsGkAtoms::br)) {
|
||||
break;
|
||||
}
|
||||
foundBRElement = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool doesCRCreateNewP = htmlEditor->GetReturnInParagraphCreatesNewParagraph();
|
||||
|
||||
bool splitAfterNewBR = false;
|
||||
|
@ -120,12 +120,6 @@
|
||||
[[["stylewithcss","false"\],["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<p><b id=x class=y>foo[\]bar</b></p>" compare innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "foo<a href=foo>[\]bar</a>" compare innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "foo<a href=foo>[\]bar</a>" compare innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
[[["defaultparagraphseparator","div"\],["insertparagraph",""\]\] "<p>foo[\]<!--bar-->" compare innerHTML]
|
||||
expected: FAIL
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user