mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 15:23:29 -05:00
Fix delete behaviour
1. Fixes cursor position when deleting starting with a selection at beginning of block. 2. Fixes block disappears when whole inline contents is deleted.
This commit is contained in:
parent
066bdd2cde
commit
6f83f23881
6 changed files with 62 additions and 66 deletions
|
@ -858,28 +858,24 @@ var extractContentsOfRange = function ( range, common, root ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
var deleteContentsOfRange = function ( range, root ) {
|
var deleteContentsOfRange = function ( range, root ) {
|
||||||
// Move boundaries up as much as possible to reduce need to split.
|
var startBlock = getStartBlockOfRange( range, root );
|
||||||
// But we need to check whether we've moved the boundary outside of a
|
var endBlock = getEndBlockOfRange( range, root );
|
||||||
// block. If so, the entire block will be removed, so we shouldn't merge
|
var needsMerge = ( startBlock !== endBlock );
|
||||||
// later.
|
var frag, child;
|
||||||
moveRangeBoundariesUpTree( range );
|
|
||||||
|
|
||||||
var startBlock = range.startContainer,
|
// Move boundaries up as much as possible without exiting block,
|
||||||
endBlock = range.endContainer,
|
// to reduce need to split.
|
||||||
needsMerge = ( isInline( startBlock ) || isBlock( startBlock ) ) &&
|
moveRangeBoundariesUpTree( range, startBlock, endBlock );
|
||||||
( isInline( endBlock ) || isBlock( endBlock ) );
|
|
||||||
|
|
||||||
// Remove selected range
|
// Remove selected range
|
||||||
var frag = extractContentsOfRange( range, null, root );
|
frag = extractContentsOfRange( range, null, root );
|
||||||
|
|
||||||
// Move boundaries back down tree so that they are inside the blocks.
|
// Move boundaries back down tree as far as possible.
|
||||||
// If we don't do this, the range may be collapsed to a point between
|
|
||||||
// two blocks, so get(Start|End)BlockOfRange will return null.
|
|
||||||
moveRangeBoundariesDownTree( range );
|
moveRangeBoundariesDownTree( range );
|
||||||
|
|
||||||
// If we split into two different blocks, merge the blocks.
|
// If we split into two different blocks, merge the blocks.
|
||||||
startBlock = getStartBlockOfRange( range, root );
|
|
||||||
if ( needsMerge ) {
|
if ( needsMerge ) {
|
||||||
|
// endBlock will have been split, so need to refetch
|
||||||
endBlock = getEndBlockOfRange( range, root );
|
endBlock = getEndBlockOfRange( range, root );
|
||||||
if ( startBlock && endBlock && startBlock !== endBlock ) {
|
if ( startBlock && endBlock && startBlock !== endBlock ) {
|
||||||
mergeWithBlock( startBlock, endBlock, range );
|
mergeWithBlock( startBlock, endBlock, range );
|
||||||
|
@ -892,12 +888,12 @@ var deleteContentsOfRange = function ( range, root ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure root has a block-level element in it.
|
// Ensure root has a block-level element in it.
|
||||||
var child = root.firstChild;
|
child = root.firstChild;
|
||||||
if ( !child || child.nodeName === 'BR' ) {
|
if ( !child || child.nodeName === 'BR' ) {
|
||||||
fixCursor( root, root );
|
fixCursor( root, root );
|
||||||
range.selectNodeContents( root.firstChild );
|
range.selectNodeContents( root.firstChild );
|
||||||
} else {
|
} else {
|
||||||
range.collapse( range.endContainer === root ? true : false );
|
range.collapse( true );
|
||||||
}
|
}
|
||||||
return frag;
|
return frag;
|
||||||
};
|
};
|
||||||
|
@ -1113,19 +1109,22 @@ var moveRangeBoundariesDownTree = function ( range ) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var moveRangeBoundariesUpTree = function ( range, common ) {
|
var moveRangeBoundariesUpTree = function ( range, startMax, endMax ) {
|
||||||
var startContainer = range.startContainer,
|
var startContainer = range.startContainer;
|
||||||
startOffset = range.startOffset,
|
var startOffset = range.startOffset;
|
||||||
endContainer = range.endContainer,
|
var endContainer = range.endContainer;
|
||||||
endOffset = range.endOffset,
|
var endOffset = range.endOffset;
|
||||||
maySkipBR = true,
|
var maySkipBR = true;
|
||||||
parent;
|
var parent;
|
||||||
|
|
||||||
if ( !common ) {
|
if ( !startMax ) {
|
||||||
common = range.commonAncestorContainer;
|
startMax = range.commonAncestorContainer;
|
||||||
|
}
|
||||||
|
if ( !endMax ) {
|
||||||
|
endMax = startMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( startContainer !== common && !startOffset ) {
|
while ( startContainer !== startMax && !startOffset ) {
|
||||||
parent = startContainer.parentNode;
|
parent = startContainer.parentNode;
|
||||||
startOffset = indexOf.call( parent.childNodes, startContainer );
|
startOffset = indexOf.call( parent.childNodes, startContainer );
|
||||||
startContainer = parent;
|
startContainer = parent;
|
||||||
|
@ -1139,7 +1138,7 @@ var moveRangeBoundariesUpTree = function ( range, common ) {
|
||||||
endOffset += 1;
|
endOffset += 1;
|
||||||
maySkipBR = false;
|
maySkipBR = false;
|
||||||
}
|
}
|
||||||
if ( endContainer === common ||
|
if ( endContainer === endMax ||
|
||||||
endOffset !== getLength( endContainer ) ) {
|
endOffset !== getLength( endContainer ) ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1638,7 +1637,7 @@ var keyHandlers = {
|
||||||
// delete it ourselves, because the browser won't if it is not
|
// delete it ourselves, because the browser won't if it is not
|
||||||
// inline.
|
// inline.
|
||||||
originalRange = range.cloneRange();
|
originalRange = range.cloneRange();
|
||||||
moveRangeBoundariesUpTree( range, self._root );
|
moveRangeBoundariesUpTree( range, root, root );
|
||||||
cursorContainer = range.endContainer;
|
cursorContainer = range.endContainer;
|
||||||
cursorOffset = range.endOffset;
|
cursorOffset = range.endOffset;
|
||||||
if ( cursorContainer.nodeType === ELEMENT_NODE ) {
|
if ( cursorContainer.nodeType === ELEMENT_NODE ) {
|
||||||
|
@ -2178,7 +2177,6 @@ var onCut = function ( event ) {
|
||||||
// Mobile Safari flat out doesn't work:
|
// Mobile Safari flat out doesn't work:
|
||||||
// https://bugs.webkit.org/show_bug.cgi?id=143776
|
// https://bugs.webkit.org/show_bug.cgi?id=143776
|
||||||
if ( !isEdge && !isIOS && clipboardData ) {
|
if ( !isEdge && !isIOS && clipboardData ) {
|
||||||
moveRangeBoundariesUpTree( range, root );
|
|
||||||
node.appendChild( deleteContentsOfRange( range, root ) );
|
node.appendChild( deleteContentsOfRange( range, root ) );
|
||||||
setClipboardData( clipboardData, node, root );
|
setClipboardData( clipboardData, node, root );
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -2212,7 +2210,7 @@ var onCopy = function ( event ) {
|
||||||
endBlock = getEndBlockOfRange( range, root );
|
endBlock = getEndBlockOfRange( range, root );
|
||||||
copyRoot = ( ( startBlock === endBlock ) && startBlock ) || root;
|
copyRoot = ( ( startBlock === endBlock ) && startBlock ) || root;
|
||||||
moveRangeBoundariesDownTree( range );
|
moveRangeBoundariesDownTree( range );
|
||||||
moveRangeBoundariesUpTree( range, copyRoot );
|
moveRangeBoundariesUpTree( range, copyRoot, copyRoot );
|
||||||
contents = range.cloneContents();
|
contents = range.cloneContents();
|
||||||
parent = range.commonAncestorContainer;
|
parent = range.commonAncestorContainer;
|
||||||
if ( parent.nodeType === TEXT_NODE ) {
|
if ( parent.nodeType === TEXT_NODE ) {
|
||||||
|
@ -3720,7 +3718,7 @@ proto.modifyBlocks = function ( modify, range ) {
|
||||||
expandRangeToBlockBoundaries( range, root );
|
expandRangeToBlockBoundaries( range, root );
|
||||||
|
|
||||||
// 3. Remove range.
|
// 3. Remove range.
|
||||||
moveRangeBoundariesUpTree( range, root );
|
moveRangeBoundariesUpTree( range, root, root );
|
||||||
frag = extractContentsOfRange( range, root, root );
|
frag = extractContentsOfRange( range, root, root );
|
||||||
|
|
||||||
// 4. Modify tree of fragment and reinsert.
|
// 4. Modify tree of fragment and reinsert.
|
||||||
|
@ -4454,7 +4452,7 @@ proto.removeAllFormatting = function ( range ) {
|
||||||
this.saveUndoState( range );
|
this.saveUndoState( range );
|
||||||
|
|
||||||
// Avoid splitting where we're already at edges.
|
// Avoid splitting where we're already at edges.
|
||||||
moveRangeBoundariesUpTree( range, stopNode );
|
moveRangeBoundariesUpTree( range, stopNode, stopNode );
|
||||||
|
|
||||||
// Split the selection up to the block, or if whole selection in same
|
// Split the selection up to the block, or if whole selection in same
|
||||||
// block, expand range boundaries to ends of block and split up to root.
|
// block, expand range boundaries to ends of block and split up to root.
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -51,7 +51,6 @@ var onCut = function ( event ) {
|
||||||
// Mobile Safari flat out doesn't work:
|
// Mobile Safari flat out doesn't work:
|
||||||
// https://bugs.webkit.org/show_bug.cgi?id=143776
|
// https://bugs.webkit.org/show_bug.cgi?id=143776
|
||||||
if ( !isEdge && !isIOS && clipboardData ) {
|
if ( !isEdge && !isIOS && clipboardData ) {
|
||||||
moveRangeBoundariesUpTree( range, root );
|
|
||||||
node.appendChild( deleteContentsOfRange( range, root ) );
|
node.appendChild( deleteContentsOfRange( range, root ) );
|
||||||
setClipboardData( clipboardData, node, root );
|
setClipboardData( clipboardData, node, root );
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -85,7 +84,7 @@ var onCopy = function ( event ) {
|
||||||
endBlock = getEndBlockOfRange( range, root );
|
endBlock = getEndBlockOfRange( range, root );
|
||||||
copyRoot = ( ( startBlock === endBlock ) && startBlock ) || root;
|
copyRoot = ( ( startBlock === endBlock ) && startBlock ) || root;
|
||||||
moveRangeBoundariesDownTree( range );
|
moveRangeBoundariesDownTree( range );
|
||||||
moveRangeBoundariesUpTree( range, copyRoot );
|
moveRangeBoundariesUpTree( range, copyRoot, copyRoot );
|
||||||
contents = range.cloneContents();
|
contents = range.cloneContents();
|
||||||
parent = range.commonAncestorContainer;
|
parent = range.commonAncestorContainer;
|
||||||
if ( parent.nodeType === TEXT_NODE ) {
|
if ( parent.nodeType === TEXT_NODE ) {
|
||||||
|
|
|
@ -1301,7 +1301,7 @@ proto.modifyBlocks = function ( modify, range ) {
|
||||||
expandRangeToBlockBoundaries( range, root );
|
expandRangeToBlockBoundaries( range, root );
|
||||||
|
|
||||||
// 3. Remove range.
|
// 3. Remove range.
|
||||||
moveRangeBoundariesUpTree( range, root );
|
moveRangeBoundariesUpTree( range, root, root );
|
||||||
frag = extractContentsOfRange( range, root, root );
|
frag = extractContentsOfRange( range, root, root );
|
||||||
|
|
||||||
// 4. Modify tree of fragment and reinsert.
|
// 4. Modify tree of fragment and reinsert.
|
||||||
|
@ -2035,7 +2035,7 @@ proto.removeAllFormatting = function ( range ) {
|
||||||
this.saveUndoState( range );
|
this.saveUndoState( range );
|
||||||
|
|
||||||
// Avoid splitting where we're already at edges.
|
// Avoid splitting where we're already at edges.
|
||||||
moveRangeBoundariesUpTree( range, stopNode );
|
moveRangeBoundariesUpTree( range, stopNode, stopNode );
|
||||||
|
|
||||||
// Split the selection up to the block, or if whole selection in same
|
// Split the selection up to the block, or if whole selection in same
|
||||||
// block, expand range boundaries to ends of block and split up to root.
|
// block, expand range boundaries to ends of block and split up to root.
|
||||||
|
|
|
@ -362,7 +362,7 @@ var keyHandlers = {
|
||||||
// delete it ourselves, because the browser won't if it is not
|
// delete it ourselves, because the browser won't if it is not
|
||||||
// inline.
|
// inline.
|
||||||
originalRange = range.cloneRange();
|
originalRange = range.cloneRange();
|
||||||
moveRangeBoundariesUpTree( range, self._root );
|
moveRangeBoundariesUpTree( range, root, root );
|
||||||
cursorContainer = range.endContainer;
|
cursorContainer = range.endContainer;
|
||||||
cursorOffset = range.endOffset;
|
cursorOffset = range.endOffset;
|
||||||
if ( cursorContainer.nodeType === ELEMENT_NODE ) {
|
if ( cursorContainer.nodeType === ELEMENT_NODE ) {
|
||||||
|
|
|
@ -133,28 +133,24 @@ var extractContentsOfRange = function ( range, common, root ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
var deleteContentsOfRange = function ( range, root ) {
|
var deleteContentsOfRange = function ( range, root ) {
|
||||||
// Move boundaries up as much as possible to reduce need to split.
|
var startBlock = getStartBlockOfRange( range, root );
|
||||||
// But we need to check whether we've moved the boundary outside of a
|
var endBlock = getEndBlockOfRange( range, root );
|
||||||
// block. If so, the entire block will be removed, so we shouldn't merge
|
var needsMerge = ( startBlock !== endBlock );
|
||||||
// later.
|
var frag, child;
|
||||||
moveRangeBoundariesUpTree( range );
|
|
||||||
|
|
||||||
var startBlock = range.startContainer,
|
// Move boundaries up as much as possible without exiting block,
|
||||||
endBlock = range.endContainer,
|
// to reduce need to split.
|
||||||
needsMerge = ( isInline( startBlock ) || isBlock( startBlock ) ) &&
|
moveRangeBoundariesUpTree( range, startBlock, endBlock );
|
||||||
( isInline( endBlock ) || isBlock( endBlock ) );
|
|
||||||
|
|
||||||
// Remove selected range
|
// Remove selected range
|
||||||
var frag = extractContentsOfRange( range, null, root );
|
frag = extractContentsOfRange( range, null, root );
|
||||||
|
|
||||||
// Move boundaries back down tree so that they are inside the blocks.
|
// Move boundaries back down tree as far as possible.
|
||||||
// If we don't do this, the range may be collapsed to a point between
|
|
||||||
// two blocks, so get(Start|End)BlockOfRange will return null.
|
|
||||||
moveRangeBoundariesDownTree( range );
|
moveRangeBoundariesDownTree( range );
|
||||||
|
|
||||||
// If we split into two different blocks, merge the blocks.
|
// If we split into two different blocks, merge the blocks.
|
||||||
startBlock = getStartBlockOfRange( range, root );
|
|
||||||
if ( needsMerge ) {
|
if ( needsMerge ) {
|
||||||
|
// endBlock will have been split, so need to refetch
|
||||||
endBlock = getEndBlockOfRange( range, root );
|
endBlock = getEndBlockOfRange( range, root );
|
||||||
if ( startBlock && endBlock && startBlock !== endBlock ) {
|
if ( startBlock && endBlock && startBlock !== endBlock ) {
|
||||||
mergeWithBlock( startBlock, endBlock, range );
|
mergeWithBlock( startBlock, endBlock, range );
|
||||||
|
@ -167,12 +163,12 @@ var deleteContentsOfRange = function ( range, root ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure root has a block-level element in it.
|
// Ensure root has a block-level element in it.
|
||||||
var child = root.firstChild;
|
child = root.firstChild;
|
||||||
if ( !child || child.nodeName === 'BR' ) {
|
if ( !child || child.nodeName === 'BR' ) {
|
||||||
fixCursor( root, root );
|
fixCursor( root, root );
|
||||||
range.selectNodeContents( root.firstChild );
|
range.selectNodeContents( root.firstChild );
|
||||||
} else {
|
} else {
|
||||||
range.collapse( range.endContainer === root ? true : false );
|
range.collapse( true );
|
||||||
}
|
}
|
||||||
return frag;
|
return frag;
|
||||||
};
|
};
|
||||||
|
@ -388,19 +384,22 @@ var moveRangeBoundariesDownTree = function ( range ) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var moveRangeBoundariesUpTree = function ( range, common ) {
|
var moveRangeBoundariesUpTree = function ( range, startMax, endMax ) {
|
||||||
var startContainer = range.startContainer,
|
var startContainer = range.startContainer;
|
||||||
startOffset = range.startOffset,
|
var startOffset = range.startOffset;
|
||||||
endContainer = range.endContainer,
|
var endContainer = range.endContainer;
|
||||||
endOffset = range.endOffset,
|
var endOffset = range.endOffset;
|
||||||
maySkipBR = true,
|
var maySkipBR = true;
|
||||||
parent;
|
var parent;
|
||||||
|
|
||||||
if ( !common ) {
|
if ( !startMax ) {
|
||||||
common = range.commonAncestorContainer;
|
startMax = range.commonAncestorContainer;
|
||||||
|
}
|
||||||
|
if ( !endMax ) {
|
||||||
|
endMax = startMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( startContainer !== common && !startOffset ) {
|
while ( startContainer !== startMax && !startOffset ) {
|
||||||
parent = startContainer.parentNode;
|
parent = startContainer.parentNode;
|
||||||
startOffset = indexOf.call( parent.childNodes, startContainer );
|
startOffset = indexOf.call( parent.childNodes, startContainer );
|
||||||
startContainer = parent;
|
startContainer = parent;
|
||||||
|
@ -414,7 +413,7 @@ var moveRangeBoundariesUpTree = function ( range, common ) {
|
||||||
endOffset += 1;
|
endOffset += 1;
|
||||||
maySkipBR = false;
|
maySkipBR = false;
|
||||||
}
|
}
|
||||||
if ( endContainer === common ||
|
if ( endContainer === endMax ||
|
||||||
endOffset !== getLength( endContainer ) ) {
|
endOffset !== getLength( endContainer ) ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue