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

Improve detection of range at begin/end of block.

This commit is contained in:
Neil Jenkins 2014-09-03 10:27:38 +07:00
parent 4a8152d280
commit a280cb4946
3 changed files with 72 additions and 58 deletions

View file

@ -615,6 +615,7 @@ function createElement ( doc, tag, props, children ) {
START_TO_END, START_TO_END,
END_TO_END, END_TO_END,
END_TO_START, END_TO_START,
notWS,
indexOf, indexOf,
TreeWalker, TreeWalker,
@ -1059,50 +1060,56 @@ var getEndBlockOfRange = function ( range ) {
return block && isNodeContainedInRange( range, block, true ) ? block : null; return block && isNodeContainedInRange( range, block, true ) ? block : null;
}; };
var contentWalker = new TreeWalker( null,
SHOW_TEXT|SHOW_ELEMENT,
function ( node ) {
return node.nodeType === TEXT_NODE ?
notWS.test( node.data ) :
node.nodeName === 'IMG';
}
);
var rangeDoesStartAtBlockBoundary = function ( range ) { var rangeDoesStartAtBlockBoundary = function ( range ) {
var startContainer = range.startContainer, var startContainer = range.startContainer,
startOffset = range.startOffset, startOffset = range.startOffset;
parent, child;
while ( isInline( startContainer ) ) { // If in the middle or end of a text node, we're not at the boundary.
if ( startContainer.nodeType === TEXT_NODE ) {
if ( startOffset ) { if ( startOffset ) {
return false; return false;
} }
parent = startContainer.parentNode; contentWalker.currentNode = startContainer;
startOffset = indexOf.call( parent.childNodes, startContainer ); } else {
startContainer = parent; contentWalker.currentNode = getNodeAfter( startContainer, startOffset );
} }
// Skip empty text nodes and <br>s.
while ( startOffset && // Otherwise, look for any previous content in the same block.
( child = startContainer.childNodes[ startOffset - 1 ] ) && contentWalker.root = getStartBlockOfRange( range );
( child.data === '' || child.nodeName === 'BR' ) ) {
startOffset -= 1; return !contentWalker.previousNode();
}
return !startOffset;
}; };
var rangeDoesEndAtBlockBoundary = function ( range ) { var rangeDoesEndAtBlockBoundary = function ( range ) {
var endContainer = range.endContainer, var endContainer = range.endContainer,
endOffset = range.endOffset, endOffset = range.endOffset,
length = getLength( endContainer ), length;
parent, child;
while ( isInline( endContainer ) ) { // If in a text node with content, and not at the end, we're not
if ( endOffset !== length ) { // at the boundary
if ( endContainer.nodeType === TEXT_NODE ) {
length = endContainer.data.length;
if ( length && endOffset < length ) {
return false; return false;
} }
parent = endContainer.parentNode; contentWalker.currentNode = endContainer;
endOffset = indexOf.call( parent.childNodes, endContainer ) + 1; } else {
endContainer = parent; contentWalker.currentNode = getNodeBefore( endContainer, endOffset );
length = endContainer.childNodes.length;
} }
// Skip empty text nodes and <br>s.
while ( endOffset < length && // Otherwise, look for any further content in the same block.
( child = endContainer.childNodes[ endOffset ] ) && contentWalker.root = getEndBlockOfRange( range );
( child.data === '' || child.nodeName === 'BR' ) ) {
endOffset += 1; return !contentWalker.nextNode();
}
return endOffset === length;
}; };
var expandRangeToBlockBoundaries = function ( range ) { var expandRangeToBlockBoundaries = function ( range ) {

File diff suppressed because one or more lines are too long

View file

@ -7,6 +7,7 @@
START_TO_END, START_TO_END,
END_TO_END, END_TO_END,
END_TO_START, END_TO_START,
notWS,
indexOf, indexOf,
TreeWalker, TreeWalker,
@ -451,50 +452,56 @@ var getEndBlockOfRange = function ( range ) {
return block && isNodeContainedInRange( range, block, true ) ? block : null; return block && isNodeContainedInRange( range, block, true ) ? block : null;
}; };
var contentWalker = new TreeWalker( null,
SHOW_TEXT|SHOW_ELEMENT,
function ( node ) {
return node.nodeType === TEXT_NODE ?
notWS.test( node.data ) :
node.nodeName === 'IMG';
}
);
var rangeDoesStartAtBlockBoundary = function ( range ) { var rangeDoesStartAtBlockBoundary = function ( range ) {
var startContainer = range.startContainer, var startContainer = range.startContainer,
startOffset = range.startOffset, startOffset = range.startOffset;
parent, child;
while ( isInline( startContainer ) ) { // If in the middle or end of a text node, we're not at the boundary.
if ( startContainer.nodeType === TEXT_NODE ) {
if ( startOffset ) { if ( startOffset ) {
return false; return false;
} }
parent = startContainer.parentNode; contentWalker.currentNode = startContainer;
startOffset = indexOf.call( parent.childNodes, startContainer ); } else {
startContainer = parent; contentWalker.currentNode = getNodeAfter( startContainer, startOffset );
} }
// Skip empty text nodes and <br>s.
while ( startOffset && // Otherwise, look for any previous content in the same block.
( child = startContainer.childNodes[ startOffset - 1 ] ) && contentWalker.root = getStartBlockOfRange( range );
( child.data === '' || child.nodeName === 'BR' ) ) {
startOffset -= 1; return !contentWalker.previousNode();
}
return !startOffset;
}; };
var rangeDoesEndAtBlockBoundary = function ( range ) { var rangeDoesEndAtBlockBoundary = function ( range ) {
var endContainer = range.endContainer, var endContainer = range.endContainer,
endOffset = range.endOffset, endOffset = range.endOffset,
length = getLength( endContainer ), length;
parent, child;
while ( isInline( endContainer ) ) { // If in a text node with content, and not at the end, we're not
if ( endOffset !== length ) { // at the boundary
if ( endContainer.nodeType === TEXT_NODE ) {
length = endContainer.data.length;
if ( length && endOffset < length ) {
return false; return false;
} }
parent = endContainer.parentNode; contentWalker.currentNode = endContainer;
endOffset = indexOf.call( parent.childNodes, endContainer ) + 1; } else {
endContainer = parent; contentWalker.currentNode = getNodeBefore( endContainer, endOffset );
length = endContainer.childNodes.length;
} }
// Skip empty text nodes and <br>s.
while ( endOffset < length && // Otherwise, look for any further content in the same block.
( child = endContainer.childNodes[ endOffset ] ) && contentWalker.root = getEndBlockOfRange( range );
( child.data === '' || child.nodeName === 'BR' ) ) {
endOffset += 1; return !contentWalker.nextNode();
}
return endOffset === length;
}; };
var expandRangeToBlockBoundaries = function ( range ) { var expandRangeToBlockBoundaries = function ( range ) {