Bug 1213589 part.6 ContentEventHandler should insert line breaks at open tag of elements except non-replaced inline elements r=smaug

This commit is contained in:
Masayuki Nakano 2015-12-02 13:20:00 +09:00
parent e894cacf0c
commit 32e964a3fc
6 changed files with 484 additions and 312 deletions

View File

@ -47,9 +47,10 @@ using namespace widget;
// 1.1. Cases: [textNode or text[Node or textNode[
// When text node is start of a range, start node is the text node and
// start offset is any number between 0 and the length of the text.
// 1.2. Case: [<element>
// When before an element node is start of a range, start node is parent
// of the element and start offset is the element's index in the parent.
// 1.2. Case: [<element>:
// When start of an element node is start of a range, start node is
// parent of the element and start offset is the element's index in the
// parent.
// 1.3. Case: <element/>[
// When after an empty element node is start of a range, start node is
// parent of the element and start offset is the element's index in the
@ -71,11 +72,16 @@ using namespace widget;
// 2.3 are handled correctly, the loop with nsContentIterator shouldn't
// reach the element node since the loop should've finished already at
// handling the last node which caused some text.
// 2.3. Case: </element>]
// When after an element node is end of a range, end node is parent of
// the element node and end offset is the element's index in the parent
// + 1.
// 2.4. Case: ]</root>
// 2.3. Case: <element>]
// When a line break is caused before a non-empty element node and it's
// end of a range, end node is the element and end offset is 0.
// (i.e., including open tag of the element)
// 2.4. Cases: <element/>]
// When after an empty element node is end of a range, end node is
// parent of the element node and end offset is the element's index in
// the parent + 1. (i.e., including close tag of the element or empty
// element)
// 2.5. Case: ]</root>
// When end of a range is out of bounds, end node is the root node and
// end offset is number of the children.
//
@ -398,12 +404,14 @@ ContentEventHandler::GetNativeTextLength(nsIContent* aContent,
}
/* static */ uint32_t
ContentEventHandler::GetNativeTextLengthBefore(nsIContent* aContent)
ContentEventHandler::GetNativeTextLengthBefore(nsIContent* aContent,
nsINode* aRootNode)
{
if (NS_WARN_IF(aContent->IsNodeOfType(nsINode::eTEXT))) {
return 0;
}
return IsContentBR(aContent) ? GetBRLength(LINE_BREAK_TYPE_NATIVE) : 0;
return ShouldBreakLineBefore(aContent, aRootNode) ?
GetBRLength(LINE_BREAK_TYPE_NATIVE) : 0;
}
/* static inline */ uint32_t
@ -457,6 +465,67 @@ static uint32_t ConvertToXPOffset(nsIContent* aContent, uint32_t aNativeOffset)
#endif
}
/* static */ bool
ContentEventHandler::ShouldBreakLineBefore(nsIContent* aContent,
nsINode* aRootNode)
{
// We don't need to append linebreak at the start of the root element.
if (aContent == aRootNode) {
return false;
}
// If it's not an HTML element (including other markup language's elements),
// we shouldn't insert like break before that for now. Becoming this is a
// problem must be edge case. E.g., when ContentEventHandler is used with
// MathML or SVG elements.
if (!aContent->IsHTMLElement()) {
return false;
}
// If the element is <br>, we need to check if the <br> is caused by web
// content. Otherwise, i.e., it's caused by internal reason of Gecko,
// it shouldn't be exposed as a line break to flatten text.
if (aContent->IsHTMLElement(nsGkAtoms::br)) {
return IsContentBR(aContent);
}
// Note that ideally, we should refer the style of the primary frame of
// aContent for deciding if it's an inline. However, it's difficult
// IMEContentObserver to notify IME of text change caused by style change.
// Therefore, currently, we should check only from the tag for now.
// TODO: Check if the element is an unknown HTML element.
return !aContent->IsAnyOfHTMLElements(nsGkAtoms::a,
nsGkAtoms::abbr,
nsGkAtoms::acronym,
nsGkAtoms::b,
nsGkAtoms::bdi,
nsGkAtoms::bdo,
nsGkAtoms::big,
nsGkAtoms::cite,
nsGkAtoms::code,
nsGkAtoms::data,
nsGkAtoms::del,
nsGkAtoms::dfn,
nsGkAtoms::em,
nsGkAtoms::font,
nsGkAtoms::i,
nsGkAtoms::ins,
nsGkAtoms::kbd,
nsGkAtoms::mark,
nsGkAtoms::s,
nsGkAtoms::samp,
nsGkAtoms::small,
nsGkAtoms::span,
nsGkAtoms::strike,
nsGkAtoms::strong,
nsGkAtoms::sub,
nsGkAtoms::sup,
nsGkAtoms::time,
nsGkAtoms::tt,
nsGkAtoms::u,
nsGkAtoms::var);
}
nsresult
ContentEventHandler::GenerateFlatTextContent(nsRange* aRange,
nsAFlatString& aString,
@ -506,7 +575,7 @@ ContentEventHandler::GenerateFlatTextContent(nsRange* aRange,
} else {
AppendString(aString, content);
}
} else if (IsContentBR(content)) {
} else if (ShouldBreakLineBefore(content, mRootContent)) {
aString.Append(char16_t('\n'));
}
}
@ -626,7 +695,7 @@ ContentEventHandler::AppendFontRanges(FontRangeArray& aFontRanges,
}
}
/* static */ nsresult
nsresult
ContentEventHandler::GenerateFlatFontRanges(nsRange* aRange,
FontRangeArray& aFontRanges,
uint32_t& aLength,
@ -669,7 +738,7 @@ ContentEventHandler::GenerateFlatFontRanges(nsRange* aRange,
startOffset, endOffset, aLineBreakType);
baseOffset += GetTextLengthInRange(content, startOffset, endOffset,
aLineBreakType);
} else if (IsContentBR(content)) {
} else if (ShouldBreakLineBefore(content, mRootContent)) {
if (aFontRanges.IsEmpty()) {
MOZ_ASSERT(baseOffset == 0);
FontRange* fontRange = AppendFontRange(aFontRanges, baseOffset);
@ -789,7 +858,8 @@ ContentEventHandler::SetRangeFromFlatTextOffset(nsRange* aRange,
uint32_t textLength =
content->IsNodeOfType(nsINode::eTEXT) ?
GetTextLength(content, aLineBreakType) :
(IsContentBR(content) ? GetBRLength(aLineBreakType) : 0);
(ShouldBreakLineBefore(content, mRootContent) ?
GetBRLength(aLineBreakType) : 0);
if (!textLength) {
continue;
}
@ -900,7 +970,17 @@ ContentEventHandler::SetRangeFromFlatTextOffset(nsRange* aRange,
return NS_ERROR_FAILURE;
}
// Rule #2.3: </element>]
if (content->HasChildren() &&
ShouldBreakLineBefore(content, mRootContent)) {
// Rule #2.3: </element>]
rv = aRange->SetEnd(content, 0);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
// Rule #2.4: <element/>]
nsINode* endNode = content->GetParent();
if (NS_WARN_IF(!endNode)) {
return NS_ERROR_FAILURE;
@ -932,7 +1012,7 @@ ContentEventHandler::SetRangeFromFlatTextOffset(nsRange* aRange,
*aNewOffset = offset;
}
}
// Rule #2.4: ]</root>
// Rule #2.5: ]</root>
rv = aRange->SetEnd(mRootContent,
static_cast<int32_t>(mRootContent->GetChildCount()));
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -1612,9 +1692,38 @@ ContentEventHandler::GetFlatTextLengthInRange(
return rv;
}
if (aEndPosition.OffsetIsValid()) {
// When the end position is immediately after non-root element's open tag,
// we need to include a line break caused by the open tag.
NodePosition endPosition;
if (aEndPosition.mNode != aRootContent &&
aEndPosition.IsImmediatelyAfterOpenTag()) {
if (aEndPosition.mNode->HasChildren()) {
// When the end node has some children, move the end position to the
// start of its first child.
nsINode* firstChild = aEndPosition.mNode->GetFirstChild();
if (NS_WARN_IF(!firstChild)) {
return NS_ERROR_FAILURE;
}
endPosition = NodePosition(firstChild, 0);
} else {
// When the end node is empty, move the end position after the node.
nsIContent* parentContent = aEndPosition.mNode->GetParent();
if (NS_WARN_IF(!parentContent)) {
return NS_ERROR_FAILURE;
}
int32_t indexInParent = parentContent->IndexOf(aEndPosition.mNode);
if (NS_WARN_IF(indexInParent < 0)) {
return NS_ERROR_FAILURE;
}
endPosition = NodePosition(parentContent, indexInParent + 1);
}
} else {
endPosition = aEndPosition;
}
if (endPosition.OffsetIsValid()) {
// Offset is within node's length; set end of range to that offset
rv = aEndPosition.SetToRangeEnd(prev);
rv = endPosition.SetToRangeEnd(prev);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -1623,9 +1732,9 @@ ContentEventHandler::GetFlatTextLengthInRange(
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else if (aEndPosition.mNode != aRootContent) {
} else if (endPosition.mNode != aRootContent) {
// Offset is past node's length; set end of range to end of node
rv = aEndPosition.SetToRangeEndAfter(prev);
rv = endPosition.SetToRangeEndAfter(prev);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -1663,7 +1772,12 @@ ContentEventHandler::GetFlatTextLengthInRange(
} else {
*aLength += GetTextLength(content, aLineBreakType);
}
} else if (IsContentBR(content)) {
} else if (ShouldBreakLineBefore(content, aRootContent)) {
// If the start position is start of this node but doesn't include the
// open tag, don't append the line break length.
if (node == aStartPosition.mNode && !aStartPosition.IsBeforeOpenTag()) {
continue;
}
*aLength += GetBRLength(aLineBreakType);
}
}
@ -1678,7 +1792,7 @@ ContentEventHandler::GetFlatTextLengthBefore(nsRange* aRange,
MOZ_ASSERT(aRange);
return GetFlatTextLengthInRange(
NodePosition(mRootContent, 0),
NodePosition(aRange->GetStartParent(), aRange->StartOffset()),
NodePositionBefore(aRange->GetStartParent(), aRange->StartOffset()),
mRootContent, aOffset, aLineBreakType);
}

View File

@ -84,32 +84,51 @@ public:
// are replaced to native linefeeds. Other elements are ignored.
// NodePosition stores a pair of node and offset in the node.
// When mNode is an element and mOffset is 0, the start position means after
// the open tag of mNode.
// This is useful to receive one or more sets of them instead of nsRange.
struct NodePosition final
struct NodePosition
{
nsCOMPtr<nsINode> mNode;
int32_t mOffset;
// Only when mNode is an element node and mOffset is 0, mAfterOpenTag is
// referred.
bool mAfterOpenTag;
NodePosition()
: mOffset(-1)
, mAfterOpenTag(true)
{
}
NodePosition(nsINode* aNode, int32_t aOffset)
: mNode(aNode)
, mOffset(aOffset)
, mAfterOpenTag(true)
{
}
explicit NodePosition(const nsIFrame::ContentOffsets& aContentOffsets)
: mNode(aContentOffsets.content)
, mOffset(aContentOffsets.offset)
, mAfterOpenTag(true)
{
}
protected:
NodePosition(nsINode* aNode, int32_t aOffset, bool aAfterOpenTag)
: mNode(aNode)
, mOffset(aOffset)
, mAfterOpenTag(aAfterOpenTag)
{
}
public:
bool operator==(const NodePosition& aOther) const
{
return mNode == aOther.mNode && mOffset == aOther.mOffset;
return mNode == aOther.mNode &&
mOffset == aOther.mOffset &&
mAfterOpenTag == aOther.mAfterOpenTag;
}
bool IsValid() const
@ -120,6 +139,14 @@ public:
{
return IsValid() && static_cast<uint32_t>(mOffset) <= mNode->Length();
}
bool IsBeforeOpenTag() const
{
return IsValid() && mNode->IsElement() && !mOffset && !mAfterOpenTag;
}
bool IsImmediatelyAfterOpenTag() const
{
return IsValid() && mNode->IsElement() && !mOffset && mAfterOpenTag;
}
nsresult SetToRangeStart(nsRange* aRange) const
{
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mNode));
@ -137,9 +164,35 @@ public:
}
};
// NodePositionBefore isn't good name if mNode isn't an element node nor
// mOffset is not 0, though, when mNode is an element node and mOffset is 0,
// this is treated as before the open tag of mNode.
struct NodePositionBefore final : public NodePosition
{
NodePositionBefore(nsINode* aNode, int32_t aOffset)
: NodePosition(aNode, aOffset, false)
{
}
};
// Get the flatten text length in the range.
// @param aStartPosition Start node and offset in the node of the range.
// @param aEndPosition End node and offset in the node of the range.
// @param aRootContent The root content of the editor or document.
// aRootContent won't cause any text including
// line breaks.
// @param aLength The result of the flatten text length of the
// range.
// @param aLineBreakType Whether this computes flatten text length with
// native line breakers on the platform or
// with XP line breaker (\n).
// @param aIsRemovingNode Should be true only when this is called from
// nsIMutationObserver::ContentRemoved().
// When this is true, aStartPosition.mNode should
// be the root node of removing nodes and mOffset
// should be 0 and aEndPosition.mNode should be
// same as aStartPosition.mNode and mOffset should
// be number of the children of mNode.
static nsresult GetFlatTextLengthInRange(const NodePosition& aStartPosition,
const NodePosition& aEndPosition,
nsIContent* aRootContent,
@ -155,8 +208,9 @@ public:
static uint32_t GetNativeTextLength(nsIContent* aContent,
uint32_t aMaxLength = UINT32_MAX);
// Get the native text length which is inserted before aContent.
// aContent should be a <br> element for now.
static uint32_t GetNativeTextLengthBefore(nsIContent* aContent);
// aContent should be an element.
static uint32_t GetNativeTextLengthBefore(nsIContent* aContent,
nsINode* aRootNode);
protected:
// Get the text length of aContent. aContent must be a text node.
@ -177,6 +231,11 @@ protected:
nsresult GetFlatTextLengthBefore(nsRange* aRange,
uint32_t* aOffset,
LineBreakType aLineBreakType);
// Check if we should insert a line break before aContent.
// This should return false only when aContent is an html element which
// is typically used in a paragraph like <em>.
static bool ShouldBreakLineBefore(nsIContent* aContent,
nsINode* aRootNode);
// Get the line breaker length.
static inline uint32_t GetBRLength(LineBreakType aLineBreakType);
static LineBreakType GetLineBreakType(WidgetQueryContentEvent* aEvent);
@ -221,10 +280,10 @@ protected:
int32_t aXPStartOffset,
int32_t aXPEndOffset,
LineBreakType aLineBreakType);
static nsresult GenerateFlatFontRanges(nsRange* aRange,
FontRangeArray& aFontRanges,
uint32_t& aLength,
LineBreakType aLineBreakType);
nsresult GenerateFlatFontRanges(nsRange* aRange,
FontRangeArray& aFontRanges,
uint32_t& aLength,
LineBreakType aLineBreakType);
};
} // namespace mozilla

View File

@ -879,9 +879,7 @@ IMEContentObserver::CharacterDataChanged(nsIDocument* aDocument,
ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(mRootContent, 0),
NodePosition(aContent, aInfo->mChangeStart),
mRootContent,
&offset,
LINE_BREAK_TYPE_NATIVE);
mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
@ -918,9 +916,8 @@ IMEContentObserver::NotifyContentAdded(nsINode* aContainer,
mEndOfAddedTextCache.Clear();
rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(mRootContent, 0),
NodePosition(aContainer, aStartIndex),
mRootContent, &offset,
LINE_BREAK_TYPE_NATIVE);
NodePositionBefore(aContainer, aStartIndex),
mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
if (NS_WARN_IF(NS_FAILED((rv)))) {
return;
}
@ -931,7 +928,7 @@ IMEContentObserver::NotifyContentAdded(nsINode* aContainer,
// get offset at the end of the last added node
uint32_t addingLength = 0;
rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(aContainer, aStartIndex),
NodePositionBefore(aContainer, aStartIndex),
NodePosition(aContainer, aEndIndex),
mRootContent, &addingLength,
LINE_BREAK_TYPE_NATIVE);
@ -995,12 +992,12 @@ IMEContentObserver::ContentRemoved(nsIDocument* aDocument,
uint32_t offset = 0;
nsresult rv = NS_OK;
if (!mStartOfRemovingTextRangeCache.Match(containerNode, aIndexInContainer)) {
// At removing a child node of aContainer, we need the line break caused
// by open tag of aContainer. Be careful when aIndexInContainer is 0.
rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(mRootContent, 0),
NodePosition(containerNode, aIndexInContainer),
mRootContent,
&offset,
LINE_BREAK_TYPE_NATIVE);
mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
if (NS_WARN_IF(NS_FAILED(rv))) {
mStartOfRemovingTextRangeCache.Clear();
return;
@ -1018,7 +1015,7 @@ IMEContentObserver::ContentRemoved(nsIDocument* aDocument,
} else {
uint32_t nodeLength = static_cast<int32_t>(aChild->GetChildCount());
rv = ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(aChild, 0),
NodePositionBefore(aChild, 0),
NodePosition(aChild, nodeLength),
mRootContent, &textLength,
LINE_BREAK_TYPE_NATIVE, true);
@ -1046,7 +1043,7 @@ IMEContentObserver::AttributeWillChange(nsIDocument* aDocument,
const nsAttrValue* aNewValue)
{
mPreAttrChangeLength =
ContentEventHandler::GetNativeTextLengthBefore(aElement);
ContentEventHandler::GetNativeTextLengthBefore(aElement, mRootContent);
}
void
@ -1067,17 +1064,16 @@ IMEContentObserver::AttributeChanged(nsIDocument* aDocument,
}
uint32_t postAttrChangeLength =
ContentEventHandler::GetNativeTextLengthBefore(aElement);
ContentEventHandler::GetNativeTextLengthBefore(aElement, mRootContent);
if (postAttrChangeLength == mPreAttrChangeLength) {
return;
}
uint32_t start;
nsresult rv =
ContentEventHandler::GetFlatTextLengthInRange(NodePosition(mRootContent, 0),
NodePosition(aElement, 0),
mRootContent,
&start,
LINE_BREAK_TYPE_NATIVE);
ContentEventHandler::GetFlatTextLengthInRange(
NodePosition(mRootContent, 0),
NodePositionBefore(aElement, 0),
mRootContent, &start, LINE_BREAK_TYPE_NATIVE);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}

View File

@ -41,6 +41,7 @@ class IMEContentObserver final : public nsISelectionListener
{
public:
typedef ContentEventHandler::NodePosition NodePosition;
typedef ContentEventHandler::NodePositionBefore NodePositionBefore;
typedef widget::IMENotification::SelectionChangeData SelectionChangeData;
typedef widget::IMENotification::TextChangeData TextChangeData;
typedef widget::IMENotification::TextChangeDataBase TextChangeDataBase;

View File

@ -25,6 +25,8 @@
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(runTests);
const kLF = !navigator.platform.indexOf("Win") ? "\r\n" : "\n";
function runTests()
{
var fm = Components.classes["@mozilla.org/focus-manager;1"].
@ -82,8 +84,19 @@ function runTests()
if (aElement == editor) {
var value = "";
for (var node = aElement.firstChild; node; node = node.nextSibling) {
if (node.nodeType == 3) {
if (node.nodeType == Node.TEXT_NODE) {
value += node.data;
} else if (node.nodeType == Node.ELEMENT_NODE) {
var tagName = node.tagName.toLowerCase();
switch (tagName) {
case "input":
case "textarea":
value += kLF;
break;
default:
ok(false, "Undefined tag is used in the editor: " + tagName);
break;
}
}
}
return value;

View File

@ -2325,17 +2325,6 @@ function runSetSelectionEventTest()
// #1
contenteditable.innerHTML = "abc<br>def";
synthesizeSelectionSet(0, 6 + kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.lastChild,
"runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node of the editor");
is(selection.focusOffset, contenteditable.lastChild.wholeText.length,
"runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(0, "abc" + kLF + "def", "runSetSelectionEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 100);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
@ -2405,264 +2394,264 @@ function runSetSelectionEventTest()
// #2
contenteditable.innerHTML = "<p>a<b>b</b>c</p><p>def</p>";
synthesizeSelectionSet(0, 4);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
synthesizeSelectionSet(kLFLen, 4+kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
"runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the first <p> node");
is(selection.focusNode, contenteditable.lastChild.firstChild,
"runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
"runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(0, "abcd", "runSetSelectionEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(kLFLen, "abc" + kLF + "d", "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 2);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
synthesizeSelectionSet(kLFLen, 2);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
"runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the first <p> node");
is(selection.focusNode, contenteditable.firstChild.childNodes.item(1).firstChild,
"runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <b> node");
"runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <b> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.item(1).firstChild.wholeText.length,
"runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <b> node");
checkSelection(0, "ab", "runSetSelectionEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <b> node");
checkSelection(kLFLen, "ab", "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(1, 2);
synthesizeSelectionSet(1+kLFLen, 2);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
"runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
"runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node in the first <p> node");
"runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node in the first <p> node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node in the first <p> node");
checkSelection(1, "bc", "runSetSelectionEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node in the first <p> node");
checkSelection(1+kLFLen, "bc", "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(2, 2);
synthesizeSelectionSet(2+kLFLen, 2+kLFLen);
is(selection.anchorNode, contenteditable.firstChild.childNodes.item(1).firstChild,
"runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <b> node");
"runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <b> node");
is(selection.anchorOffset, contenteditable.firstChild.childNodes.item(1).firstChild.wholeText.length,
"runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <b> node");
"runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <b> node");
is(selection.focusNode, contenteditable.lastChild.firstChild,
"runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the last <p> node");
"runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the last <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(2, "cd", "runSetSelectionEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(2+kLFLen, "c" + kLF + "d", "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3, 1);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node in the first <p> node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node in the first <p> node");
synthesizeSelectionSet(3+kLFLen*2, 1);
is(selection.anchorNode, contenteditable.lastChild,
"runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the second <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the second <p> node");
is(selection.focusNode, contenteditable.lastChild.firstChild,
"runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
"runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(3, "d", "runSetSelectionEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(3+kLFLen*2, "d", "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
// #3
contenteditable.innerHTML = "<div>abc<p>def</p></div>";
synthesizeSelectionSet(1, 2);
synthesizeSelectionSet(1+kLFLen, 2);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
"runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
"runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
"runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
is(selection.focusOffset, contenteditable.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
checkSelection(1, "bc", "runSetSelectionEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
checkSelection(1+kLFLen, "bc", "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(1, 3);
synthesizeSelectionSet(1+kLFLen, 3+kLFLen);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
"runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
"runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
"runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(1, "bcd", "runSetSelectionEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(1+kLFLen, "bc" + kLF + "d", "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3, 0);
synthesizeSelectionSet(3+kLFLen, 0);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
"runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, contenteditable.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the first text node");
"runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the first text node");
is(selection.focusNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
"runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
is(selection.focusOffset, contenteditable.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
checkSelection(3, "", "runSetSelectionEventTest #3 (3, 0), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
checkSelection(3+kLFLen, "", "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 6);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
synthesizeSelectionSet(0, 6+kLFLen*2);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
"runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
"runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(0, "abcdef", "runSetSelectionEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(0, kLF + "abc" + kLF + "def", "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 100);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(0, "abcdef", "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
checkSelection(0, kLF + "abc" + kLF + "def", "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(4, 2);
synthesizeSelectionSet(4+kLFLen*2, 2);
is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
"runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
"runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
"runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(4, "ef", "runSetSelectionEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(4, 100);
synthesizeSelectionSet(4+kLFLen*2, 100);
is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
"runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
"runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
"runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(4, "ef", "runSetSelectionEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(6, 0);
synthesizeSelectionSet(6+kLFLen*2, 0);
is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
"runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
"runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
"runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(6, "", "runSetSelectionEventTest #3 (6, 0), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(6, 1);
synthesizeSelectionSet(6+kLFLen*2, 1);
is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
"runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
"runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
"runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(6, "", "runSetSelectionEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
// #4
contenteditable.innerHTML = "<div><p>abc</p>def</div>";
synthesizeSelectionSet(1, 2);
synthesizeSelectionSet(1+kLFLen*2, 2);
is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
"runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
"runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
"runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
is(selection.focusOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
checkSelection(1, "bc", "runSetSelectionEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
checkSelection(1+kLFLen*2, "bc", "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(1, 3);
synthesizeSelectionSet(1+kLFLen*2, 3);
is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
"runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
"runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
"runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(1, "bcd", "runSetSelectionEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(1+kLFLen*2, "bcd", "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3, 0);
synthesizeSelectionSet(3+kLFLen*2, 0);
is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
"runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
is(selection.anchorOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <p> node");
"runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <p> node");
is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
"runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
is(selection.focusOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
checkSelection(3, "", "runSetSelectionEventTest #4 (3, 0), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
checkSelection(3+kLFLen*2, "", "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 6);
is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
synthesizeSelectionSet(0, 6+kLFLen*2);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
"runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
"runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(0, "abcdef", "runSetSelectionEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(0, kLF + kLF + "abcdef", "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 100);
is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(0, "abcdef", "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
checkSelection(0, kLF + kLF + "abcdef", "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(4, 2);
synthesizeSelectionSet(4+kLFLen*2, 2);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
"runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
"runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
"runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(4, "ef", "runSetSelectionEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(4, 100);
synthesizeSelectionSet(4+kLFLen*2, 100);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
"runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
"runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
"runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(4, "ef", "runSetSelectionEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(6, 0);
synthesizeSelectionSet(6+kLFLen*2, 0);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
"runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
"runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
"runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(6, "", "runSetSelectionEventTest #4 (6, 0), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(6, 1);
synthesizeSelectionSet(6+kLFLen*2, 1);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
"runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
"runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
"runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(6, "", "runSetSelectionEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
// #5
contenteditable.innerHTML = "<br>";
@ -2703,38 +2692,38 @@ function runSetSelectionEventTest()
// #6
contenteditable.innerHTML = "<p><br></p>";
synthesizeSelectionSet(0, kLFLen);
synthesizeSelectionSet(kLFLen, kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
"runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
"runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
"runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(0, kLF, "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen, kLF, "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 0);
synthesizeSelectionSet(kLFLen*2, 0);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
"runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
"runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
"runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen, "", "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen*2, "", "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 1);
synthesizeSelectionSet(kLFLen*2, 1);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
"runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
"runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
"runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(kLFLen, "", "runSetSelectionEventTest #6 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(kLFLen*2, "", "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
// #7
contenteditable.innerHTML = "<br><br>";
@ -2797,60 +2786,60 @@ function runSetSelectionEventTest()
// #8
contenteditable.innerHTML = "<p><br><br></p>";
synthesizeSelectionSet(0, kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(0, kLF, "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, kLFLen * 2);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(0, kLF + kLF, "runSetSelectionEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 0);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(kLFLen, "", "runSetSelectionEventTest #8 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen, kLFLen) selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen, kLF, "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(kLFLen, kLF, "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen * 2, 0);
synthesizeSelectionSet(kLFLen, kLFLen * 2);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen, kLF + kLF, "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen*2, 0);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(kLFLen*2, "", "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen*2, kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*2, kLFLen) selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen * 2, "", "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
"runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen*2, kLF, "runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen*3, 0);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen*3, "", "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\"");
}
function runQueryTextContentEventTest()
@ -2883,74 +2872,74 @@ function runQueryTextContentEventTest()
// #2
contenteditable.innerHTML = "<p>a<b>b</b>c</p><p>def</p>";
result = synthesizeQueryTextContent(0, 4);
is(result.text, "abcd", "runQueryTextContentEventTest #2 (0, 4), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, 4+kLFLen);
is(result.text, "abc" + kLF + "d", "runQueryTextContentEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 2);
is(result.text, "ab", "runQueryTextContentEventTest #2 (0, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, 2);
is(result.text, "ab", "runQueryTextContentEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1, 2);
is(result.text, "bc", "runQueryTextContentEventTest #2 (1, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1+kLFLen, 2);
is(result.text, "bc", "runQueryTextContentEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(2, 2);
is(result.text, "cd", "runQueryTextContentEventTest #2 (2, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(2+kLFLen, 2+kLFLen);
is(result.text, "c" + kLF + "d", "runQueryTextContentEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3, 1);
is(result.text, "d", "runQueryTextContentEventTest #2 (3, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3+kLFLen*2, 1);
is(result.text, "d", "runQueryTextContentEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
// #3
contenteditable.innerHTML = "<div>abc<p>def</p></div>";
result = synthesizeQueryTextContent(1, 2);
is(result.text, "bc", "runQueryTextContentEventTest #3 (1, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1+kLFLen, 2);
is(result.text, "bc", "runQueryTextContentEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1, 3);
is(result.text, "bcd", "runQueryTextContentEventTest #3 (1, 3), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1+kLFLen, 3+kLFLen);
is(result.text, "bc" + kLF + "d", "runQueryTextContentEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3, 1);
is(result.text, "d", "runQueryTextContentEventTest #3 (3, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3+kLFLen*2, 1);
is(result.text, "d", "runQueryTextContentEventTest #3 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 6);
is(result.text, "abcdef", "runQueryTextContentEventTest #3 (0, 6), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 6+kLFLen*2);
is(result.text, kLF + "abc" + kLF + "def", "runQueryTextContentEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 100);
is(result.text, "abcdef", "runQueryTextContentEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
is(result.text, kLF + "abc" + kLF + "def", "runQueryTextContentEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4, 2);
is(result.text, "ef", "runQueryTextContentEventTest #3 (4, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4+kLFLen*2, 2);
is(result.text, "ef", "runQueryTextContentEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4, 100);
is(result.text, "ef", "runQueryTextContentEventTest #3 (4, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4+kLFLen*2, 100);
is(result.text, "ef", "runQueryTextContentEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(6, 1);
is(result.text, "", "runQueryTextContentEventTest #3 (6, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(6+kLFLen*2, 1);
is(result.text, "", "runQueryTextContentEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
// #4
contenteditable.innerHTML = "<div><p>abc</p>def</div>";
result = synthesizeQueryTextContent(1, 2);
is(result.text, "bc", "runQueryTextContentEventTest #4 (1, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1+kLFLen*2, 2);
is(result.text, "bc", "runQueryTextContentEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1, 3);
is(result.text, "bcd", "runQueryTextContentEventTest #4 (1, 3), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1+kLFLen*2, 3);
is(result.text, "bcd", "runQueryTextContentEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3, 1);
is(result.text, "d", "runQueryTextContentEventTest #4 (3, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3+kLFLen*2, 1);
is(result.text, "d", "runQueryTextContentEventTest #4 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 6);
is(result.text, "abcdef", "runQueryTextContentEventTest #4 (0, 6), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 6+kLFLen*2);
is(result.text, kLF + kLF + "abcdef", "runQueryTextContentEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 100);
is(result.text, "abcdef", "runQueryTextContentEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
is(result.text, kLF + kLF + "abcdef", "runQueryTextContentEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4, 2);
is(result.text, "ef", "runQueryTextContentEventTest #4 (4, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4+kLFLen*2, 2);
is(result.text, "ef", "runQueryTextContentEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4, 100);
is(result.text, "ef", "runQueryTextContentEventTest #4 (4, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4+kLFLen*2, 100);
is(result.text, "ef", "runQueryTextContentEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(6, 1);
is(result.text, "", "runQueryTextContentEventTest #4 (6, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(6+kLFLen*2, 1);
is(result.text, "", "runQueryTextContentEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
// #5
contenteditable.innerHTML = "<br>";
@ -2964,11 +2953,11 @@ function runQueryTextContentEventTest()
// #6
contenteditable.innerHTML = "<p><br></p>";
result = synthesizeQueryTextContent(0, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, 1);
is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen*2, 1);
is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
// #7
contenteditable.innerHTML = "<br><br>";
@ -2988,17 +2977,17 @@ function runQueryTextContentEventTest()
// #8
contenteditable.innerHTML = "<p><br><br></p>";
result = synthesizeQueryTextContent(0, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #8 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, kLFLen * 2);
is(result.text, kLF + kLF, "runQueryTextContentEventTest #8 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen * 2, 1);
is(result.text, "", "runQueryTextContentEventTest #8 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, kLFLen * 2);
is(result.text, kLF + kLF, "runQueryTextContentEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen*2, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen*3, 1);
is(result.text, "", "runQueryTextContentEventTest #8 (kLFLen*3, 1), \"" + contenteditable.innerHTML + "\"");
}
function runCSSTransformTest()