diff --git a/src/selection/selection.js b/src/selection/selection.js index ae759cb..537d2be 100644 --- a/src/selection/selection.js +++ b/src/selection/selection.js @@ -492,10 +492,17 @@ nextNode = caretNode.nextSibling; } } else { - caretNode = r[0].startContainer; + if (r[0].startOffset === 0 && r[0].startContainer.previousSibling) { + caretNode = r[0].startContainer.previousSibling; + if (caretNode.nodeType === 3) { + offset = caretNode.data.length; + } + } else { + caretNode = r[0].startContainer; + offset = r[0].startOffset; + } prevNode = caretNode.previousSibling; nextNode = caretNode.nextSibling; - offset = r[0].startOffset; } return { diff --git a/src/views/composer.observe.js b/src/views/composer.observe.js index e836494..0d2d9aa 100644 --- a/src/views/composer.observe.js +++ b/src/views/composer.observe.js @@ -175,6 +175,70 @@ } } this.tableSelection = wysihtml5.quirks.tableCellsSelection(this.element, this.parent); + }, + + // Fixes some misbehaviours of enters in linebreaks mode (natively a bit unsupported feature) + // Returns true if some corrections is applied so events know when to prevent default + doLineBreaksModeEnterWithCaret: function(composer) { + var breakNodes = "p, pre, div, blockquote", + caretInfo, parent, txtNode, + ret = false; + + caretInfo = composer.selection.getNodesNearCaret(); + if (caretInfo) { + + if (caretInfo.caretNode || caretInfo.nextNode) { + parent = dom.getParentElement(caretInfo.caretNode || caretInfo.nextNode, { query: breakNodes }, 2); + if (parent === composer.element) { + parent = undefined; + } + } + + if (parent && caretInfo.caretNode) { + if (domNode(caretInfo.caretNode).is.lineBreak()) { + + if (composer.config.doubleLineBreakEscapesBlock) { + // Double enter (enter on blank line) exits block element in useLineBreaks mode. + ret = true; + caretInfo.caretNode.parentNode.removeChild(caretInfo.caretNode); + + // Ensure surplous line breaks are not added to preceding element + if (domNode(caretInfo.nextNode).is.lineBreak()) { + caretInfo.nextNode.parentNode.removeChild(caretInfo.nextNode); + } + + var brNode = composer.doc.createElement('br'); + if (domNode(caretInfo.nextNode).is.lineBreak() && caretInfo.nextNode === parent.lastChild) { + parent.parentNode.insertBefore(brNode, parent.nextSibling); + } else { + composer.selection.splitElementAtCaret(parent, brNode); + } + + // Ensure surplous blank lines are not added to preceding element + if (caretInfo.nextNode && caretInfo.nextNode.nodeType === 3) { + // Replaces blank lines at the beginning of textnode + caretInfo.nextNode.data = caretInfo.nextNode.data.replace(/^ *[\r\n]+/, ''); + } + composer.selection.setBefore(brNode); + } + + } else if (caretInfo.caretNode.nodeType === 3 && wysihtml5.browser.hasCaretBlockElementIssue() && caretInfo.textOffset === caretInfo.caretNode.data.length && !caretInfo.nextNode) { + + // This fixes annoying webkit issue when you press enter at the end of a block then seemingly nothing happens. + // in reality one line break is generated and cursor is reported after it, but when entering something cursor jumps before the br + ret = true; + var br1 = composer.doc.createElement('br'), + br2 = composer.doc.createElement('br'), + f = composer.doc.createDocumentFragment(); + f.appendChild(br1); + f.appendChild(br2); + composer.selection.insertNode(f); + composer.selection.setBefore(br2); + + } + } + } + return ret; } }; @@ -215,59 +279,8 @@ caretInfo, parent, txtNode; if (composer.selection.isCollapsed()) { - caretInfo = composer.selection.getNodesNearCaret(); - if (caretInfo) { - - if (caretInfo.caretNode || caretInfo.nextNode) { - parent = dom.getParentElement(caretInfo.caretNode || caretInfo.nextNode, { query: breakNodes }, 2); - if (parent === composer.element) { - parent = undefined; - } - } - - if (parent && caretInfo.caretNode) { - if (domNode(caretInfo.caretNode).is.lineBreak()) { - - if (composer.config.doubleLineBreakEscapesBlock) { - // Double enter (enter on blank line) exits block element in useLineBreaks mode. - event.preventDefault(); - caretInfo.caretNode.parentNode.removeChild(caretInfo.caretNode); - - // Ensure surplous line breaks are not added to preceding element - if (domNode(caretInfo.nextNode).is.lineBreak()) { - caretInfo.nextNode.parentNode.removeChild(caretInfo.nextNode); - } - - var brNode = composer.doc.createElement('br'); - if (domNode(caretInfo.nextNode).is.lineBreak() && caretInfo.nextNode === parent.lastChild) { - parent.parentNode.insertBefore(brNode, parent.nextSibling); - } else { - composer.selection.splitElementAtCaret(parent, brNode); - } - - // Ensure surplous blank lines are not added to preceding element - if (caretInfo.nextNode && caretInfo.nextNode.nodeType === 3) { - // Replaces blank lines at the beginning of textnode - caretInfo.nextNode.data = caretInfo.nextNode.data.replace(/^ *[\r\n]+/, ''); - } - composer.selection.setBefore(brNode); - } - - } else if (caretInfo.caretNode.nodeType === 3 && wysihtml5.browser.hasCaretBlockElementIssue() && caretInfo.textOffset === caretInfo.caretNode.data.length && !caretInfo.nextNode) { - - // This fixes annoying webkit issue when you press enter at the end of a block then seemingly nothing happens. - // in reality one line break is generated and cursor is reported after it, but when entering something cursor jumps before the br - event.preventDefault(); - var br1 = composer.doc.createElement('br'), - br2 = composer.doc.createElement('br'), - f = composer.doc.createDocumentFragment(); - f.appendChild(br1); - f.appendChild(br2); - composer.selection.insertNode(f); - composer.selection.setBefore(br2); - - } - } + if (actions.doLineBreaksModeEnterWithCaret(composer)) { + event.preventDefault(); } } } diff --git a/test/views/composer_test.js b/test/views/composer_test.js index 89e1a02..f826f56 100644 --- a/test/views/composer_test.js +++ b/test/views/composer_test.js @@ -37,7 +37,7 @@ if (wysihtml5.browser.supported()) { // Editor initiation tests asyncTest("fixDeleteInTheBeginningOfBlock", function() { - expect(2); + expect(3); var that = this; var editor = new wysihtml5.Editor(this.editableArea, this.rules); editor.on("load", function() { @@ -54,6 +54,10 @@ if (wysihtml5.browser.supported()) { composer.observeActions.fixDeleteInTheBeginningOfBlock(composer); equal(e.innerHTML, "
test
line1
line2
test"; + that.setCaretTo(editor, e.childNodes[0], 2); + composer.observeActions.doLineBreaksModeEnterWithCaret(composer); + equal(e.innerHTML, "
ing
test
ing", "Splits block node with double blank lines"); start(); });