зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1726064 - part 4: Make `HTMLEditor::HandleKeyPressEvent()` use `HTMLEditUtils::GetInclusiveAncestorElement()` r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D122942
This commit is contained in:
Родитель
c7cfba7954
Коммит
ffacdefc1d
|
@ -226,7 +226,7 @@ bool HTMLEditUtils::IsListItem(const nsINode* aNode) {
|
|||
/**
|
||||
* IsAnyTableElement() returns true if aNode is an html table, td, tr, ...
|
||||
*/
|
||||
bool HTMLEditUtils::IsAnyTableElement(nsINode* aNode) {
|
||||
bool HTMLEditUtils::IsAnyTableElement(const nsINode* aNode) {
|
||||
MOZ_ASSERT(aNode);
|
||||
return aNode->IsAnyOfHTMLElements(
|
||||
nsGkAtoms::table, nsGkAtoms::tr, nsGkAtoms::td, nsGkAtoms::th,
|
||||
|
|
|
@ -138,7 +138,7 @@ class HTMLEditUtils final {
|
|||
static bool IsListItem(const nsINode* aNode);
|
||||
static bool IsTable(nsINode* aNode);
|
||||
static bool IsTableRow(nsINode* aNode);
|
||||
static bool IsAnyTableElement(nsINode* aNode);
|
||||
static bool IsAnyTableElement(const nsINode* aNode);
|
||||
static bool IsAnyTableElementButNotTable(nsINode* aNode);
|
||||
static bool IsTableCell(const nsINode* aNode);
|
||||
static bool IsTableCellOrCaption(nsINode& aNode);
|
||||
|
|
|
@ -1031,14 +1031,16 @@ nsresult HTMLEditor::HandleKeyPressEvent(WidgetKeyboardEvent* aKeyboardEvent) {
|
|||
break;
|
||||
}
|
||||
|
||||
Element* blockParent = HTMLEditUtils::GetInclusiveAncestorBlockElement(
|
||||
*startContainer->AsContent());
|
||||
if (!blockParent) {
|
||||
const Element* editableBlockElement =
|
||||
HTMLEditUtils::GetInclusiveAncestorElement(
|
||||
*startContainer->AsContent(),
|
||||
HTMLEditUtils::ClosestEditableBlockElement);
|
||||
if (!editableBlockElement) {
|
||||
break;
|
||||
}
|
||||
|
||||
// If selection is in a table element, we need special handling.
|
||||
if (HTMLEditUtils::IsAnyTableElement(blockParent)) {
|
||||
if (HTMLEditUtils::IsAnyTableElement(editableBlockElement)) {
|
||||
EditActionResult result = HandleTabKeyPressInTable(aKeyboardEvent);
|
||||
if (result.Failed()) {
|
||||
NS_WARNING("HTMLEditor::HandleTabKeyPressInTable() failed");
|
||||
|
@ -1055,7 +1057,7 @@ nsresult HTMLEditor::HandleKeyPressEvent(WidgetKeyboardEvent* aKeyboardEvent) {
|
|||
}
|
||||
|
||||
// If selection is in an list item element, treat it as indent or outdent.
|
||||
if (HTMLEditUtils::IsListItem(blockParent)) {
|
||||
if (HTMLEditUtils::IsListItem(editableBlockElement)) {
|
||||
aKeyboardEvent->PreventDefault();
|
||||
if (!aKeyboardEvent->IsShift()) {
|
||||
nsresult rv = IndentAsAction();
|
||||
|
|
|
@ -239,6 +239,7 @@ skip-if = os != 'mac' # bug 574005
|
|||
[test_dragdrop.html]
|
||||
skip-if = os == 'android'
|
||||
[test_handle_new_lines.html]
|
||||
[test_htmleditor_tab_key_handling.html]
|
||||
[test_initial_selection_and_caret_of_designMode.html]
|
||||
[test_inline_style_cache.html]
|
||||
[test_inlineTableEditing.html]
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Testing indentation with `Tab` key</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(() => {
|
||||
function initEditor(aEditingHostTag) {
|
||||
const editor = document.createElement(aEditingHostTag);
|
||||
editor.setAttribute("contenteditable", "true");
|
||||
document.body.insertBefore(editor, document.body.firstChild);
|
||||
editor.getBoundingClientRect();
|
||||
const htmlEditor = SpecialPowers.wrap(window).docShell.editingSession.getEditorForWindow(window);
|
||||
htmlEditor.flags &= ~SpecialPowers.Ci.nsIEditor.eEditorAllowInteraction;
|
||||
return editor;
|
||||
}
|
||||
|
||||
(function test_tab_in_paragraph() {
|
||||
const editor = initEditor("div");
|
||||
editor.innerHTML = "<p>abc</p><p>def</p>";
|
||||
editor.getBoundingClientRect();
|
||||
editor.focus();
|
||||
getSelection().collapse(editor.querySelector("p").firstChild, 1);
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(
|
||||
editor.innerHTML.replace(/ /g, " "),
|
||||
`<p>a bc</p><p>def</p>`,
|
||||
"4 white-spaces should be inserted into the paragraph by Tab"
|
||||
);
|
||||
|
||||
let blurred = false;
|
||||
editor.addEventListener("blur", () => {
|
||||
blurred = true;
|
||||
}, {once: true});
|
||||
synthesizeKey("KEY_Tab", {shiftKey: true});
|
||||
is(
|
||||
editor.innerHTML.replace(/ /g, " "),
|
||||
`<p>a bc</p><p>def</p>`,
|
||||
"The spaces in the paragraph shouldn't be removed by Shift-Tab"
|
||||
);
|
||||
ok(blurred, "Shift-Tab should cause moving focus");
|
||||
editor.remove();
|
||||
})();
|
||||
|
||||
(function test_tab_in_body_text() {
|
||||
const editor = initEditor("div");
|
||||
editor.innerHTML = "abc";
|
||||
editor.getBoundingClientRect();
|
||||
editor.focus();
|
||||
getSelection().collapse(editor.firstChild, 1);
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(
|
||||
editor.innerHTML.replace(/ /g, " "),
|
||||
`a bc`,
|
||||
"4 white-spaces should be inserted into the body text by Tab"
|
||||
);
|
||||
editor.remove();
|
||||
})();
|
||||
|
||||
(function test_tab_in_li() {
|
||||
const editor = initEditor("div");
|
||||
for (const list of ["ol", "ul"]) {
|
||||
editor.innerHTML = `abc<${list}><li>def</li><li>ghi</li><li>jkl</li></${list}>`;
|
||||
editor.getBoundingClientRect();
|
||||
editor.focus();
|
||||
getSelection().collapse(editor.querySelector("li + li").firstChild, 1);
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(
|
||||
editor.innerHTML,
|
||||
`abc<${list}><li>def</li><${list}><li>ghi</li></${list}><li>jkl</li></${list}>`,
|
||||
`The list item containing caret should be moved into new sub-<${list}> by Tab`
|
||||
);
|
||||
synthesizeKey("KEY_Tab", {shiftKey: true});
|
||||
is(
|
||||
editor.innerHTML,
|
||||
`abc<${list}><li>def</li><li>ghi</li><li>jkl</li></${list}>`,
|
||||
`The list item containing caret should be moved into parent <${list}> by Shift-Tab`
|
||||
);
|
||||
}
|
||||
editor.remove();
|
||||
})();
|
||||
|
||||
(function test_tab_in_nested_editing_host_in_li() {
|
||||
const editor = initEditor("div");
|
||||
editor.innerHTML = `abc<ul><li>def</li><li><span contenteditable="false">g<span contenteditable="true">h</span>i</span></li><li>jkl</li></ul>`;
|
||||
editor.getBoundingClientRect();
|
||||
editor.focus();
|
||||
getSelection().collapse(editor.querySelector("span[contenteditable=true]").firstChild, 1);
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(
|
||||
editor.innerHTML,
|
||||
`abc<ul><li>def</li><li><span contenteditable="false">g<span contenteditable="true">h</span>i</span></li><li>jkl</li></ul>`,
|
||||
`The list item containing caret should be modified by Tab`
|
||||
);
|
||||
editor.remove();
|
||||
})();
|
||||
|
||||
// TODO: Add table cell cases.
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче