mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 07:13:08 -05:00
Fix Range#get(Start|End)Block.
Was still returning the wrong result in certain situations (for example when the start boundary was just before the end of a block).
This commit is contained in:
parent
1792b66ac3
commit
0f750d2a0e
2 changed files with 59 additions and 44 deletions
File diff suppressed because one or more lines are too long
101
source/Range.js
101
source/Range.js
|
@ -23,6 +23,31 @@ var ELEMENT_NODE = 1, // Node.ELEMENT_NODE
|
||||||
END_TO_END = 2, // Range.END_TO_END
|
END_TO_END = 2, // Range.END_TO_END
|
||||||
END_TO_START = 3; // Range.END_TO_START
|
END_TO_START = 3; // Range.END_TO_START
|
||||||
|
|
||||||
|
var getNodeBefore = function ( node, offset ) {
|
||||||
|
var children = node.childNodes;
|
||||||
|
while ( offset && node.nodeType === ELEMENT_NODE ) {
|
||||||
|
node = children[ offset - 1 ];
|
||||||
|
children = node.childNodes;
|
||||||
|
offset = children.length;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getNodeAfter = function ( node, offset ) {
|
||||||
|
if ( node.nodeType === ELEMENT_NODE ) {
|
||||||
|
var children = node.childNodes;
|
||||||
|
if ( offset < children.length ) {
|
||||||
|
node = children[ offset ];
|
||||||
|
} else {
|
||||||
|
while ( node && !node.nextSibling ) {
|
||||||
|
node = node.parentNode;
|
||||||
|
}
|
||||||
|
if ( node ) { node = node.nextSibling; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
implement( Range, {
|
implement( Range, {
|
||||||
_insertNode: function ( node ) {
|
_insertNode: function ( node ) {
|
||||||
// Insert at start.
|
// Insert at start.
|
||||||
|
@ -331,60 +356,50 @@ implement( Range, {
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
getFirstNodeAfterStart: function () {
|
|
||||||
var node = this.startContainer;
|
|
||||||
if ( node.nodeType === ELEMENT_NODE ) {
|
|
||||||
var offset = this.startOffset,
|
|
||||||
children = node.childNodes;
|
|
||||||
if ( offset < children.length ) {
|
|
||||||
node = children[ offset ];
|
|
||||||
} else {
|
|
||||||
while ( node && !node.nextSibling ) {
|
|
||||||
node = node.parentNode;
|
|
||||||
}
|
|
||||||
if ( node ) { node = node.nextSibling; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
getLastNodeBeforeEnd: function () {
|
|
||||||
var node = this.endContainer,
|
|
||||||
offset = this.startOffset,
|
|
||||||
children = node.childNodes;
|
|
||||||
while ( offset && node.nodeType === ELEMENT_NODE ) {
|
|
||||||
node = children[ offset - 1 ];
|
|
||||||
children = node.childNodes;
|
|
||||||
offset = children.length;
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns the first block at least partially contained by the range,
|
// Returns the first block at least partially contained by the range,
|
||||||
// or null if no block is contained by the range.
|
// or null if no block is contained by the range.
|
||||||
getStartBlock: function () {
|
getStartBlock: function () {
|
||||||
// 1. Find first node after range start.
|
var container = this.startContainer,
|
||||||
var node = this.getFirstNodeAfterStart();
|
block;
|
||||||
// 2. If not a block, get previous block.
|
|
||||||
if ( node && !node.isBlock() ) {
|
// If inline, get the containing block.
|
||||||
node = node.getPreviousBlock();
|
if ( container.isInline() ) {
|
||||||
|
block = container.getPreviousBlock();
|
||||||
|
} else if ( container.isBlock() ) {
|
||||||
|
block = container;
|
||||||
|
} else {
|
||||||
|
block = getNodeBefore( container, this.startOffset );
|
||||||
|
block = block.getNextBlock();
|
||||||
}
|
}
|
||||||
// 3. Check the block does not end before range begins.
|
// Check the block actually intersects the range
|
||||||
return node && this.containsNode( node, true ) ? node : null;
|
return block && this.containsNode( block, true ) ? block : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns the last block at least partially contained by the range,
|
// Returns the last block at least partially contained by the range,
|
||||||
// or null if no block is contained by the range.
|
// or null if no block is contained by the range.
|
||||||
getEndBlock: function () {
|
getEndBlock: function () {
|
||||||
// 1. Find first node before range end.
|
var container = this.endContainer,
|
||||||
var node = this.getLastNodeBeforeEnd();
|
block, child;
|
||||||
// 2. If not a block, get previous block.
|
|
||||||
if ( node && !node.isBlock() ) {
|
// If inline, get the containing block.
|
||||||
node = node.getPreviousBlock();
|
if ( container.isInline() ) {
|
||||||
|
block = container.getPreviousBlock();
|
||||||
|
} else if ( container.isBlock() ) {
|
||||||
|
block = container;
|
||||||
|
} else {
|
||||||
|
block = getNodeAfter( container, this.endOffset );
|
||||||
|
if ( !block ) {
|
||||||
|
block = container.ownerDocument.body;
|
||||||
|
while ( child = block.lastChild ) {
|
||||||
|
block = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block = block.getPreviousBlock();
|
||||||
|
|
||||||
}
|
}
|
||||||
// 3. Check the block does not end before range ends.
|
// Check the block actually intersects the range
|
||||||
return node && this.containsNode( node, true ) ? node : null;
|
return block && this.containsNode( block, true ) ? block : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
startsAtBlockBoundary: function () {
|
startsAtBlockBoundary: function () {
|
||||||
|
|
Loading…
Reference in a new issue