0
Fork 0
mirror of https://github.com/fastmail/Squire.git synced 2025-01-03 05:00:13 -05:00

Improve merging edges of inserted tree fragment.

Fixes #87.
This commit is contained in:
Neil Jenkins 2015-06-12 17:48:06 +07:00
parent fc80de80d7
commit e59e6418af
3 changed files with 102 additions and 50 deletions

View file

@ -788,15 +788,13 @@ var insertTreeFragmentIntoRange = function ( range, frag ) {
// Move range down into text nodes // Move range down into text nodes
moveRangeBoundariesDownTree( range ); moveRangeBoundariesDownTree( range );
// If inline, just insert at the current position.
if ( allInline ) { if ( allInline ) {
// If inline, just insert at the current position.
insertNodeInRange( range, frag ); insertNodeInRange( range, frag );
range.collapse( false ); range.collapse( false );
} } else {
// Otherwise, split up to blockquote (if a parent) or body, insert inline // Otherwise...
// before and after split and insert block in between split, then merge // 1. Split up to blockquote (if a parent) or body
// containers.
else {
var splitPoint = range.startContainer, var splitPoint = range.startContainer,
nodeAfterSplit = split( splitPoint, range.startOffset, nodeAfterSplit = split( splitPoint, range.startOffset,
getNearest( splitPoint.parentNode, 'BLOCKQUOTE' ) || getNearest( splitPoint.parentNode, 'BLOCKQUOTE' ) ||
@ -807,8 +805,10 @@ var insertTreeFragmentIntoRange = function ( range, frag ) {
endContainer = nodeAfterSplit, endContainer = nodeAfterSplit,
endOffset = 0, endOffset = 0,
parent = nodeAfterSplit.parentNode, parent = nodeAfterSplit.parentNode,
child, node; child, node, prev, next;
// 2. Move down into edge either side of split and insert any inline
// nodes at the beginning/end of the fragment
while ( ( child = startContainer.lastChild ) && while ( ( child = startContainer.lastChild ) &&
child.nodeType === ELEMENT_NODE && child.nodeType === ELEMENT_NODE &&
child.nodeName !== 'BR' ) { child.nodeName !== 'BR' ) {
@ -828,32 +828,58 @@ var insertTreeFragmentIntoRange = function ( range, frag ) {
endOffset += 1; endOffset += 1;
} }
// Fix cursor then insert block(s) // 3. Fix cursor then insert block(s) in the fragment
node = frag; node = frag;
while ( node = getNextBlock( node ) ) { while ( node = getNextBlock( node ) ) {
fixCursor( node ); fixCursor( node );
} }
parent.insertBefore( frag, nodeAfterSplit ); parent.insertBefore( frag, nodeAfterSplit );
// Remove empty nodes created by split and merge inserted containers // 4. Remove empty nodes created either side of split, then
// with edges of split // merge containers at the edges.
node = nodeAfterSplit.previousSibling; next = nodeBeforeSplit.nextSibling;
if ( !nodeAfterSplit.textContent ) { node = getPreviousBlock( next );
parent.removeChild( nodeAfterSplit ); if ( !/\S/.test( node.textContent ) ) {
} else { do {
mergeContainers( nodeAfterSplit ); parent = node.parentNode;
parent.removeChild( node );
node = parent;
} while ( parent && !parent.lastChild &&
parent.nodeName !== 'BODY' );
} }
if ( !nodeAfterSplit.parentNode ) { if ( !nodeBeforeSplit.parentNode ) {
endContainer = node; nodeBeforeSplit = next.previousSibling;
endOffset = getLength( endContainer ); }
if ( !startContainer.parentNode ) {
startContainer = nodeBeforeSplit;
startOffset = nodeBeforeSplit.childNodes.length;
}
// Merge inserted containers with edges of split
if ( isContainer( next ) ) {
mergeContainers( next );
} }
if ( !nodeBeforeSplit.textContent) { prev = nodeAfterSplit.previousSibling;
startContainer = nodeBeforeSplit.nextSibling; node = isBlock( nodeAfterSplit ) ?
startOffset = 0; nodeAfterSplit : getNextBlock( nodeAfterSplit );
parent.removeChild( nodeBeforeSplit ); if ( !/\S/.test( node.textContent ) ) {
} else { do {
mergeContainers( nodeBeforeSplit ); parent = node.parentNode;
parent.removeChild( node );
node = parent;
} while ( parent && !parent.lastChild &&
parent.nodeName !== 'BODY' );
}
if ( !nodeAfterSplit.parentNode ) {
nodeAfterSplit = prev.nextSibling;
}
if ( !endOffset ) {
endContainer = prev;
endOffset = prev.childNodes.length;
}
// Merge inserted containers with edges of split
if ( isContainer( nodeAfterSplit ) ) {
mergeContainers( nodeAfterSplit );
} }
range.setStart( startContainer, startOffset ); range.setStart( startContainer, startOffset );

File diff suppressed because one or more lines are too long

View file

@ -187,15 +187,13 @@ var insertTreeFragmentIntoRange = function ( range, frag ) {
// Move range down into text nodes // Move range down into text nodes
moveRangeBoundariesDownTree( range ); moveRangeBoundariesDownTree( range );
// If inline, just insert at the current position.
if ( allInline ) { if ( allInline ) {
// If inline, just insert at the current position.
insertNodeInRange( range, frag ); insertNodeInRange( range, frag );
range.collapse( false ); range.collapse( false );
} } else {
// Otherwise, split up to blockquote (if a parent) or body, insert inline // Otherwise...
// before and after split and insert block in between split, then merge // 1. Split up to blockquote (if a parent) or body
// containers.
else {
var splitPoint = range.startContainer, var splitPoint = range.startContainer,
nodeAfterSplit = split( splitPoint, range.startOffset, nodeAfterSplit = split( splitPoint, range.startOffset,
getNearest( splitPoint.parentNode, 'BLOCKQUOTE' ) || getNearest( splitPoint.parentNode, 'BLOCKQUOTE' ) ||
@ -206,8 +204,10 @@ var insertTreeFragmentIntoRange = function ( range, frag ) {
endContainer = nodeAfterSplit, endContainer = nodeAfterSplit,
endOffset = 0, endOffset = 0,
parent = nodeAfterSplit.parentNode, parent = nodeAfterSplit.parentNode,
child, node; child, node, prev, next;
// 2. Move down into edge either side of split and insert any inline
// nodes at the beginning/end of the fragment
while ( ( child = startContainer.lastChild ) && while ( ( child = startContainer.lastChild ) &&
child.nodeType === ELEMENT_NODE && child.nodeType === ELEMENT_NODE &&
child.nodeName !== 'BR' ) { child.nodeName !== 'BR' ) {
@ -227,32 +227,58 @@ var insertTreeFragmentIntoRange = function ( range, frag ) {
endOffset += 1; endOffset += 1;
} }
// Fix cursor then insert block(s) // 3. Fix cursor then insert block(s) in the fragment
node = frag; node = frag;
while ( node = getNextBlock( node ) ) { while ( node = getNextBlock( node ) ) {
fixCursor( node ); fixCursor( node );
} }
parent.insertBefore( frag, nodeAfterSplit ); parent.insertBefore( frag, nodeAfterSplit );
// Remove empty nodes created by split and merge inserted containers // 4. Remove empty nodes created either side of split, then
// with edges of split // merge containers at the edges.
node = nodeAfterSplit.previousSibling; next = nodeBeforeSplit.nextSibling;
if ( !nodeAfterSplit.textContent ) { node = getPreviousBlock( next );
parent.removeChild( nodeAfterSplit ); if ( !/\S/.test( node.textContent ) ) {
} else { do {
mergeContainers( nodeAfterSplit ); parent = node.parentNode;
parent.removeChild( node );
node = parent;
} while ( parent && !parent.lastChild &&
parent.nodeName !== 'BODY' );
} }
if ( !nodeAfterSplit.parentNode ) { if ( !nodeBeforeSplit.parentNode ) {
endContainer = node; nodeBeforeSplit = next.previousSibling;
endOffset = getLength( endContainer ); }
if ( !startContainer.parentNode ) {
startContainer = nodeBeforeSplit;
startOffset = nodeBeforeSplit.childNodes.length;
}
// Merge inserted containers with edges of split
if ( isContainer( next ) ) {
mergeContainers( next );
} }
if ( !nodeBeforeSplit.textContent) { prev = nodeAfterSplit.previousSibling;
startContainer = nodeBeforeSplit.nextSibling; node = isBlock( nodeAfterSplit ) ?
startOffset = 0; nodeAfterSplit : getNextBlock( nodeAfterSplit );
parent.removeChild( nodeBeforeSplit ); if ( !/\S/.test( node.textContent ) ) {
} else { do {
mergeContainers( nodeBeforeSplit ); parent = node.parentNode;
parent.removeChild( node );
node = parent;
} while ( parent && !parent.lastChild &&
parent.nodeName !== 'BODY' );
}
if ( !nodeAfterSplit.parentNode ) {
nodeAfterSplit = prev.nextSibling;
}
if ( !endOffset ) {
endContainer = prev;
endOffset = prev.childNodes.length;
}
// Merge inserted containers with edges of split
if ( isContainer( nodeAfterSplit ) ) {
mergeContainers( nodeAfterSplit );
} }
range.setStart( startContainer, startOffset ); range.setStart( startContainer, startOffset );