зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1540037 - part 19: Make `IsEmpty()` be a virtual method of `EditorBase` and implement `nsIEditor::GetDocumentIsEmpty()` in `EditorBase` r=m_kato
Currently, `EditorBase::GetDocumentIsEmpty()` is implemented by `TextEditor`, and it refers only `IsEmpty()` which is implemented both by `TextEditor` and `HTMLEditor`. So, `IsEmpty()` should be a virtual method of `EditorBase`, then, `EditorBase` can implement `GetDocumentIsEmpty()`. Depends on D115786 Differential Revision: https://phabricator.services.mozilla.com/D115787
This commit is contained in:
Родитель
ae69b73075
Коммит
95c41d54c3
|
@ -1069,7 +1069,9 @@ NS_IMETHODIMP EditorBase::SetShouldTxnSetSelection(bool aShould) {
|
|||
}
|
||||
|
||||
NS_IMETHODIMP EditorBase::GetDocumentIsEmpty(bool* aDocumentIsEmpty) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
MOZ_ASSERT(aDocumentIsEmpty);
|
||||
*aDocumentIsEmpty = IsEmpty();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX: The rule system should tell us which node to select all on (ie, the
|
||||
|
|
|
@ -578,6 +578,13 @@ class EditorBase : public nsIEditor,
|
|||
*/
|
||||
bool IsInEditSubAction() const { return mIsInEditSubAction; }
|
||||
|
||||
/**
|
||||
* IsEmpty() checks whether the editor is empty. If editor has only padding
|
||||
* <br> element for empty editor, returns true. If editor's root element has
|
||||
* non-empty text nodes or other nodes like <br>, returns false.
|
||||
*/
|
||||
virtual bool IsEmpty() const = 0;
|
||||
|
||||
/**
|
||||
* SuppressDispatchingInputEvent() suppresses or unsuppresses dispatching
|
||||
* "input" event.
|
||||
|
|
|
@ -151,13 +151,7 @@ class HTMLEditor final : public TextEditor,
|
|||
MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD BeginningOfDocument() override;
|
||||
MOZ_CAN_RUN_SCRIPT NS_IMETHOD SetFlags(uint32_t aFlags) override;
|
||||
|
||||
/**
|
||||
* IsEmpty() checks whether the editor is empty. If editor has only padding
|
||||
* <br> element for empty editor, returns true. If editor's root element has
|
||||
* non-empty text nodes or other nodes like <br>, returns false even if there
|
||||
* are only empty blocks.
|
||||
*/
|
||||
virtual bool IsEmpty() const override;
|
||||
bool IsEmpty() const final;
|
||||
|
||||
virtual bool CanPaste(int32_t aClipboardType) const override;
|
||||
using EditorBase::CanPaste;
|
||||
|
|
|
@ -532,12 +532,6 @@ bool TextEditor::IsEmpty() const {
|
|||
!anonymousDivElement->GetFirstChild()->Length();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP TextEditor::GetDocumentIsEmpty(bool* aDocumentIsEmpty) {
|
||||
MOZ_ASSERT(aDocumentIsEmpty);
|
||||
*aDocumentIsEmpty = IsEmpty();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP TextEditor::GetTextLength(int32_t* aCount) {
|
||||
MOZ_ASSERT(aCount);
|
||||
|
||||
|
|
|
@ -56,8 +56,6 @@ class TextEditor : public EditorBase, public nsITimerCallback, public nsINamed {
|
|||
NS_DECL_NSINAMED
|
||||
|
||||
// Overrides of nsIEditor
|
||||
NS_IMETHOD GetDocumentIsEmpty(bool* aDocumentIsEmpty) override;
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT NS_IMETHOD
|
||||
SetDocumentCharacterSet(const nsACString& characterSet) override;
|
||||
|
||||
|
@ -163,12 +161,7 @@ class TextEditor : public EditorBase, public nsITimerCallback, public nsINamed {
|
|||
uint32_t aFlags,
|
||||
const nsAString& aValue) override;
|
||||
|
||||
/**
|
||||
* IsEmpty() checks whether the editor is empty. If editor has only padding
|
||||
* <br> element for empty editor, returns true. If editor's root element has
|
||||
* non-empty text nodes or other nodes like <br>, returns false.
|
||||
*/
|
||||
virtual bool IsEmpty() const;
|
||||
bool IsEmpty() const override;
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT virtual nsresult HandleKeyPressEvent(
|
||||
WidgetKeyboardEvent* aKeyboardEvent) override;
|
||||
|
|
|
@ -266,6 +266,7 @@ skip-if = os == 'android'
|
|||
[test_middle_click_paste.html]
|
||||
skip-if = headless
|
||||
[test_nsIEditor_beginningOfDocument.html]
|
||||
[test_nsIEditor_documentIsEmpty.html]
|
||||
[test_nsIEditor_insertLineBreak.html]
|
||||
[test_nsIEditor_isSelectionEditable.html]
|
||||
[test_nsIEditorMailSupport_insertAsCitedQuotation.html]
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests of nsIEditor#documentIsEmpty</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(() => {
|
||||
const originalBody = document.body.innerHTML;
|
||||
|
||||
(function test_with_text_editor() {
|
||||
for (const test of [
|
||||
{
|
||||
tag: "input",
|
||||
innerHTML: '<input><input value="abc"><input placeholder="abc">',
|
||||
},
|
||||
{
|
||||
tag: "textarea",
|
||||
innerHTML: '<textarea></textarea><textarea>abc</textarea><textarea placeholder="abc"></textarea>',
|
||||
},
|
||||
]) {
|
||||
document.body.innerHTML = test.innerHTML;
|
||||
let textControl = document.body.querySelector(test.tag);
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, true,
|
||||
`nsIEditor.documentIsEmpty should be true if value of <${test.tag}> is empty by default`);
|
||||
textControl.focus();
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, true,
|
||||
`nsIEditor.documentIsEmpty should be true if value of <${test.tag}> is empty by default after getting focus`);
|
||||
textControl.value = "abc";
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, false,
|
||||
`nsIEditor.documentIsEmpty should be false if <${test.tag}>.value is set to non-empty string`);
|
||||
textControl.value = "";
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, true,
|
||||
`nsIEditor.documentIsEmpty should be true if <${test.tag}>.value is set to empty string`);
|
||||
|
||||
textControl = textControl.nextSibling;
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, false,
|
||||
`nsIEditor.documentIsEmpty should be false if value of <${test.tag}> is non-empty by default`);
|
||||
textControl.focus();
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, false,
|
||||
`nsIEditor.documentIsEmpty should be false if value of <${test.tag}> is non-empty by default after getting focus`);
|
||||
textControl.value = "def";
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, false,
|
||||
`nsIEditor.documentIsEmpty should be false if <${test.tag}>.value is set to different non-empty string`);
|
||||
textControl.value = "";
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, true,
|
||||
`nsIEditor.documentIsEmpty should be true if <${test.tag}>.value is set to empty string from non-empty string`);
|
||||
|
||||
textControl = textControl.nextSibling;
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, true,
|
||||
`nsIEditor.documentIsEmpty should be true if value of <${test.tag}> is empty by default (placeholder isn't empty)`);
|
||||
textControl.focus();
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, true,
|
||||
`nsIEditor.documentIsEmpty should be true if value of <${test.tag}> is empty by default after getting focus (placeholder isn't empty)`);
|
||||
textControl.value = "abc";
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, false,
|
||||
`nsIEditor.documentIsEmpty should be false if <${test.tag}>.value is set to non-empty string (placeholder isn't empty)`);
|
||||
textControl.value = "";
|
||||
is(SpecialPowers.wrap(textControl).editor.documentIsEmpty, true,
|
||||
`nsIEditor.documentIsEmpty should be true if <${test.tag}>.value is set to empty string (placeholder isn't empty)`);
|
||||
}
|
||||
})();
|
||||
|
||||
function getHTMLEditor() {
|
||||
const editingSession = SpecialPowers.wrap(window).docShell.editingSession;
|
||||
if (!editingSession) {
|
||||
return null;
|
||||
}
|
||||
return editingSession.getEditorForWindow(window);
|
||||
}
|
||||
|
||||
(function test_with_contenteditable() {
|
||||
document.body.innerHTML = "<div contenteditable></div>";
|
||||
try {
|
||||
getHTMLEditor().documentIsEmpty;
|
||||
todo(false, "nsIEditor.documentIsEmpty should throw an exception when no editing host has focus");
|
||||
} catch (e) {
|
||||
ok(true, "nsIEditor.documentIsEmpty should throw an exception when no editing host has focus");
|
||||
}
|
||||
document.querySelector("div[contenteditable]").focus();
|
||||
todo_is(getHTMLEditor().documentIsEmpty, true,
|
||||
"nsIEditor.documentIsEmpty should be true when editing host does not have contents");
|
||||
|
||||
document.body.innerHTML = "<div contenteditable><br></div>";
|
||||
document.querySelector("div[contenteditable]").focus();
|
||||
is(getHTMLEditor().documentIsEmpty, false,
|
||||
"nsIEditor.documentIsEmpty should be false when editing host has only a <br> element");
|
||||
|
||||
document.body.innerHTML = "<div contenteditable><p><br></p></div>";
|
||||
document.querySelector("div[contenteditable]").focus();
|
||||
is(getHTMLEditor().documentIsEmpty, false,
|
||||
"nsIEditor.documentIsEmpty should be false when editing host has only an empty paragraph");
|
||||
|
||||
document.body.innerHTML = "<div contenteditable><p>abc</p></div>";
|
||||
document.querySelector("div[contenteditable]").focus();
|
||||
is(getHTMLEditor().documentIsEmpty, false,
|
||||
"nsIEditor.documentIsEmpty should be false when editing host has text in a paragraph");
|
||||
|
||||
document.body.innerHTML = "<div contenteditable>abc</div>";
|
||||
document.querySelector("div[contenteditable]").focus();
|
||||
is(getHTMLEditor().documentIsEmpty, false,
|
||||
"nsIEditor.documentIsEmpty should be false when editing host has text directly");
|
||||
|
||||
document.execCommand("selectall");
|
||||
document.execCommand("delete");
|
||||
todo_is(getHTMLEditor().documentIsEmpty, true,
|
||||
"nsIEditor.documentIsEmpty should be true when all contents in editing host are deleted");
|
||||
})();
|
||||
|
||||
document.designMode = "on";
|
||||
(function test_with_designMode() {
|
||||
document.body.innerHTML = "";
|
||||
is(getHTMLEditor().documentIsEmpty, true,
|
||||
"nsIEditor.documentIsEmpty should be true when <body> is empty in designMode");
|
||||
document.body.focus();
|
||||
is(getHTMLEditor().documentIsEmpty, true,
|
||||
"nsIEditor.documentIsEmpty should be true when <body> is empty in designMode (after setting focus explicitly)");
|
||||
|
||||
document.body.innerHTML = "<div><br></div>";
|
||||
is(getHTMLEditor().documentIsEmpty, false,
|
||||
"nsIEditor.documentIsEmpty should be false when <body> has only an empty paragraph in designMode");
|
||||
|
||||
document.body.innerHTML = "<div>abc</div>";
|
||||
is(getHTMLEditor().documentIsEmpty, false,
|
||||
"nsIEditor.documentIsEmpty should be false when <body> has text in a paragraph in designMode");
|
||||
|
||||
document.body.innerHTML = "abc";
|
||||
is(getHTMLEditor().documentIsEmpty, false,
|
||||
"nsIEditor.documentIsEmpty should be false when <body> has text directly in designMode");
|
||||
|
||||
document.execCommand("selectall");
|
||||
document.execCommand("delete");
|
||||
todo_is(getHTMLEditor().documentIsEmpty, true,
|
||||
"nsIEditor.documentIsEmpty should be true when all contents in designMode are deleted");
|
||||
})();
|
||||
document.designMode = "off";
|
||||
|
||||
document.body.innerHTML = originalBody;
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче