Bug 570144 - After pressing Enter, editable DIVs in list items are duplicated; r=ehsan
authorFabien Cazenave <kaze@kompozer.net>
Mon, 12 Sep 2011 15:25:38 -0400
changeset 77938 e4f2aa3c5bc2e2de5d9569603d5d80c859f79f21
parent 77937 88e23391bc2c99799a4a8c112fc91230179b5ccf
child 77939 d3af41c6bf0b13cdc08e1de33399557963782c87
push id340
push userclegnitto@mozilla.com
push dateTue, 08 Nov 2011 22:56:33 +0000
treeherdermozilla-beta@f745dc151615 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs570144
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 570144 - After pressing Enter, editable DIVs in list items are duplicated; r=ehsan
editor/libeditor/html/nsHTMLEditRules.cpp
editor/libeditor/html/tests/Makefile.in
editor/libeditor/html/tests/test_bug460740.html
editor/libeditor/html/tests/test_bug570144.html
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -1607,17 +1607,17 @@ nsHTMLEditRules::WillInsertBreak(nsISele
     res = mHTMLEditor->GetLengthOfDOMNode(blockParent, blockLen);
     NS_ENSURE_SUCCESS(res, res);
     nsCOMPtr<nsIDOMNode> brNode;
     res = mHTMLEditor->CreateBR(blockParent, blockLen, address_of(brNode));
     NS_ENSURE_SUCCESS(res, res);
   }
   
   nsCOMPtr<nsIDOMNode> listItem = IsInListItem(blockParent);
-  if (listItem)
+  if (listItem && listItem != hostNode)
   {
     res = ReturnInListItem(aSelection, listItem, node, offset);
     *aHandled = PR_TRUE;
     return NS_OK;
   }
   
   // headers: close (or split) header
   else if (nsHTMLEditUtils::IsHeader(blockParent))
@@ -6502,29 +6502,31 @@ nsHTMLEditRules::MakeTransitionList(nsCO
 
 /********************************************************
  *  main implementation methods 
  ********************************************************/
  
 ///////////////////////////////////////////////////////////////////////////
 // IsInListItem: if aNode is the descendant of a listitem, return that li.
 //               But table element boundaries are stoppers on the search.
+//               Also stops on the active editor host (contenteditable).
 //               Also test if aNode is an li itself.
 //                       
 nsCOMPtr<nsIDOMNode> 
 nsHTMLEditRules::IsInListItem(nsIDOMNode *aNode)
 {
   NS_ENSURE_TRUE(aNode, nsnull);  
   if (nsHTMLEditUtils::IsListItem(aNode)) return aNode;
   
   nsCOMPtr<nsIDOMNode> parent, tmp;
   aNode->GetParentNode(getter_AddRefs(parent));
   
   while (parent)
   {
+    if (!mHTMLEditor->IsNodeInActiveEditor(parent)) return nsnull;
     if (nsHTMLEditUtils::IsTableElement(parent)) return nsnull;
     if (nsHTMLEditUtils::IsListItem(parent)) return parent;
     tmp=parent; tmp->GetParentNode(getter_AddRefs(parent));
   }
   return nsnull;
 }
 
 
--- a/editor/libeditor/html/tests/Makefile.in
+++ b/editor/libeditor/html/tests/Makefile.in
@@ -68,16 +68,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug487524.html \
 		test_bug520189.html \
 		test_bug525389.html \
 		test_bug537046.html \
 		test_bug549262.html \
 		file_bug549262.html \
 		test_bug550434.html \
 		test_bug551704.html \
+		test_bug570144.html \
 		test_bug592592.html \
 		test_bug597784.html \
 		test_bug599322.html \
 		test_bug607584.html \
 		test_bug611182.html \
 		test_bug612447.html \
 		test_bug620906.html \
 		test_bug622371.html \
--- a/editor/libeditor/html/tests/test_bug460740.html
+++ b/editor/libeditor/html/tests/test_bug460740.html
@@ -79,18 +79,18 @@ function split(element, caretPos) {
     case CARET_END:
       pos = len;
       break;
   }
 
   // put the caret on the requested position
   var range = document.createRange();
   var sel = window.getSelection();
-  range.setStart(element.firstChild, len);
-  range.setEnd(element.firstChild, len);
+  range.setStart(element.firstChild, pos);
+  range.setEnd(element.firstChild, pos);
   sel.addRange(range);
   
   // simulates a [Return] keypress
   synthesizeKey("VK_RETURN", {});
 }
 
 // count the number of non-BR elements in #content
 function getBlockCount() {
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_bug570144.html
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=570144
+-->
+<head>
+  <title>Test for Bug 570144</title>
+  <script type="application/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>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=570144">Mozilla Bug 570144</a>
+<p id="display"></p>
+<div id="content">
+  <!-- editable paragraphs in list item -->
+  <section id="test1">
+    <ol>
+      <li><p contenteditable>foo</p></li>
+    </ol>
+    <ul>
+      <li><p contenteditable>foo</p></li>
+    </ul>
+    <dl>
+      <dt>foo</dt>
+      <dd><p contenteditable>bar</p></dd>
+    </dl>
+  </section>
+  <!-- paragraphs in editable list item -->
+  <section id="test2">
+    <ol>
+      <li contenteditable><p>foo</p></li>
+    </ol>
+    <ul>
+      <li contenteditable><p>foo</p></li>
+    </ul>
+    <dl>
+      <dt>foo</dt>
+      <dd contenteditable><p>bar</p></dd>
+    </dl>
+  </section>
+  <!-- paragraphs in editable list -->
+  <section id="test3">
+    <ol contenteditable>
+      <li><p>foo</p></li>
+    </ol>
+    <ul contenteditable>
+      <li><p>foo</p></li>
+    </ul>
+    <dl contenteditable>
+      <dt>foo</dt>
+      <dd><p>bar</p></dd>
+    </dl>
+  </section>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 570144 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+function try2split(list) {
+  var editor = list.hasAttribute("contenteditable")
+             ? list : list.querySelector("*[contenteditable]");
+  editor.focus();
+  // put the caret at the end of the paragraph
+  var selection = window.getSelection();
+  if (editor.nodeName.toLowerCase() == "p")
+    selection.selectAllChildren(editor);
+  else
+    selection.selectAllChildren(editor.querySelector("p"));
+  selection.collapseToEnd();
+  // simulate a [Return] keypress
+  synthesizeKey("VK_RETURN", {});
+}
+
+function testSection(element, context, shouldCreateLI, shouldCreateP) {
+  var nbLI = shouldCreateLI ? 2 : 1; // number of expected list items
+  var nbP  = shouldCreateP  ? 2 : 1; // number of expected paragraphs
+
+  function message(nodeName, dup) {
+    return context + ":[Return] should " + (dup ? "" : "not ")
+                   + "create another <" + nodeName + ">."
+  }
+  var msgP  = message("p",  shouldCreateP);
+  var msgLI = message("li", shouldCreateLI);
+  var msgDT = message("dt", shouldCreateLI);
+  var msgDD = message("dd", false);
+
+  const ol = element.querySelector("ol");
+  try2split(ol);
+  is(ol.querySelectorAll("li").length, nbLI, msgLI);
+  is(ol.querySelectorAll("p").length, nbP, msgP);
+
+  const ul = element.querySelector("ul");
+  try2split(ul);
+  is(ul.querySelectorAll("li").length, nbLI, msgLI);
+  is(ul.querySelectorAll("p").length, nbP, msgP);
+
+  const dl = element.querySelector("dl");
+  try2split(dl);
+  is(dl.querySelectorAll("dt").length, nbLI, msgDT);
+  is(dl.querySelectorAll("dd").length, 1, msgDD);
+  is(dl.querySelectorAll("p").length, nbP, msgP);
+}
+
+function runTests() {
+  testSection(document.getElementById("test1"), "editable paragraph in list item", false, false);
+  testSection(document.getElementById("test2"), "paragraph in editable list item", false, true);
+  testSection(document.getElementById("test3"), "paragraph in editable list",      true,  false);
+  /* Note: concerning #test3, it would be preferrable that [Return] creates
+   * another paragraph in another list item (i.e. last argument = 'true').
+   * Currently it just creates an empty list item, which is acceptable.
+   */
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>