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 76898 e4f2aa3c5bc2e2de5d9569603d5d80c859f79f21
parent 76897 88e23391bc2c99799a4a8c112fc91230179b5ccf
child 76899 d3af41c6bf0b13cdc08e1de33399557963782c87
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersehsan
bugs570144
milestone9.0a1
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>