From 885c25ac6af506e3e6c4d1b37757cb8759b64322 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 12 Apr 2018 06:43:17 +0300 Subject: [PATCH 1/4] Cleanup after ordered/unordered list removal in WebKit --- src/js/util.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/js/util.js b/src/js/util.js index c2bf06c45..dcd5c81e9 100644 --- a/src/js/util.js +++ b/src/js/util.js @@ -675,6 +675,18 @@ cleanListDOM: function (ownerDocument, element) { if (element.nodeName.toLowerCase() !== 'li') { + if (element.nodeName.toLowerCase() === 'span') { + var newNode = ownerDocument.createElement('p'); + newNode.innerHTML = element.innerHTML; + element.parentNode.insertBefore(newNode, element); + + if (element.nextSibling.nodeName.toLowerCase() === 'br') { + element.nextSibling.remove(); + } + + element.remove(); + } + return; } From 8d3fcb9af8349e27f0ba27889df85042b5eec690 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 12 Apr 2018 07:09:05 +0300 Subject: [PATCH 2/4] Fix multiline cleanup --- src/js/util.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/js/util.js b/src/js/util.js index dcd5c81e9..0d15d64bc 100644 --- a/src/js/util.js +++ b/src/js/util.js @@ -675,16 +675,21 @@ cleanListDOM: function (ownerDocument, element) { if (element.nodeName.toLowerCase() !== 'li') { - if (element.nodeName.toLowerCase() === 'span') { - var newNode = ownerDocument.createElement('p'); - newNode.innerHTML = element.innerHTML; - element.parentNode.insertBefore(newNode, element); + var newNode, nextNode, + node = element; - if (element.nextSibling.nodeName.toLowerCase() === 'br') { - element.nextSibling.remove(); + while (node && node.nodeName.toLowerCase() === 'span') { + newNode = ownerDocument.createElement('p'); + newNode.innerHTML = node.innerHTML; + node.parentNode.insertBefore(newNode, node); + + if (node.nextSibling.nodeName.toLowerCase() === 'br') { + node.nextSibling.remove(); } - element.remove(); + nextNode = node.nextSibling; + node.remove(); + node = nextNode; } return; From 3a9643cc44dfaa2c04966026a24458afac066277 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 12 Apr 2018 13:04:27 +0300 Subject: [PATCH 3/4] Add a test case --- spec/content.spec.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/spec/content.spec.js b/spec/content.spec.js index 56f584c09..c5f1b8ac7 100644 --- a/spec/content.spec.js +++ b/spec/content.spec.js @@ -50,6 +50,21 @@ describe('Content TestCase', function () { } }); + it('should cleanup after list is removed', function () { + this.el.innerHTML = '
  • lorem
  • ipsum
  • dolor
'; + var editor = this.newMediumEditor('.editor', { + toolbar: { + buttons: ['unorderedlist'] + } + }), + target = editor.elements[0].querySelector('li'), + toolbar = editor.getExtensionByName('toolbar'); + + selectElementContentsAndFire(target); + fireEvent(toolbar.getToolbarElement().querySelector('[data-action="insertunorderedlist"]'), 'click'); + expect(this.el.innerHTML).toBe('

lorem

  • ipsum
  • dolor
'); + }); + describe('when the tab key is pressed', function () { it('should indent when within an
  • ', function () { this.el.innerHTML = '
    1. lorem
    2. ipsum
    '; From 1192a15cb74a3e152712bd7eed943c64d9de0a9c Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 12 Apr 2018 13:05:48 +0300 Subject: [PATCH 4/4] Fix for firefox & keep same selection --- src/js/core.js | 2 +- src/js/util.js | 56 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/js/core.js b/src/js/core.js index 9def0f452..d2b3a01a1 100644 --- a/src/js/core.js +++ b/src/js/core.js @@ -939,7 +939,7 @@ // do some DOM clean-up for known browser issues after the action if (action === 'insertunorderedlist' || action === 'insertorderedlist') { - MediumEditor.util.cleanListDOM(this.options.ownerDocument, this.getSelectedParentElement()); + MediumEditor.util.cleanListDOM(this.options.contentWindow, this.options.ownerDocument, this.getSelectedParentElement()); } this.checkSelection(); diff --git a/src/js/util.js b/src/js/util.js index 0d15d64bc..92af85d1e 100644 --- a/src/js/util.js +++ b/src/js/util.js @@ -673,36 +673,58 @@ return false; }, - cleanListDOM: function (ownerDocument, element) { + cleanListDOM: function (contentWindow, ownerDocument, element) { if (element.nodeName.toLowerCase() !== 'li') { - var newNode, nextNode, + var selection = contentWindow.getSelection(), + newRange = ownerDocument.createRange(), + oldRange = selection.getRangeAt(0), + startContainer = oldRange.startContainer, + startOffset = oldRange.startOffset, + endContainer = oldRange.endContainer, + endOffset = oldRange.endOffset, + node, newNode, nextNode; + + if (element.nodeName.toLowerCase() === 'span') { + // Chrome unwraps removed li elements into a span node = element; + } else { + // FF leaves them as text nodes + node = startContainer; + } - while (node && node.nodeName.toLowerCase() === 'span') { - newNode = ownerDocument.createElement('p'); - newNode.innerHTML = node.innerHTML; - node.parentNode.insertBefore(newNode, node); + while (node) { + if (node.nodeName.toLowerCase() !== 'span' && node.nodeName.toLowerCase() !== '#text') { + break; + } - if (node.nextSibling.nodeName.toLowerCase() === 'br') { + if (node.nextSibling && node.nextSibling.nodeName.toLowerCase() === 'br') { node.nextSibling.remove(); } nextNode = node.nextSibling; - node.remove(); + + newNode = ownerDocument.createElement('p'); + node.parentNode.replaceChild(newNode, node); + newNode.appendChild(node); + node = nextNode; } - return; - } - - var list = element.parentElement; + // Restore selection + newRange.setStart(startContainer, startOffset); + newRange.setEnd(endContainer, endOffset); + selection.removeAllRanges(); + selection.addRange(newRange); + } else { + var list = element.parentElement; - if (list.parentElement.nodeName.toLowerCase() === 'p') { // yes we need to clean up - Util.unwrap(list.parentElement, ownerDocument); + if (list.parentElement.nodeName.toLowerCase() === 'p') { // yes we need to clean up + Util.unwrap(list.parentElement, ownerDocument); - // move cursor at the end of the text inside the list - // for some unknown reason, the cursor is moved to end of the "visual" line - MediumEditor.selection.moveCursor(ownerDocument, element.firstChild, element.firstChild.textContent.length); + // move cursor at the end of the text inside the list + // for some unknown reason, the cursor is moved to end of the "visual" line + MediumEditor.selection.moveCursor(ownerDocument, element.firstChild, element.firstChild.textContent.length); + } } },