From e60e81a9d4e6b70f0cdeee48bb58a6174118eab3 Mon Sep 17 00:00:00 2001 From: Oliver Pulges Date: Tue, 18 Aug 2015 14:11:43 +0300 Subject: [PATCH] Fixes node.normalize polyfill failing to restore cursor in some cases --- src/polyfills.js | 15 +++++++++-- test/polyfills_test.js | 60 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/polyfills.js b/src/polyfills.js index 5f421fb..832a251 100644 --- a/src/polyfills.js +++ b/src/polyfills.js @@ -367,6 +367,8 @@ wysihtml5.polyfills = function(win, doc) { return all; }; + + var normalizeFix = function() { var f = Node.prototype.normalize; var nf = function() { @@ -374,13 +376,15 @@ wysihtml5.polyfills = function(win, doc) { s = this.ownerDocument.defaultView.getSelection(), anode = s.anchorNode, aoffset = s.anchorOffset, + aelement = anode && anode.nodeType === 1 && anode.childNodes.length > 0 ? anode.childNodes[aoffset] : undefined, fnode = s.focusNode, foffset = s.focusOffset, + felement = fnode && fnode.nodeType === 1 && foffset > 0 ? fnode.childNodes[foffset -1] : undefined, r = this.ownerDocument.createRange(), prevTxt = texts.shift(), curText = prevTxt ? texts.shift() : null; - if ((anode === fnode && foffset < aoffset) || (anode !== fnode && (anode.compareDocumentPosition(fnode) & Node.DOCUMENT_POSITION_PRECEDING))) { + if ((anode === fnode && foffset < aoffset) || (anode !== fnode && (anode.compareDocumentPosition(fnode) & Node.DOCUMENT_POSITION_PRECEDING) && !(anode.compareDocumentPosition(fnode) & Node.DOCUMENT_POSITION_CONTAINS))) { fnode = [anode, anode = fnode][0]; foffset = [aoffset, aoffset = foffset][0]; } @@ -404,13 +408,20 @@ wysihtml5.polyfills = function(win, doc) { } } + if (felement) { + foffset = Array.prototype.indexOf.call(felement.parentNode.childNodes, felement) + 1; + } + + if (aelement) { + aoffset = Array.prototype.indexOf.call(aelement.parentNode.childNodes, aelement); + } + if (anode && anode.parentNode && fnode && fnode.parentNode) { r.setStart(anode, aoffset); r.setEnd(fnode, foffset); s.removeAllRanges(); s.addRange(r); } - }; Node.prototype.normalize = nf; }; diff --git a/test/polyfills_test.js b/test/polyfills_test.js index d8244f5..cab0cc9 100644 --- a/test/polyfills_test.js +++ b/test/polyfills_test.js @@ -33,3 +33,63 @@ test("Check element.normalize is preserving caret position", function() { ok(s.anchorNode === this.editable.firstChild, "Anchor element is correct after normalize"); ok(s.anchorOffset === 7 , "Anchor offset is correct after normalize"); }); + +test("Check element.normalize is preserving selection", function() { + var text1 = document.createTextNode('test'), + text2 = document.createTextNode('foo'), + text3 = document.createTextNode('third'), + text4 = document.createTextNode('fourth'), + br = document.createElement('br'), + r = rangy.createRange(), + s; + + this.editable.appendChild(text1); + this.editable.appendChild(text2); + this.editable.appendChild(br); + this.editable.appendChild(text3); + this.editable.appendChild(text4); + + r.setStart(text2, 0); + r.setEndAfter(br); + r.select(); + + this.editable.normalize(); + s = rangy.getSelection(); + + ok(this.editable.childNodes.length === 3, "Normalize merged nodes"); + equal(s.anchorNode, this.editable.firstChild, "Anchor element is correct after normalize"); + equal(s.anchorOffset, 4 , "Anchor offset is correct after normalize"); + equal(s.focusNode, this.editable, "Focus element is correct after normalize"); + equal(s.focusOffset, 2 , "Focus offset is correct after normalize"); +}); + + +test("Check element.normalize is preserving selection 2", function() { + var text1 = document.createTextNode('test'), + text2 = document.createTextNode('foo'), + text3 = document.createTextNode('third'), + text4 = document.createTextNode('fourth'), + br = document.createElement('br'), + r = rangy.createRange(), + s; + + this.editable.appendChild(text1); + this.editable.appendChild(text2); + this.editable.appendChild(br); + this.editable.appendChild(text3); + this.editable.appendChild(text4); + + r.setStartBefore(br); + r.setEnd(text4, 0); + r.select(); + + this.editable.normalize(); + s = rangy.getSelection(); + + ok(this.editable.childNodes.length === 3, "Normalize merged nodes"); + equal(s.anchorNode, this.editable, "Anchor element is correct after normalize"); + equal(s.anchorOffset, 1, "Anchor offset is correct after normalize"); + equal(s.focusNode, this.editable.childNodes[2], "Focus element is correct after normalize"); + equal(s.focusOffset, 5 , "Focus offset is correct after normalize"); +}); +