Bug 1499430 - Make PresShell::PageMove() use result of nsFrameSelection::GetFrameToPageSelect() when PresShell::GetScrollableFrameToScroll() returns nullptr r=smaug

If there is no scrollable frame, PresShell::GetScrollableFrameToScroll() returns
nullptr.  However, even when we don't expand selection, we need to move caret
in current selection root.  Therefore, it should call
nsFrameSelection::CommonPageMove() with the result of
nsFrameSelection::GetFrameToPageSelect() to move caret.

Differential Revision: https://phabricator.services.mozilla.com/D16020

--HG--
rename : layout/base/tests/test_expanding_selection_per_page.html => layout/base/tests/test_moving_and_expanding_selection_per_page.html
extra : moz-landing-system : lando
This commit is contained in:
Masayuki Nakano 2019-01-10 05:02:56 +00:00
parent e708455671
commit 95635bbb30
4 changed files with 365 additions and 317 deletions

View File

@ -2266,14 +2266,16 @@ PresShell::IntraLineMove(bool aForward, bool aExtend) {
NS_IMETHODIMP
PresShell::PageMove(bool aForward, bool aExtend) {
nsIFrame* frame;
nsIFrame* frame = nullptr;
if (!aExtend) {
frame = do_QueryFrame(GetScrollableFrameToScroll(nsIPresShell::eVertical));
} else {
frame = mSelection->GetFrameToPageSelect();
// If there is no scrollable frame, get the frame to move caret instead.
}
if (!frame) {
return NS_OK;
frame = mSelection->GetFrameToPageSelect();
if (!frame) {
return NS_OK;
}
}
RefPtr<nsFrameSelection> frameSelection = mSelection;
frameSelection->CommonPageMove(aForward, aExtend, frame);

View File

@ -151,8 +151,6 @@ skip-if = e10s # bug 1020135, nested oop iframes not supported
support-files = bug921928_event_target_iframe_apps_oop.html
[test_event_target_radius.html]
skip-if = toolkit == 'android' # Bug 1355836
[test_expanding_selection_per_page.html]
support-files = window_empty_document.html
[test_flush_on_paint.html]
skip-if = true # Bug 688128
[test_frame_reconstruction_for_pseudo_elements.html]
@ -163,6 +161,8 @@ support-files =
file_getBoxQuads_convertPointRectQuad_frame1.html
file_getBoxQuads_convertPointRectQuad_frame2.html
[test_getClientRects_emptytext.html]
[test_moving_and_expanding_selection_per_page.html]
support-files = window_empty_document.html
[test_mozPaintCount.html]
skip-if = toolkit == 'android' # android: Requires plugin support
[test_preserve3d_sorting_hit_testing.html]

View File

@ -1,311 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Test for expanding selection per page</title>
<script type="text/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>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(() => {
open("window_empty_document.html", "_blank", "width=500,height=500");
});
async function doTests(aWindow) {
const IS_WIN = navigator.platform.includes("Win");
// On macOS and Linux, Shift + PageUp/PageDown requires native event to
// resolve default action of PageDown and PageUp. Although macOS widget has
// nsIWidget::AttachNativeKeyEvent(), we cannot use synthesizeKey() for the
// following tests. So, use nsISelectionController.pageMove() instead on
// non-Windows platforms.
const kUseKeyboardEvent = IS_WIN;
let selectionController;
if (!kUseKeyboardEvent) {
selectionController = SpecialPowers.wrap(aWindow)
.docShell
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
.getInterface(SpecialPowers.Ci.nsISelectionDisplay)
.QueryInterface(SpecialPowers.Ci.nsISelectionController);
}
// On Windows, per-page selection to start or end expands selection to same
// column of first or last line. On the other platforms, it expands selection
// to start or end of first or last line.
const kSelectToStartOrEnd = !IS_WIN;
await SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false]]});
await SimpleTest.promiseFocus(aWindow);
function getNodeDescription(aNode) {
function getElementDescription(aElement) {
if (aElement.getAttribute("id") !== null) {
return `${aElement.tagName.toLowerCase()}#${aElement.getAttribute("id")}`;
}
if (aElement.tagName === "BR") {
return `${getElementDescription(aElement.previousSibling)} + br`;
}
return aElement.tagName.toLowerCase();
}
switch (aNode.nodeType) {
case aNode.TEXT_NODE:
return `text node in ${getElementDescription(aNode.parentElement)}`;
case aNode.ELEMENT_NODE:
return getElementDescription(aNode);
default:
return "unknown node";
}
}
function doSelectPageDown() {
if (kUseKeyboardEvent) {
synthesizeKey("KEY_PageDown", {shiftKey: true}, aWindow);
} else {
selectionController.pageMove(true, true);
}
}
function doSelectPageUp() {
if (kUseKeyboardEvent) {
synthesizeKey("KEY_PageUp", {shiftKey: true}, aWindow);
} else {
selectionController.pageMove(false, true);
}
}
let doc = aWindow.document;
let body = doc.body;
let selection = doc.getSelection();
let container;
body.innerHTML = '<span id="s1">first line</span><br>' +
'<span id="s2">second line</span><br>' +
'<span id="s3">last line</span>';
container = doc.documentElement;
let description = "Expanding selection to forward in non-scrollable body: ";
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s1").firstChild, 3);
doSelectPageDown();
is(container.scrollTop, 0, description + "this test shouldn't create scrollable document");
let range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s1").firstChild,
`${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
is(range.startOffset, 3,
`${description} selection should be expanded from the first line's 3rd insertion point`);
is(range.endContainer, doc.getElementById("s3").firstChild,
`${description} selection should be expanded into the last line (got: ${getNodeDescription(range.endContainer)})`);
if (kSelectToStartOrEnd) {
is(range.endOffset, range.endContainer.length,
`${description} selection should be expanded to end of the last line`);
} else {
isfuzzy(range.endOffset, 3, 2,
`${description} selection should be expanded to around the last line's 3rd insertion point`);
}
description = "Expanding selection to backward in non-scrollable body: ";
selection.collapse(doc.getElementById("s3").firstChild, 3);
doSelectPageUp();
is(container.scrollTop, 0, description + "this test shouldn't create scrollable document");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s1").firstChild,
`${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
if (kSelectToStartOrEnd) {
is(range.startOffset, 0,
`${description} selection should be expanded to start of the first line`);
} else {
isfuzzy(range.startOffset, 3, 2,
`${description} selection should be expanded to around the first line's 3rd insertion point`);
}
is(range.endContainer, doc.getElementById("s3").firstChild,
`${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
is(range.endOffset, 3,
`${description} selection should be expanded from the last line's 3rd insertion point`);
body.innerHTML = '<span id="s1">first line in the body</span>' +
'<div id="d1" style="height: 2em; line-height: 1em; overflow: auto;">' +
'<span id="s2">first line</span><br>' +
'<span id="s3">second line</span><br>' +
'<span id="s4">third line</span><br>' +
'<span id="s5">last line</span>' +
"</div>" +
'<span id="s6">last line in the body</span>';
container = doc.getElementById("d1");
description = "Expanding selection to forward in scrollable area in the body: ";
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s2").firstChild, 3);
doSelectPageDown();
isnot(container.scrollTop, 0, description + "should be scrolled down");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
is(range.startOffset, 3,
`${description} selection should be expanded from the first line's 3rd insertion point`);
is(range.endContainer, doc.getElementById("s4").firstChild,
`${description} selection should be expanded into the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
isfuzzy(range.endOffset, 3, 2,
`${description} selection should be expanded to around the 3rd line's 3rd insertion point`);
description = "Expanding selection to backward in scrollable area in the body: ";
selection.collapse(doc.getElementById("s4").firstChild, 3);
let previousScrollTop = container.scrollTop;
doSelectPageUp();
ok(container.scrollTop < previousScrollTop, description + "should be scrolled up");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
isfuzzy(range.startOffset, 3, 2,
`${description} selection should be expanded to around the first line's 3rd insertion point`);
is(range.endContainer, doc.getElementById("s4").firstChild,
`${description} selection should be expanded from the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
is(range.endOffset, 3,
`${description} selection should be expanded from the 3rd line's 3rd insertion point`);
body.innerHTML = '<span id="s1">first line in the body</span>' +
'<div id="d1" contenteditable style="height: 2em; line-height: 1em; overflow: auto;">' +
'<span id="s2">first line</span><br>' +
'<span id="s3">second line</span><br>' +
'<span id="s4">third line</span><br>' +
'<span id="s5">last line</span>' +
"</div>" +
'<span id="s6">last line in the body</span>';
container = doc.getElementById("d1");
description = "Expanding selection to forward in scrollable editable div in the body: ";
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s2").firstChild, 3);
doSelectPageDown();
isnot(container.scrollTop, 0, description + "should be scrolled down");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
is(range.startOffset, 3,
`${description} selection should be expanded from the first line's 3rd insertion point`);
is(range.endContainer, doc.getElementById("s4").firstChild,
`${description} selection should be expanded into the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
isfuzzy(range.endOffset, 3, 2,
`${description} selection should be expanded to around the 3rd line's 3rd insertion point`);
description = "Expanding selection to backward in scrollable editable div in the body: ";
selection.collapse(doc.getElementById("s4").firstChild, 3);
previousScrollTop = container.scrollTop;
doSelectPageUp();
ok(container.scrollTop < previousScrollTop, description + "should be scrolled up");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
isfuzzy(range.startOffset, 3, 2,
`${description} selection should be expanded to around the first line's 3rd insertion point`);
is(range.endContainer, doc.getElementById("s4").firstChild,
`${description} selection should be expanded from the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
is(range.endOffset, 3,
`${description} selection should be expanded from the 3rd line's 3rd insertion point`);
body.innerHTML = '<span id="s1">first line in the body</span>' +
'<div id="d1" contenteditable>' +
'<span id="s2">first line</span><br>' +
'<span id="s3">second line</span><br>' +
'<span id="s4">third line</span><br>' +
'<span id="s5">last line</span>' +
"</div>" +
'<span id="s6">last line in the body</span>';
container = doc.getElementById("d1");
description = "Expanding selection to forward in non-scrollable editable div in the body: ";
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s2").firstChild, 3);
doSelectPageDown();
is(container.scrollTop, 0, description + "editable div shouldn't be scrollable");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
is(range.startOffset, 3,
`${description} selection should be expanded from the first line's 3rd insertion point`);
is(range.endContainer, doc.getElementById("s5").firstChild,
`${description} selection should be expanded into the last line (got: ${getNodeDescription(range.endContainer)})`);
if (kSelectToStartOrEnd) {
is(range.endOffset, range.endContainer.length,
`${description} selection should be expanded to end of the last line`);
} else {
isfuzzy(range.endOffset, 3, 2,
`${description} selection should be expanded to around the last line's 3rd insertion point`);
}
description = "Expanding selection to backward in non-scrollable editable div in the body: ";
selection.collapse(doc.getElementById("s5").firstChild, 3);
doSelectPageUp();
is(container.scrollTop, 0, description + "editable div shouldn't be scrollable");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
if (kSelectToStartOrEnd) {
is(range.startOffset, 0,
`${description} selection should be expanded to start of the first line`);
} else {
isfuzzy(range.startOffset, 3, 2,
`${description} selection should be expanded to around the first line's 3rd insertion point`);
}
is(range.endContainer, doc.getElementById("s5").firstChild,
`${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
is(range.endOffset, 3,
`${description} selection should be expanded from the last line's 3rd insertion point`);
body.innerHTML = '<span id="s1">first line in the body</span>' +
'<div id="d1" contenteditable>' +
'<span id="s2">first editable line</span><br>' +
'<div id="d2" style="height: 3em; line-height: 1em; overflow: auto;">' +
'<span id="s3">first line</span><br>' +
'<span id="s4">second line</span>' +
"</div>" +
'<span id="s5">last editable line</span>' +
"</div>" +
'<span id="s6">last line in the body</span>';
container = doc.getElementById("d2");
description = "Expanding selection to forward in scrollable div (but not scrollable along y-axis) in the editable div: ";
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s3").firstChild, 3);
doSelectPageDown();
is(container.scrollTop, 0, description + "scrollable div in the editable div (but not scrollable along y-axis) shouldn't be scrollable");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s3").firstChild,
`${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
is(range.startOffset, 3,
`${description} selection should be expanded from the first line's 3rd insertion point`);
is(range.endContainer, doc.getElementById("s5").firstChild,
`${description} selection should be expanded into the last editable line (got: ${getNodeDescription(range.endContainer)})`);
if (kSelectToStartOrEnd) {
is(range.endOffset, range.endContainer.length,
`${description} selection should be expanded to end of the last editable line`);
} else {
isfuzzy(range.endOffset, 3, 2,
`${description} selection should be expanded to around the last editable line's 3rd insertion point`);
}
description = "Expanding selection to backward in scrollable div (but not scrollable along y-axis) in the editable div: ";
selection.collapse(doc.getElementById("s4").firstChild, 3);
doSelectPageUp();
is(container.scrollTop, 0, description + "scrollable div (but not scrollable along y-axis) in the editable div shouldn't be scrollable");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded into the first editable line (got: ${getNodeDescription(range.startContainer)})`);
if (kSelectToStartOrEnd) {
is(range.startOffset, 0,
`${description} selection should be expanded to start of the first editable line`);
} else {
isfuzzy(range.startOffset, 3, 2,
`${description} selection should be expanded to around the first editable line's 3rd insertion point`);
}
is(range.endContainer, doc.getElementById("s4").firstChild,
`${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
is(range.endOffset, 3,
`${description} selection should be expanded from the last line's 3rd insertion point`);
aWindow.close();
SimpleTest.finish();
}
</script>
</html>

View File

@ -0,0 +1,357 @@
<!DOCTYPE html>
<html>
<head>
<title>Test for expanding selection per page</title>
<script type="text/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>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(() => {
open("window_empty_document.html", "_blank", "width=500,height=500");
});
async function doTests(aWindow) {
const IS_WIN = navigator.platform.includes("Win");
// On macOS and Linux, Shift + PageUp/PageDown requires native event to
// resolve default action of PageDown and PageUp. Although macOS widget has
// nsIWidget::AttachNativeKeyEvent(), we cannot use synthesizeKey() for the
// following tests. So, use nsISelectionController.pageMove() instead on
// non-Windows platforms.
const kUseKeyboardEvent = IS_WIN;
let selectionController = SpecialPowers.wrap(aWindow)
.docShell
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
.getInterface(SpecialPowers.Ci.nsISelectionDisplay)
.QueryInterface(SpecialPowers.Ci.nsISelectionController);
// On Windows, per-page selection to start or end expands selection to same
// column of first or last line. On the other platforms, it expands selection
// to start or end of first or last line.
const kSelectToStartOrEnd = !IS_WIN;
await SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false]]});
await SimpleTest.promiseFocus(aWindow);
function getNodeDescription(aNode) {
function getElementDescription(aElement) {
if (aElement.getAttribute("id") !== null) {
return `${aElement.tagName.toLowerCase()}#${aElement.getAttribute("id")}`;
}
if (aElement.tagName === "BR") {
return `${getElementDescription(aElement.previousSibling)} + br`;
}
return aElement.tagName.toLowerCase();
}
switch (aNode.nodeType) {
case aNode.TEXT_NODE:
return `text node in ${getElementDescription(aNode.parentElement)}`;
case aNode.ELEMENT_NODE:
return getElementDescription(aNode);
default:
return "unknown node";
}
}
function doTest(aExpandSelection) {
// Note that when neither editor has focus nor in caret mode, key navigation
// does not call nsISelectionController::PageMove(). Therefore, in such
// cases, you need to call doPageDown() and doPageUp() with setting true
// to aUseSelectionController.
function doPageDown(aUseSelectionController) {
if (kUseKeyboardEvent && !aUseSelectionController) {
synthesizeKey("KEY_PageDown", {shiftKey: aExpandSelection}, aWindow);
} else {
selectionController.pageMove(true, aExpandSelection);
}
}
function doPageUp(aUseSelectionController) {
if (kUseKeyboardEvent && !aUseSelectionController) {
synthesizeKey("KEY_PageUp", {shiftKey: aExpandSelection}, aWindow);
} else {
selectionController.pageMove(false, aExpandSelection);
}
}
let doc = aWindow.document;
let body = doc.body;
let selection = doc.getSelection();
let container;
body.innerHTML = '<span id="s1">first line</span><br>' +
'<span id="s2">second line</span><br>' +
'<span id="s3">last line</span>';
container = doc.documentElement;
let description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in non-scrollable body: `;
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s1").firstChild, 3);
doPageDown(!aExpandSelection);
is(container.scrollTop, 0, description + "this test shouldn't create scrollable document");
let range = selection.getRangeAt(0);
if (aExpandSelection) {
is(range.startContainer, doc.getElementById("s1").firstChild,
`${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
is(range.startOffset, 3,
`${description} selection should be expanded from the first line's 3rd insertion point`);
} else {
ok(range.collapsed, `${description} selection should be collapsed`);
}
is(range.endContainer, doc.getElementById("s3").firstChild,
`${description} selection should be expanded into the last line (got: ${getNodeDescription(range.endContainer)})`);
if (kSelectToStartOrEnd) {
is(range.endOffset, range.endContainer.length,
`${description} selection should be expanded to end of the last line`);
} else {
isfuzzy(range.endOffset, 3, 2,
`${description} selection should be expanded to around the last line's 3rd insertion point`);
}
description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in non-scrollable body: `;
selection.collapse(doc.getElementById("s3").firstChild, 3);
doPageUp(!aExpandSelection);
is(container.scrollTop, 0, description + "this test shouldn't create scrollable document");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s1").firstChild,
`${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
if (kSelectToStartOrEnd) {
is(range.startOffset, 0,
`${description} selection should be expanded to start of the first line`);
} else {
isfuzzy(range.startOffset, 3, 2,
`${description} selection should be expanded to around the first line's 3rd insertion point`);
}
if (aExpandSelection) {
is(range.endContainer, doc.getElementById("s3").firstChild,
`${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
is(range.endOffset, 3,
`${description} selection should be expanded from the last line's 3rd insertion point`);
} else {
ok(range.collapsed, `${description} selection should be collapsed`);
}
body.innerHTML = '<span id="s1">first line in the body</span>' +
'<div id="d1" style="height: 2em; line-height: 1em; overflow: auto;">' +
'<span id="s2">first line</span><br>' +
'<span id="s3">second line</span><br>' +
'<span id="s4">third line</span><br>' +
'<span id="s5">last line</span>' +
"</div>" +
'<span id="s6">last line in the body</span>';
container = doc.getElementById("d1");
description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in scrollable area in the body: `;
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s2").firstChild, 3);
doPageDown(!aExpandSelection);
isnot(container.scrollTop, 0, description + "should be scrolled down");
range = selection.getRangeAt(0);
if (aExpandSelection) {
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
is(range.startOffset, 3,
`${description} selection should be expanded from the first line's 3rd insertion point`);
} else {
ok(range.collapsed, `${description} selection should be collapsed`);
}
is(range.endContainer, doc.getElementById("s4").firstChild,
`${description} selection should be expanded into the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
isfuzzy(range.endOffset, 3, 2,
`${description} selection should be expanded to around the 3rd line's 3rd insertion point`);
description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in scrollable area in the body: `;
selection.collapse(doc.getElementById("s4").firstChild, 3);
let previousScrollTop = container.scrollTop;
doPageUp(!aExpandSelection);
ok(container.scrollTop < previousScrollTop, description + "should be scrolled up");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
isfuzzy(range.startOffset, 3, 2,
`${description} selection should be expanded to around the first line's 3rd insertion point`);
if (aExpandSelection) {
is(range.endContainer, doc.getElementById("s4").firstChild,
`${description} selection should be expanded from the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
is(range.endOffset, 3,
`${description} selection should be expanded from the 3rd line's 3rd insertion point`);
} else {
ok(range.collapsed, `${description} selection should be collapsed`);
}
body.innerHTML = '<span id="s1">first line in the body</span>' +
'<div id="d1" contenteditable style="height: 2em; line-height: 1em; overflow: auto;">' +
'<span id="s2">first line</span><br>' +
'<span id="s3">second line</span><br>' +
'<span id="s4">third line</span><br>' +
'<span id="s5">last line</span>' +
"</div>" +
'<span id="s6">last line in the body</span>';
container = doc.getElementById("d1");
description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in scrollable editable div in the body: `;
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s2").firstChild, 3);
doPageDown();
isnot(container.scrollTop, 0, description + "should be scrolled down");
range = selection.getRangeAt(0);
if (aExpandSelection) {
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
is(range.startOffset, 3,
`${description} selection should be expanded from the first line's 3rd insertion point`);
} else {
ok(range.collapsed, `${description} selection should be collapsed`);
}
is(range.endContainer, doc.getElementById("s4").firstChild,
`${description} selection should be expanded into the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
isfuzzy(range.endOffset, 3, 2,
`${description} selection should be expanded to around the 3rd line's 3rd insertion point`);
description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in scrollable editable div in the body: `;
selection.collapse(doc.getElementById("s4").firstChild, 3);
previousScrollTop = container.scrollTop;
doPageUp();
ok(container.scrollTop < previousScrollTop, description + "should be scrolled up");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
isfuzzy(range.startOffset, 3, 2,
`${description} selection should be expanded to around the first line's 3rd insertion point`);
if (aExpandSelection) {
is(range.endContainer, doc.getElementById("s4").firstChild,
`${description} selection should be expanded from the 3rd line (got: ${getNodeDescription(range.endContainer)})`);
is(range.endOffset, 3,
`${description} selection should be expanded from the 3rd line's 3rd insertion point`);
} else {
ok(range.collapsed, `${description} selection should be collapsed`);
}
body.innerHTML = '<span id="s1">first line in the body</span>' +
'<div id="d1" contenteditable>' +
'<span id="s2">first line</span><br>' +
'<span id="s3">second line</span><br>' +
'<span id="s4">third line</span><br>' +
'<span id="s5">last line</span>' +
"</div>" +
'<span id="s6">last line in the body</span>';
container = doc.getElementById("d1");
description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in non-scrollable editable div in the body: `;
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s2").firstChild, 3);
doPageDown();
is(container.scrollTop, 0, description + "editable div shouldn't be scrollable");
range = selection.getRangeAt(0);
if (aExpandSelection) {
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
is(range.startOffset, 3,
`${description} selection should be expanded from the first line's 3rd insertion point`);
} else {
ok(range.collapsed, `${description} selection should be collapsed`);
}
is(range.endContainer, doc.getElementById("s5").firstChild,
`${description} selection should be expanded into the last line (got: ${getNodeDescription(range.endContainer)})`);
if (kSelectToStartOrEnd) {
is(range.endOffset, range.endContainer.length,
`${description} selection should be expanded to end of the last line`);
} else {
isfuzzy(range.endOffset, 3, 2,
`${description} selection should be expanded to around the last line's 3rd insertion point`);
}
description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in non-scrollable editable div in the body: `;
selection.collapse(doc.getElementById("s5").firstChild, 3);
doPageUp();
is(container.scrollTop, 0, description + "editable div shouldn't be scrollable");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded into the first line (got: ${getNodeDescription(range.startContainer)})`);
if (kSelectToStartOrEnd) {
is(range.startOffset, 0,
`${description} selection should be expanded to start of the first line`);
} else {
isfuzzy(range.startOffset, 3, 2,
`${description} selection should be expanded to around the first line's 3rd insertion point`);
}
if (aExpandSelection) {
is(range.endContainer, doc.getElementById("s5").firstChild,
`${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
is(range.endOffset, 3,
`${description} selection should be expanded from the last line's 3rd insertion point`);
} else {
ok(range.collapsed, `${description} selection should be collapsed`);
}
body.innerHTML = '<span id="s1">first line in the body</span>' +
'<div id="d1" contenteditable>' +
'<span id="s2">first editable line</span><br>' +
'<div id="d2" style="height: 3em; line-height: 1em; overflow: auto;">' +
'<span id="s3">first line</span><br>' +
'<span id="s4">second line</span>' +
"</div>" +
'<span id="s5">last editable line</span>' +
"</div>" +
'<span id="s6">last line in the body</span>';
container = doc.getElementById("d2");
description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to forward in scrollable div (but not scrollable along y-axis) in the editable div: `;
is(container.scrollTop, 0, description + "scrollTop should be 0 at initialization");
selection.collapse(doc.getElementById("s3").firstChild, 3);
doPageDown();
is(container.scrollTop, 0, description + "scrollable div in the editable div (but not scrollable along y-axis) shouldn't be scrollable");
range = selection.getRangeAt(0);
if (aExpandSelection) {
is(range.startContainer, doc.getElementById("s3").firstChild,
`${description} selection should be expanded from the first line (got: ${getNodeDescription(range.startContainer)})`);
is(range.startOffset, 3,
`${description} selection should be expanded from the first line's 3rd insertion point`);
} else {
ok(range.collapsed, `${description} selection should be collapsed`);
}
is(range.endContainer, doc.getElementById("s5").firstChild,
`${description} selection should be expanded into the last editable line (got: ${getNodeDescription(range.endContainer)})`);
if (kSelectToStartOrEnd) {
is(range.endOffset, range.endContainer.length,
`${description} selection should be expanded to end of the last editable line`);
} else {
isfuzzy(range.endOffset, 3, 2,
`${description} selection should be expanded to around the last editable line's 3rd insertion point`);
}
description = `${aExpandSelection ? "Expanding selection" : "Moving caret"} to backward in scrollable div (but not scrollable along y-axis) in the editable div: `;
selection.collapse(doc.getElementById("s4").firstChild, 3);
doPageUp();
is(container.scrollTop, 0, description + "scrollable div (but not scrollable along y-axis) in the editable div shouldn't be scrollable");
range = selection.getRangeAt(0);
is(range.startContainer, doc.getElementById("s2").firstChild,
`${description} selection should be expanded into the first editable line (got: ${getNodeDescription(range.startContainer)})`);
if (kSelectToStartOrEnd) {
is(range.startOffset, 0,
`${description} selection should be expanded to start of the first editable line`);
} else {
isfuzzy(range.startOffset, 3, 2,
`${description} selection should be expanded to around the first editable line's 3rd insertion point`);
}
if (aExpandSelection) {
is(range.endContainer, doc.getElementById("s4").firstChild,
`${description} selection should be expanded from the last line (got: ${getNodeDescription(range.endContainer)})`);
is(range.endOffset, 3,
`${description} selection should be expanded from the last line's 3rd insertion point`);
} else {
ok(range.collapsed, `${description} selection should be collapsed`);
}
}
doTest(false);
doTest(true);
aWindow.close();
SimpleTest.finish();
}
</script>
</html>