0
Fork 0
mirror of https://github.com/fastmail/Squire.git synced 2024-12-22 15:23:29 -05:00

When inserting text nodes, merge them with text nodes that border it.

This fixes a bug where if you paste two text nodes in a row, an error occurs.
This commit is contained in:
Jerjou Cheng 2015-01-26 17:44:57 -08:00
parent dfed911833
commit 4ee0b7ea87
4 changed files with 129 additions and 3 deletions

View file

@ -2,7 +2,7 @@
all: install build all: install build
intall: install:
npm install npm install
clean: clean:

View file

@ -687,15 +687,78 @@ var insertNodeInRange = function ( range, node ) {
childCount = children.length; childCount = children.length;
/**
* Merge the given text node and the one on its left together into one text node.
*/
var mergeLeft = function ( node ) {
if ( node.nodeType !== TEXT_NODE ) return;
var prev = node.previousSibling;
if ( prev && prev.nodeType === TEXT_NODE ) {
// Update the end of the selection if it'll be affected by our merge
var prevIndex = indexOf.call( endContainer.childNodes, prev );
if ( prevIndex >= 0 ) {
if ( prevIndex <= endOffset ) {
endOffset--;
} else if ( prevIndex + 1 === endOffset ) {
// It ends between the nodes we're merging. So find the index into that node.
endContainer = prev;
endOffset = prev.data.length;
}
}
if ( endContainer === prev ) {
endOffset += node.data.length;
}
// The updated selection will start in the middle of the previous element now.
startContainer = prev;
startOffset = prev.data.length;
prev.appendData( node.data );
node.parentNode.removeChild( node );
return prev;
}
}
/**
* Merge the given text node and the one on its right together into one text node.
*/
var mergeRight = function ( node ) {
if ( node.nodeType !== TEXT_NODE ) return;
var next = node.nextSibling;
if ( next && next.nodeType === TEXT_NODE ) {
var nextIndex = indexOf.call( endContainer.childNodes, next );
if ( nextIndex >= 0 ) {
if ( nextIndex <= endOffset ) {
endOffset--;
} else if ( nextIndex + 1 === endOffset ) {
// It ends between the nodes we're merging. So find the index into that node.
endContainer = next;
endOffset = 0;
}
}
if ( endContainer === next ) {
endContainer = node;
endOffset += node.data.length;
}
node.appendData( next.data );
next.parentNode.removeChild( next );
}
}
if ( startOffset === childCount) { if ( startOffset === childCount) {
startContainer.appendChild( node ); startContainer.appendChild( node );
} else { } else {
startContainer.insertBefore( node, children[ startOffset ] ); startContainer.insertBefore( node, children[ startOffset ] );
} }
if ( startContainer === endContainer ) { if ( startContainer === endContainer ) {
endOffset += children.length - childCount; endOffset += children.length - childCount;
} }
// If we split a text node, merge the text nodes back together
var insertedNode = children[ startOffset ];
mergeRight( mergeLeft( insertedNode ) || insertedNode );
range.setStart( startContainer, startOffset ); range.setStart( startContainer, startOffset );
range.setEnd( endContainer, endOffset ); range.setEnd( endContainer, endOffset );
}; };

File diff suppressed because one or more lines are too long

View file

@ -103,15 +103,78 @@ var insertNodeInRange = function ( range, node ) {
childCount = children.length; childCount = children.length;
/**
* Merge the given text node and the one on its left together into one text node.
*/
var mergeLeft = function ( node ) {
if ( node.nodeType !== TEXT_NODE ) return;
var prev = node.previousSibling;
if ( prev && prev.nodeType === TEXT_NODE ) {
// Update the end of the selection if it'll be affected by our merge
var prevIndex = indexOf.call( endContainer.childNodes, prev );
if ( prevIndex >= 0 ) {
if ( prevIndex <= endOffset ) {
endOffset--;
} else if ( prevIndex + 1 === endOffset ) {
// It ends between the nodes we're merging. So find the index into that node.
endContainer = prev;
endOffset = prev.data.length;
}
}
if ( endContainer === prev ) {
endOffset += node.data.length;
}
// The updated selection will start in the middle of the previous element now.
startContainer = prev;
startOffset = prev.data.length;
prev.appendData( node.data );
node.parentNode.removeChild( node );
return prev;
}
}
/**
* Merge the given text node and the one on its right together into one text node.
*/
var mergeRight = function ( node ) {
if ( node.nodeType !== TEXT_NODE ) return;
var next = node.nextSibling;
if ( next && next.nodeType === TEXT_NODE ) {
var nextIndex = indexOf.call( endContainer.childNodes, next );
if ( nextIndex >= 0 ) {
if ( nextIndex <= endOffset ) {
endOffset--;
} else if ( nextIndex + 1 === endOffset ) {
// It ends between the nodes we're merging. So find the index into that node.
endContainer = next;
endOffset = 0;
}
}
if ( endContainer === next ) {
endContainer = node;
endOffset += node.data.length;
}
node.appendData( next.data );
next.parentNode.removeChild( next );
}
}
if ( startOffset === childCount) { if ( startOffset === childCount) {
startContainer.appendChild( node ); startContainer.appendChild( node );
} else { } else {
startContainer.insertBefore( node, children[ startOffset ] ); startContainer.insertBefore( node, children[ startOffset ] );
} }
if ( startContainer === endContainer ) { if ( startContainer === endContainer ) {
endOffset += children.length - childCount; endOffset += children.length - childCount;
} }
// If we split a text node, merge the text nodes back together
var insertedNode = children[ startOffset ];
mergeRight( mergeLeft( insertedNode ) || insertedNode );
range.setStart( startContainer, startOffset ); range.setStart( startContainer, startOffset );
range.setEnd( endContainer, endOffset ); range.setEnd( endContainer, endOffset );
}; };