Skip to content

Commit

Permalink
Fix double line break handling in Safari case (when character behind …
Browse files Browse the repository at this point in the history
…cursor)

Also add tests for it
  • Loading branch information
Oliver Pulges committed Dec 15, 2015
1 parent 35121df commit 193e611
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 56 deletions.
11 changes: 9 additions & 2 deletions src/selection/selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
119 changes: 66 additions & 53 deletions src/views/composer.observe.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
};

Expand Down Expand Up @@ -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();
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion test/views/composer_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -54,6 +54,10 @@ if (wysihtml5.browser.supported()) {
composer.observeActions.fixDeleteInTheBeginningOfBlock(composer);
equal(e.innerHTML, "<p>test<br>line1<br>line2</p>", "Merges previous and current paragraph node correctly");

e.innerHTML = "<pre>test<br>ing</pre>";
that.setCaretTo(editor, e.childNodes[0], 2);
composer.observeActions.doLineBreaksModeEnterWithCaret(composer);
equal(e.innerHTML, "<pre>test</pre><br><pre>ing</pre>", "Splits block node with double blank lines");

start();
});
Expand Down

0 comments on commit 193e611

Please sign in to comment.