mirror of
https://github.com/fastmail/Squire.git
synced 2025-01-03 05:00:13 -05:00
Turn Range prototype extensions into functions.
A step towards being able to share code between multiple concurrent instances of the editor. Also reduces minified size slightly.
This commit is contained in:
parent
dbda1fa4ed
commit
7812b8db23
4 changed files with 263 additions and 259 deletions
|
@ -580,9 +580,7 @@ if ( function () {
|
||||||
fixCursor,
|
fixCursor,
|
||||||
split,
|
split,
|
||||||
mergeWithBlock,
|
mergeWithBlock,
|
||||||
mergeContainers,
|
mergeContainers
|
||||||
|
|
||||||
Range
|
|
||||||
*/
|
*/
|
||||||
/*jshint strict:false */
|
/*jshint strict:false */
|
||||||
|
|
||||||
|
@ -611,11 +609,11 @@ var getNodeAfter = function ( node, offset ) {
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
var RangePrototype = Range.prototype;
|
// ---
|
||||||
|
|
||||||
RangePrototype.forEachTextNode = function ( fn ) {
|
var forEachTextNodeInRange = function ( range, fn ) {
|
||||||
var range = this.cloneRange();
|
range = range.cloneRange();
|
||||||
range.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
|
|
||||||
var startContainer = range.startContainer,
|
var startContainer = range.startContainer,
|
||||||
endContainer = range.endContainer,
|
endContainer = range.endContainer,
|
||||||
|
@ -631,9 +629,9 @@ RangePrototype.forEachTextNode = function ( fn ) {
|
||||||
( textnode = walker.nextNode() ) ) {}
|
( textnode = walker.nextNode() ) ) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.getTextContent = function () {
|
var getTextContentInRange = function ( range ) {
|
||||||
var textContent = '';
|
var textContent = '';
|
||||||
this.forEachTextNode( function ( textnode, range ) {
|
forEachTextNodeInRange( range, function ( textnode, range ) {
|
||||||
var value = textnode.data;
|
var value = textnode.data;
|
||||||
if ( value && ( /\S/.test( value ) ) ) {
|
if ( value && ( /\S/.test( value ) ) ) {
|
||||||
if ( textnode === range.endContainer ) {
|
if ( textnode === range.endContainer ) {
|
||||||
|
@ -650,12 +648,12 @@ RangePrototype.getTextContent = function () {
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
RangePrototype._insertNode = function ( node ) {
|
var insertNodeInRange = function ( range, node ) {
|
||||||
// Insert at start.
|
// Insert at start.
|
||||||
var startContainer = this.startContainer,
|
var startContainer = range.startContainer,
|
||||||
startOffset = this.startOffset,
|
startOffset = range.startOffset,
|
||||||
endContainer = this.endContainer,
|
endContainer = range.endContainer,
|
||||||
endOffset = this.endOffset,
|
endOffset = range.endOffset,
|
||||||
parent, children, childCount, afterSplit;
|
parent, children, childCount, afterSplit;
|
||||||
|
|
||||||
// If part way through a text node, split it.
|
// If part way through a text node, split it.
|
||||||
|
@ -664,7 +662,7 @@ RangePrototype._insertNode = function ( node ) {
|
||||||
children = parent.childNodes;
|
children = parent.childNodes;
|
||||||
if ( startOffset === startContainer.length ) {
|
if ( startOffset === startContainer.length ) {
|
||||||
startOffset = indexOf.call( children, startContainer ) + 1;
|
startOffset = indexOf.call( children, startContainer ) + 1;
|
||||||
if ( this.collapsed ) {
|
if ( range.collapsed ) {
|
||||||
endContainer = parent;
|
endContainer = parent;
|
||||||
endOffset = startOffset;
|
endOffset = startOffset;
|
||||||
}
|
}
|
||||||
|
@ -698,20 +696,18 @@ RangePrototype._insertNode = function ( node ) {
|
||||||
endOffset += children.length - childCount;
|
endOffset += children.length - childCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setStart( startContainer, startOffset );
|
range.setStart( startContainer, startOffset );
|
||||||
this.setEnd( endContainer, endOffset );
|
range.setEnd( endContainer, endOffset );
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype._extractContents = function ( common ) {
|
var extractContentsOfRange = function ( range, common ) {
|
||||||
var startContainer = this.startContainer,
|
var startContainer = range.startContainer,
|
||||||
startOffset = this.startOffset,
|
startOffset = range.startOffset,
|
||||||
endContainer = this.endContainer,
|
endContainer = range.endContainer,
|
||||||
endOffset = this.endOffset;
|
endOffset = range.endOffset;
|
||||||
|
|
||||||
if ( !common ) {
|
if ( !common ) {
|
||||||
common = this.commonAncestorContainer;
|
common = range.commonAncestorContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( common.nodeType === TEXT_NODE ) {
|
if ( common.nodeType === TEXT_NODE ) {
|
||||||
|
@ -730,28 +726,28 @@ RangePrototype._extractContents = function ( common ) {
|
||||||
startNode = next;
|
startNode = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setStart( common, endNode ?
|
range.setStart( common, endNode ?
|
||||||
indexOf.call( common.childNodes, endNode ) :
|
indexOf.call( common.childNodes, endNode ) :
|
||||||
common.childNodes.length );
|
common.childNodes.length );
|
||||||
this.collapse( true );
|
range.collapse( true );
|
||||||
|
|
||||||
fixCursor( common );
|
fixCursor( common );
|
||||||
|
|
||||||
return frag;
|
return frag;
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype._deleteContents = function () {
|
var deleteContentsOfRange = function ( range ) {
|
||||||
// Move boundaries up as much as possible to reduce need to split.
|
// Move boundaries up as much as possible to reduce need to split.
|
||||||
this.moveBoundariesUpTree();
|
moveRangeBoundariesUpTree( range );
|
||||||
|
|
||||||
// Remove selected range
|
// Remove selected range
|
||||||
this._extractContents();
|
extractContentsOfRange( range );
|
||||||
|
|
||||||
// If we split into two different blocks, merge the blocks.
|
// If we split into two different blocks, merge the blocks.
|
||||||
var startBlock = this.getStartBlock(),
|
var startBlock = getStartBlockOfRange( range ),
|
||||||
endBlock = this.getEndBlock();
|
endBlock = getEndBlockOfRange( range );
|
||||||
if ( startBlock && endBlock && startBlock !== endBlock ) {
|
if ( startBlock && endBlock && startBlock !== endBlock ) {
|
||||||
mergeWithBlock( startBlock, endBlock, this );
|
mergeWithBlock( startBlock, endBlock, range );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure block has necessary children
|
// Ensure block has necessary children
|
||||||
|
@ -760,27 +756,25 @@ RangePrototype._deleteContents = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure body has a block-level element in it.
|
// Ensure body has a block-level element in it.
|
||||||
var body = this.endContainer.ownerDocument.body,
|
var body = range.endContainer.ownerDocument.body,
|
||||||
child = body.firstChild;
|
child = body.firstChild;
|
||||||
if ( !child || child.nodeName === 'BR' ) {
|
if ( !child || child.nodeName === 'BR' ) {
|
||||||
fixCursor( body );
|
fixCursor( body );
|
||||||
this.selectNodeContents( body.firstChild );
|
range.selectNodeContents( body.firstChild );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure valid range (must have only block or inline containers)
|
// Ensure valid range (must have only block or inline containers)
|
||||||
var isCollapsed = this.collapsed;
|
var isCollapsed = range.collapsed;
|
||||||
this.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
if ( isCollapsed ) {
|
if ( isCollapsed ) {
|
||||||
// Collapse
|
// Collapse
|
||||||
this.collapse( true );
|
range.collapse( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
RangePrototype.insertTreeFragment = function ( frag ) {
|
var insertTreeFragmentIntoRange = function ( range, frag ) {
|
||||||
// Check if it's all inline content
|
// Check if it's all inline content
|
||||||
var allInline = true,
|
var allInline = true,
|
||||||
children = frag.childNodes,
|
children = frag.childNodes,
|
||||||
|
@ -793,23 +787,23 @@ RangePrototype.insertTreeFragment = function ( frag ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete any selected content
|
// Delete any selected content
|
||||||
if ( !this.collapsed ) {
|
if ( !range.collapsed ) {
|
||||||
this._deleteContents();
|
deleteContentsOfRange( range );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move range down into text ndoes
|
// Move range down into text ndoes
|
||||||
this.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
|
|
||||||
// If inline, just insert at the current position.
|
// If inline, just insert at the current position.
|
||||||
if ( allInline ) {
|
if ( allInline ) {
|
||||||
this._insertNode( frag );
|
insertNodeInRange( range, frag );
|
||||||
this.collapse( false );
|
range.collapse( false );
|
||||||
}
|
}
|
||||||
// Otherwise, split up to body, insert inline before and after split
|
// Otherwise, split up to body, insert inline before and after split
|
||||||
// and insert block in between split, then merge containers.
|
// and insert block in between split, then merge containers.
|
||||||
else {
|
else {
|
||||||
var nodeAfterSplit = split( this.startContainer, this.startOffset,
|
var nodeAfterSplit = split( range.startContainer, range.startOffset,
|
||||||
this.startContainer.ownerDocument.body ),
|
range.startContainer.ownerDocument.body ),
|
||||||
nodeBeforeSplit = nodeAfterSplit.previousSibling,
|
nodeBeforeSplit = nodeAfterSplit.previousSibling,
|
||||||
startContainer = nodeBeforeSplit,
|
startContainer = nodeBeforeSplit,
|
||||||
startOffset = startContainer.childNodes.length,
|
startOffset = startContainer.childNodes.length,
|
||||||
|
@ -865,17 +859,16 @@ RangePrototype.insertTreeFragment = function ( frag ) {
|
||||||
mergeContainers( nodeBeforeSplit );
|
mergeContainers( nodeBeforeSplit );
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setStart( startContainer, startOffset );
|
range.setStart( startContainer, startOffset );
|
||||||
this.setEnd( endContainer, endOffset );
|
range.setEnd( endContainer, endOffset );
|
||||||
this.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
RangePrototype.containsNode = function ( node, partial ) {
|
var isNodeContainedInRange = function ( range, node, partial ) {
|
||||||
var range = this,
|
var nodeRange = node.ownerDocument.createRange();
|
||||||
nodeRange = node.ownerDocument.createRange();
|
|
||||||
|
|
||||||
nodeRange.selectNode( node );
|
nodeRange.selectNode( node );
|
||||||
|
|
||||||
|
@ -899,11 +892,11 @@ RangePrototype.containsNode = function ( node, partial ) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.moveBoundariesDownTree = function () {
|
var moveRangeBoundariesDownTree = function ( range ) {
|
||||||
var startContainer = this.startContainer,
|
var startContainer = range.startContainer,
|
||||||
startOffset = this.startOffset,
|
startOffset = range.startOffset,
|
||||||
endContainer = this.endContainer,
|
endContainer = range.endContainer,
|
||||||
endOffset = this.endOffset,
|
endOffset = range.endOffset,
|
||||||
child;
|
child;
|
||||||
|
|
||||||
while ( startContainer.nodeType !== TEXT_NODE ) {
|
while ( startContainer.nodeType !== TEXT_NODE ) {
|
||||||
|
@ -936,26 +929,24 @@ RangePrototype.moveBoundariesDownTree = function () {
|
||||||
// If collapsed, this algorithm finds the nearest text node positions
|
// If collapsed, this algorithm finds the nearest text node positions
|
||||||
// *outside* the range rather than inside, but also it flips which is
|
// *outside* the range rather than inside, but also it flips which is
|
||||||
// assigned to which.
|
// assigned to which.
|
||||||
if ( this.collapsed ) {
|
if ( range.collapsed ) {
|
||||||
this.setStart( endContainer, endOffset );
|
range.setStart( endContainer, endOffset );
|
||||||
this.setEnd( startContainer, startOffset );
|
range.setEnd( startContainer, startOffset );
|
||||||
} else {
|
} else {
|
||||||
this.setStart( startContainer, startOffset );
|
range.setStart( startContainer, startOffset );
|
||||||
this.setEnd( endContainer, endOffset );
|
range.setEnd( endContainer, endOffset );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.moveBoundariesUpTree = function ( common ) {
|
var moveRangeBoundariesUpTree = function ( range, common ) {
|
||||||
var startContainer = this.startContainer,
|
var startContainer = range.startContainer,
|
||||||
startOffset = this.startOffset,
|
startOffset = range.startOffset,
|
||||||
endContainer = this.endContainer,
|
endContainer = range.endContainer,
|
||||||
endOffset = this.endOffset,
|
endOffset = range.endOffset,
|
||||||
parent;
|
parent;
|
||||||
|
|
||||||
if ( !common ) {
|
if ( !common ) {
|
||||||
common = this.commonAncestorContainer;
|
common = range.commonAncestorContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( startContainer !== common && !startOffset ) {
|
while ( startContainer !== common && !startOffset ) {
|
||||||
|
@ -971,16 +962,14 @@ RangePrototype.moveBoundariesUpTree = function ( common ) {
|
||||||
endContainer = parent;
|
endContainer = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setStart( startContainer, startOffset );
|
range.setStart( startContainer, startOffset );
|
||||||
this.setEnd( endContainer, endOffset );
|
range.setEnd( endContainer, endOffset );
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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.
|
||||||
RangePrototype.getStartBlock = function () {
|
var getStartBlockOfRange = function ( range ) {
|
||||||
var container = this.startContainer,
|
var container = range.startContainer,
|
||||||
block;
|
block;
|
||||||
|
|
||||||
// If inline, get the containing block.
|
// If inline, get the containing block.
|
||||||
|
@ -989,17 +978,17 @@ RangePrototype.getStartBlock = function () {
|
||||||
} else if ( isBlock( container ) ) {
|
} else if ( isBlock( container ) ) {
|
||||||
block = container;
|
block = container;
|
||||||
} else {
|
} else {
|
||||||
block = getNodeBefore( container, this.startOffset );
|
block = getNodeBefore( container, range.startOffset );
|
||||||
block = getNextBlock( block );
|
block = getNextBlock( block );
|
||||||
}
|
}
|
||||||
// Check the block actually intersects the range
|
// Check the block actually intersects the range
|
||||||
return block && this.containsNode( block, true ) ? block : null;
|
return block && isNodeContainedInRange( range, 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.
|
||||||
RangePrototype.getEndBlock = function () {
|
var getEndBlockOfRange = function ( range ) {
|
||||||
var container = this.endContainer,
|
var container = range.endContainer,
|
||||||
block, child;
|
block, child;
|
||||||
|
|
||||||
// If inline, get the containing block.
|
// If inline, get the containing block.
|
||||||
|
@ -1008,7 +997,7 @@ RangePrototype.getEndBlock = function () {
|
||||||
} else if ( isBlock( container ) ) {
|
} else if ( isBlock( container ) ) {
|
||||||
block = container;
|
block = container;
|
||||||
} else {
|
} else {
|
||||||
block = getNodeAfter( container, this.endOffset );
|
block = getNodeAfter( container, range.endOffset );
|
||||||
if ( !block ) {
|
if ( !block ) {
|
||||||
block = container.ownerDocument.body;
|
block = container.ownerDocument.body;
|
||||||
while ( child = block.lastChild ) {
|
while ( child = block.lastChild ) {
|
||||||
|
@ -1019,12 +1008,12 @@ RangePrototype.getEndBlock = function () {
|
||||||
|
|
||||||
}
|
}
|
||||||
// Check the block actually intersects the range
|
// Check the block actually intersects the range
|
||||||
return block && this.containsNode( block, true ) ? block : null;
|
return block && isNodeContainedInRange( range, block, true ) ? block : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.startsAtBlockBoundary = function () {
|
var rangeDoesStartAtBlockBoundary = function ( range ) {
|
||||||
var startContainer = this.startContainer,
|
var startContainer = range.startContainer,
|
||||||
startOffset = this.startOffset,
|
startOffset = range.startOffset,
|
||||||
parent, child;
|
parent, child;
|
||||||
|
|
||||||
while ( isInline( startContainer ) ) {
|
while ( isInline( startContainer ) ) {
|
||||||
|
@ -1044,9 +1033,9 @@ RangePrototype.startsAtBlockBoundary = function () {
|
||||||
return !startOffset;
|
return !startOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.endsAtBlockBoundary = function () {
|
var rangeDoesEndAtBlockBoundary = function ( range ) {
|
||||||
var endContainer = this.endContainer,
|
var endContainer = range.endContainer,
|
||||||
endOffset = this.endOffset,
|
endOffset = range.endOffset,
|
||||||
length = getLength( endContainer ),
|
length = getLength( endContainer ),
|
||||||
parent, child;
|
parent, child;
|
||||||
|
|
||||||
|
@ -1068,19 +1057,17 @@ RangePrototype.endsAtBlockBoundary = function () {
|
||||||
return endOffset === length;
|
return endOffset === length;
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.expandToBlockBoundaries = function () {
|
var expandRangeToBlockBoundaries = function ( range ) {
|
||||||
var start = this.getStartBlock(),
|
var start = getStartBlockOfRange( range ),
|
||||||
end = this.getEndBlock(),
|
end = getEndBlockOfRange( range ),
|
||||||
parent;
|
parent;
|
||||||
|
|
||||||
if ( start && end ) {
|
if ( start && end ) {
|
||||||
parent = start.parentNode;
|
parent = start.parentNode;
|
||||||
this.setStart( parent, indexOf.call( parent.childNodes, start ) );
|
range.setStart( parent, indexOf.call( parent.childNodes, start ) );
|
||||||
parent = end.parentNode;
|
parent = end.parentNode;
|
||||||
this.setEnd( parent, indexOf.call( parent.childNodes, end ) + 1 );
|
range.setEnd( parent, indexOf.call( parent.childNodes, end ) + 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
/*global
|
/*global
|
||||||
DOCUMENT_POSITION_PRECEDING,
|
DOCUMENT_POSITION_PRECEDING,
|
||||||
|
@ -1128,6 +1115,21 @@ RangePrototype.expandToBlockBoundaries = function () {
|
||||||
mergeContainers,
|
mergeContainers,
|
||||||
createElement,
|
createElement,
|
||||||
|
|
||||||
|
forEachTextNodeInRange,
|
||||||
|
getTextContentInRange,
|
||||||
|
insertNodeInRange,
|
||||||
|
extractContentsOfRange,
|
||||||
|
deleteContentsOfRange,
|
||||||
|
insertTreeFragmentIntoRange,
|
||||||
|
isNodeContainedInRange,
|
||||||
|
moveRangeBoundariesDownTree,
|
||||||
|
moveRangeBoundariesUpTree,
|
||||||
|
getStartBlockOfRange,
|
||||||
|
getEndBlockOfRange,
|
||||||
|
rangeDoesStartAtBlockBoundary,
|
||||||
|
rangeDoesEndAtBlockBoundary,
|
||||||
|
expandRangeToBlockBoundaries,
|
||||||
|
|
||||||
Range,
|
Range,
|
||||||
top,
|
top,
|
||||||
console,
|
console,
|
||||||
|
@ -1405,11 +1407,11 @@ var insertElement = function ( el, range ) {
|
||||||
if ( !range ) { range = getSelection(); }
|
if ( !range ) { range = getSelection(); }
|
||||||
range.collapse( true );
|
range.collapse( true );
|
||||||
if ( isInline( el ) ) {
|
if ( isInline( el ) ) {
|
||||||
range._insertNode( el );
|
insertNodeInRange( range, el );
|
||||||
range.setStartAfter( el );
|
range.setStartAfter( el );
|
||||||
} else {
|
} else {
|
||||||
// Get containing block node.
|
// Get containing block node.
|
||||||
var splitNode = range.getStartBlock() || body,
|
var splitNode = getStartBlockOfRange( range ) || body,
|
||||||
parent, nodeAfterSplit;
|
parent, nodeAfterSplit;
|
||||||
// While at end of container node, move up DOM tree.
|
// While at end of container node, move up DOM tree.
|
||||||
while ( splitNode !== body && !splitNode.nextSibling ) {
|
while ( splitNode !== body && !splitNode.nextSibling ) {
|
||||||
|
@ -1424,7 +1426,7 @@ var insertElement = function ( el, range ) {
|
||||||
body.insertBefore( el, nodeAfterSplit );
|
body.insertBefore( el, nodeAfterSplit );
|
||||||
range.setStart( nodeAfterSplit, 0 );
|
range.setStart( nodeAfterSplit, 0 );
|
||||||
range.setStart( nodeAfterSplit, 0 );
|
range.setStart( nodeAfterSplit, 0 );
|
||||||
range.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
} else {
|
} else {
|
||||||
body.appendChild( el );
|
body.appendChild( el );
|
||||||
// Insert blank line below block.
|
// Insert blank line below block.
|
||||||
|
@ -1454,9 +1456,9 @@ var saveRangeToBookmark = function ( range ) {
|
||||||
}),
|
}),
|
||||||
temp;
|
temp;
|
||||||
|
|
||||||
range._insertNode( startNode );
|
insertNodeInRange( range, startNode );
|
||||||
range.collapse( false );
|
range.collapse( false );
|
||||||
range._insertNode( endNode );
|
insertNodeInRange( range, endNode );
|
||||||
|
|
||||||
// In a collapsed range, the start is sometimes inserted after the end!
|
// In a collapsed range, the start is sometimes inserted after the end!
|
||||||
if ( startNode.compareDocumentPosition( endNode ) &
|
if ( startNode.compareDocumentPosition( endNode ) &
|
||||||
|
@ -1508,7 +1510,7 @@ var getRangeAndRemoveBookmark = function ( range ) {
|
||||||
range.setEnd( _range.endContainer, _range.endOffset );
|
range.setEnd( _range.endContainer, _range.endOffset );
|
||||||
collapsed = range.collapsed;
|
collapsed = range.collapsed;
|
||||||
|
|
||||||
range.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
if ( collapsed ) {
|
if ( collapsed ) {
|
||||||
range.collapse( true );
|
range.collapse( true );
|
||||||
}
|
}
|
||||||
|
@ -1638,7 +1640,7 @@ var hasFormat = function ( tag, attributes, range ) {
|
||||||
// Otherwise, check each text node at least partially contained within
|
// Otherwise, check each text node at least partially contained within
|
||||||
// the selection and make sure all of them have the format we want.
|
// the selection and make sure all of them have the format we want.
|
||||||
walker = new TreeWalker( root, SHOW_TEXT, function ( node ) {
|
walker = new TreeWalker( root, SHOW_TEXT, function ( node ) {
|
||||||
return range.containsNode( node, true ) ?
|
return isNodeContainedInRange( range, node, true ) ?
|
||||||
FILTER_ACCEPT : FILTER_SKIP;
|
FILTER_ACCEPT : FILTER_SKIP;
|
||||||
}, false );
|
}, false );
|
||||||
|
|
||||||
|
@ -1661,7 +1663,7 @@ var addFormat = function ( tag, attributes, range ) {
|
||||||
|
|
||||||
if ( range.collapsed ) {
|
if ( range.collapsed ) {
|
||||||
el = fixCursor( createElement( tag, attributes ) );
|
el = fixCursor( createElement( tag, attributes ) );
|
||||||
range._insertNode( el );
|
insertNodeInRange( range, el );
|
||||||
range.setStart( el.firstChild, el.firstChild.length );
|
range.setStart( el.firstChild, el.firstChild.length );
|
||||||
range.collapse( true );
|
range.collapse( true );
|
||||||
}
|
}
|
||||||
|
@ -1678,7 +1680,7 @@ var addFormat = function ( tag, attributes, range ) {
|
||||||
range.commonAncestorContainer,
|
range.commonAncestorContainer,
|
||||||
SHOW_TEXT,
|
SHOW_TEXT,
|
||||||
function ( node ) {
|
function ( node ) {
|
||||||
return range.containsNode( node, true ) ?
|
return isNodeContainedInRange( range, node, true ) ?
|
||||||
FILTER_ACCEPT : FILTER_SKIP;
|
FILTER_ACCEPT : FILTER_SKIP;
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
|
@ -1741,7 +1743,7 @@ var removeFormat = function ( tag, attributes, range, partial ) {
|
||||||
} else {
|
} else {
|
||||||
fixer = doc.createTextNode( '' );
|
fixer = doc.createTextNode( '' );
|
||||||
}
|
}
|
||||||
range._insertNode( fixer );
|
insertNodeInRange( range, fixer );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find block-level ancestor of selection
|
// Find block-level ancestor of selection
|
||||||
|
@ -1760,7 +1762,7 @@ var removeFormat = function ( tag, attributes, range, partial ) {
|
||||||
examineNode = function ( node, exemplar ) {
|
examineNode = function ( node, exemplar ) {
|
||||||
// If the node is completely contained by the range then
|
// If the node is completely contained by the range then
|
||||||
// we're going to remove all formatting so ignore it.
|
// we're going to remove all formatting so ignore it.
|
||||||
if ( range.containsNode( node, false ) ) {
|
if ( isNodeContainedInRange( range, node, false ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1769,7 +1771,7 @@ var removeFormat = function ( tag, attributes, range, partial ) {
|
||||||
|
|
||||||
// If not at least partially contained, wrap entire contents
|
// If not at least partially contained, wrap entire contents
|
||||||
// in a clone of the tag we're removing and we're done.
|
// in a clone of the tag we're removing and we're done.
|
||||||
if ( !range.containsNode( node, true ) ) {
|
if ( !isNodeContainedInRange( range, node, true ) ) {
|
||||||
// Ignore bookmarks and empty text nodes
|
// Ignore bookmarks and empty text nodes
|
||||||
if ( node.nodeName !== 'INPUT' &&
|
if ( node.nodeName !== 'INPUT' &&
|
||||||
( !isText || node.data ) ) {
|
( !isText || node.data ) ) {
|
||||||
|
@ -1800,7 +1802,7 @@ var removeFormat = function ( tag, attributes, range, partial ) {
|
||||||
},
|
},
|
||||||
formatTags = Array.prototype.filter.call(
|
formatTags = Array.prototype.filter.call(
|
||||||
root.getElementsByTagName( tag ), function ( el ) {
|
root.getElementsByTagName( tag ), function ( el ) {
|
||||||
return range.containsNode( el, true ) &&
|
return isNodeContainedInRange( range, el, true ) &&
|
||||||
hasTagAttributes( el, tag, attributes );
|
hasTagAttributes( el, tag, attributes );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1912,8 +1914,8 @@ var forEachBlock = function ( fn, mutates, range ) {
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
}
|
}
|
||||||
|
|
||||||
var start = range.getStartBlock(),
|
var start = getStartBlockOfRange( range ),
|
||||||
end = range.getEndBlock();
|
end = getEndBlockOfRange( range );
|
||||||
if ( start && end ) {
|
if ( start && end ) {
|
||||||
do {
|
do {
|
||||||
if ( fn( start ) || start === end ) { break; }
|
if ( fn( start ) || start === end ) { break; }
|
||||||
|
@ -1950,14 +1952,14 @@ var modifyBlocks = function ( modify, range ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Expand range to block boundaries
|
// 3. Expand range to block boundaries
|
||||||
range.expandToBlockBoundaries();
|
expandRangeToBlockBoundaries( range );
|
||||||
|
|
||||||
// 4. Remove range.
|
// 4. Remove range.
|
||||||
range.moveBoundariesUpTree( body );
|
moveRangeBoundariesUpTree( range, body );
|
||||||
var frag = range._extractContents( body );
|
var frag = extractContentsOfRange( range, body );
|
||||||
|
|
||||||
// 5. Modify tree of fragment and reinsert.
|
// 5. Modify tree of fragment and reinsert.
|
||||||
range._insertNode( modify( frag ) );
|
insertNodeInRange( range, modify( frag ) );
|
||||||
|
|
||||||
// 6. Merge containers at edges
|
// 6. Merge containers at edges
|
||||||
if ( range.endOffset < range.endContainer.childNodes.length ) {
|
if ( range.endOffset < range.endContainer.childNodes.length ) {
|
||||||
|
@ -2541,7 +2543,7 @@ addEventListener( isIE ? 'beforepaste' : 'paste', function ( event ) {
|
||||||
|
|
||||||
// Insert pasted data
|
// Insert pasted data
|
||||||
if ( doPaste ) {
|
if ( doPaste ) {
|
||||||
range.insertTreeFragment( frag );
|
insertTreeFragmentIntoRange( range, frag );
|
||||||
docWasChanged();
|
docWasChanged();
|
||||||
|
|
||||||
range.collapse( false );
|
range.collapse( false );
|
||||||
|
@ -2615,7 +2617,7 @@ var afterDelete = function () {
|
||||||
parent = getPreviousBlock( parent );
|
parent = getPreviousBlock( parent );
|
||||||
}
|
}
|
||||||
fixCursor( parent );
|
fixCursor( parent );
|
||||||
range.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
setSelection( range );
|
setSelection( range );
|
||||||
updatePath( range );
|
updatePath( range );
|
||||||
}
|
}
|
||||||
|
@ -2656,10 +2658,10 @@ var keyHandlers = {
|
||||||
// Selected text is overwritten, therefore delete the contents
|
// Selected text is overwritten, therefore delete the contents
|
||||||
// to collapse selection.
|
// to collapse selection.
|
||||||
if ( !range.collapsed ) {
|
if ( !range.collapsed ) {
|
||||||
range._deleteContents();
|
deleteContentsOfRange( range );
|
||||||
}
|
}
|
||||||
|
|
||||||
var block = range.getStartBlock(),
|
var block = getStartBlockOfRange( range ),
|
||||||
tag = block ? block.nodeName : 'DIV',
|
tag = block ? block.nodeName : 'DIV',
|
||||||
splitTag = tagAfterSplit[ tag ],
|
splitTag = tagAfterSplit[ tag ],
|
||||||
nodeAfterSplit;
|
nodeAfterSplit;
|
||||||
|
@ -2667,7 +2669,7 @@ var keyHandlers = {
|
||||||
// If this is a malformed bit of document, just play it safe
|
// If this is a malformed bit of document, just play it safe
|
||||||
// and insert a <br>.
|
// and insert a <br>.
|
||||||
if ( !block ) {
|
if ( !block ) {
|
||||||
range._insertNode( createElement( 'BR' ) );
|
insertNodeInRange( range, createElement( 'BR' ) );
|
||||||
range.collapse( false );
|
range.collapse( false );
|
||||||
setSelection( range );
|
setSelection( range );
|
||||||
updatePath( range, true );
|
updatePath( range, true );
|
||||||
|
@ -2711,7 +2713,7 @@ var keyHandlers = {
|
||||||
}
|
}
|
||||||
range.setStart( splitNode, splitOffset );
|
range.setStart( splitNode, splitOffset );
|
||||||
range.setEnd( splitNode, splitOffset );
|
range.setEnd( splitNode, splitOffset );
|
||||||
block = range.getStartBlock();
|
block = getStartBlockOfRange( range );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !block.textContent ) {
|
if ( !block.textContent ) {
|
||||||
|
@ -2785,16 +2787,16 @@ var keyHandlers = {
|
||||||
recordUndoState( range );
|
recordUndoState( range );
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
range._deleteContents();
|
deleteContentsOfRange( range );
|
||||||
setSelection( range );
|
setSelection( range );
|
||||||
updatePath( range, true );
|
updatePath( range, true );
|
||||||
}
|
}
|
||||||
// If at beginning of block, merge with previous
|
// If at beginning of block, merge with previous
|
||||||
else if ( range.startsAtBlockBoundary() ) {
|
else if ( rangeDoesStartAtBlockBoundary( range ) ) {
|
||||||
recordUndoState( range );
|
recordUndoState( range );
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var current = range.getStartBlock(),
|
var current = getStartBlockOfRange( range ),
|
||||||
previous = current && getPreviousBlock( current );
|
previous = current && getPreviousBlock( current );
|
||||||
// Must not be at the very beginning of the text area.
|
// Must not be at the very beginning of the text area.
|
||||||
if ( previous ) {
|
if ( previous ) {
|
||||||
|
@ -2851,16 +2853,16 @@ var keyHandlers = {
|
||||||
recordUndoState( range );
|
recordUndoState( range );
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
range._deleteContents();
|
deleteContentsOfRange( range );
|
||||||
setSelection( range );
|
setSelection( range );
|
||||||
updatePath( range, true );
|
updatePath( range, true );
|
||||||
}
|
}
|
||||||
// If at end of block, merge next into this block
|
// If at end of block, merge next into this block
|
||||||
else if ( range.endsAtBlockBoundary() ) {
|
else if ( rangeDoesEndAtBlockBoundary( range ) ) {
|
||||||
recordUndoState( range );
|
recordUndoState( range );
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var current = range.getStartBlock(),
|
var current = getStartBlockOfRange( range ),
|
||||||
next = current && getNextBlock( current );
|
next = current && getNextBlock( current );
|
||||||
// Must not be at the very end of the text area.
|
// Must not be at the very end of the text area.
|
||||||
if ( next ) {
|
if ( next ) {
|
||||||
|
@ -3093,7 +3095,7 @@ editor = win.editor = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getSelectedText: function () {
|
getSelectedText: function () {
|
||||||
return getSelection().getTextContent();
|
return getTextContentInRange( getSelection() );
|
||||||
},
|
},
|
||||||
|
|
||||||
insertElement: chain( insertElement ),
|
insertElement: chain( insertElement ),
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -44,6 +44,21 @@
|
||||||
mergeContainers,
|
mergeContainers,
|
||||||
createElement,
|
createElement,
|
||||||
|
|
||||||
|
forEachTextNodeInRange,
|
||||||
|
getTextContentInRange,
|
||||||
|
insertNodeInRange,
|
||||||
|
extractContentsOfRange,
|
||||||
|
deleteContentsOfRange,
|
||||||
|
insertTreeFragmentIntoRange,
|
||||||
|
isNodeContainedInRange,
|
||||||
|
moveRangeBoundariesDownTree,
|
||||||
|
moveRangeBoundariesUpTree,
|
||||||
|
getStartBlockOfRange,
|
||||||
|
getEndBlockOfRange,
|
||||||
|
rangeDoesStartAtBlockBoundary,
|
||||||
|
rangeDoesEndAtBlockBoundary,
|
||||||
|
expandRangeToBlockBoundaries,
|
||||||
|
|
||||||
Range,
|
Range,
|
||||||
top,
|
top,
|
||||||
console,
|
console,
|
||||||
|
@ -321,11 +336,11 @@ var insertElement = function ( el, range ) {
|
||||||
if ( !range ) { range = getSelection(); }
|
if ( !range ) { range = getSelection(); }
|
||||||
range.collapse( true );
|
range.collapse( true );
|
||||||
if ( isInline( el ) ) {
|
if ( isInline( el ) ) {
|
||||||
range._insertNode( el );
|
insertNodeInRange( range, el );
|
||||||
range.setStartAfter( el );
|
range.setStartAfter( el );
|
||||||
} else {
|
} else {
|
||||||
// Get containing block node.
|
// Get containing block node.
|
||||||
var splitNode = range.getStartBlock() || body,
|
var splitNode = getStartBlockOfRange( range ) || body,
|
||||||
parent, nodeAfterSplit;
|
parent, nodeAfterSplit;
|
||||||
// While at end of container node, move up DOM tree.
|
// While at end of container node, move up DOM tree.
|
||||||
while ( splitNode !== body && !splitNode.nextSibling ) {
|
while ( splitNode !== body && !splitNode.nextSibling ) {
|
||||||
|
@ -340,7 +355,7 @@ var insertElement = function ( el, range ) {
|
||||||
body.insertBefore( el, nodeAfterSplit );
|
body.insertBefore( el, nodeAfterSplit );
|
||||||
range.setStart( nodeAfterSplit, 0 );
|
range.setStart( nodeAfterSplit, 0 );
|
||||||
range.setStart( nodeAfterSplit, 0 );
|
range.setStart( nodeAfterSplit, 0 );
|
||||||
range.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
} else {
|
} else {
|
||||||
body.appendChild( el );
|
body.appendChild( el );
|
||||||
// Insert blank line below block.
|
// Insert blank line below block.
|
||||||
|
@ -370,9 +385,9 @@ var saveRangeToBookmark = function ( range ) {
|
||||||
}),
|
}),
|
||||||
temp;
|
temp;
|
||||||
|
|
||||||
range._insertNode( startNode );
|
insertNodeInRange( range, startNode );
|
||||||
range.collapse( false );
|
range.collapse( false );
|
||||||
range._insertNode( endNode );
|
insertNodeInRange( range, endNode );
|
||||||
|
|
||||||
// In a collapsed range, the start is sometimes inserted after the end!
|
// In a collapsed range, the start is sometimes inserted after the end!
|
||||||
if ( startNode.compareDocumentPosition( endNode ) &
|
if ( startNode.compareDocumentPosition( endNode ) &
|
||||||
|
@ -424,7 +439,7 @@ var getRangeAndRemoveBookmark = function ( range ) {
|
||||||
range.setEnd( _range.endContainer, _range.endOffset );
|
range.setEnd( _range.endContainer, _range.endOffset );
|
||||||
collapsed = range.collapsed;
|
collapsed = range.collapsed;
|
||||||
|
|
||||||
range.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
if ( collapsed ) {
|
if ( collapsed ) {
|
||||||
range.collapse( true );
|
range.collapse( true );
|
||||||
}
|
}
|
||||||
|
@ -554,7 +569,7 @@ var hasFormat = function ( tag, attributes, range ) {
|
||||||
// Otherwise, check each text node at least partially contained within
|
// Otherwise, check each text node at least partially contained within
|
||||||
// the selection and make sure all of them have the format we want.
|
// the selection and make sure all of them have the format we want.
|
||||||
walker = new TreeWalker( root, SHOW_TEXT, function ( node ) {
|
walker = new TreeWalker( root, SHOW_TEXT, function ( node ) {
|
||||||
return range.containsNode( node, true ) ?
|
return isNodeContainedInRange( range, node, true ) ?
|
||||||
FILTER_ACCEPT : FILTER_SKIP;
|
FILTER_ACCEPT : FILTER_SKIP;
|
||||||
}, false );
|
}, false );
|
||||||
|
|
||||||
|
@ -577,7 +592,7 @@ var addFormat = function ( tag, attributes, range ) {
|
||||||
|
|
||||||
if ( range.collapsed ) {
|
if ( range.collapsed ) {
|
||||||
el = fixCursor( createElement( tag, attributes ) );
|
el = fixCursor( createElement( tag, attributes ) );
|
||||||
range._insertNode( el );
|
insertNodeInRange( range, el );
|
||||||
range.setStart( el.firstChild, el.firstChild.length );
|
range.setStart( el.firstChild, el.firstChild.length );
|
||||||
range.collapse( true );
|
range.collapse( true );
|
||||||
}
|
}
|
||||||
|
@ -594,7 +609,7 @@ var addFormat = function ( tag, attributes, range ) {
|
||||||
range.commonAncestorContainer,
|
range.commonAncestorContainer,
|
||||||
SHOW_TEXT,
|
SHOW_TEXT,
|
||||||
function ( node ) {
|
function ( node ) {
|
||||||
return range.containsNode( node, true ) ?
|
return isNodeContainedInRange( range, node, true ) ?
|
||||||
FILTER_ACCEPT : FILTER_SKIP;
|
FILTER_ACCEPT : FILTER_SKIP;
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
|
@ -657,7 +672,7 @@ var removeFormat = function ( tag, attributes, range, partial ) {
|
||||||
} else {
|
} else {
|
||||||
fixer = doc.createTextNode( '' );
|
fixer = doc.createTextNode( '' );
|
||||||
}
|
}
|
||||||
range._insertNode( fixer );
|
insertNodeInRange( range, fixer );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find block-level ancestor of selection
|
// Find block-level ancestor of selection
|
||||||
|
@ -676,7 +691,7 @@ var removeFormat = function ( tag, attributes, range, partial ) {
|
||||||
examineNode = function ( node, exemplar ) {
|
examineNode = function ( node, exemplar ) {
|
||||||
// If the node is completely contained by the range then
|
// If the node is completely contained by the range then
|
||||||
// we're going to remove all formatting so ignore it.
|
// we're going to remove all formatting so ignore it.
|
||||||
if ( range.containsNode( node, false ) ) {
|
if ( isNodeContainedInRange( range, node, false ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,7 +700,7 @@ var removeFormat = function ( tag, attributes, range, partial ) {
|
||||||
|
|
||||||
// If not at least partially contained, wrap entire contents
|
// If not at least partially contained, wrap entire contents
|
||||||
// in a clone of the tag we're removing and we're done.
|
// in a clone of the tag we're removing and we're done.
|
||||||
if ( !range.containsNode( node, true ) ) {
|
if ( !isNodeContainedInRange( range, node, true ) ) {
|
||||||
// Ignore bookmarks and empty text nodes
|
// Ignore bookmarks and empty text nodes
|
||||||
if ( node.nodeName !== 'INPUT' &&
|
if ( node.nodeName !== 'INPUT' &&
|
||||||
( !isText || node.data ) ) {
|
( !isText || node.data ) ) {
|
||||||
|
@ -716,7 +731,7 @@ var removeFormat = function ( tag, attributes, range, partial ) {
|
||||||
},
|
},
|
||||||
formatTags = Array.prototype.filter.call(
|
formatTags = Array.prototype.filter.call(
|
||||||
root.getElementsByTagName( tag ), function ( el ) {
|
root.getElementsByTagName( tag ), function ( el ) {
|
||||||
return range.containsNode( el, true ) &&
|
return isNodeContainedInRange( range, el, true ) &&
|
||||||
hasTagAttributes( el, tag, attributes );
|
hasTagAttributes( el, tag, attributes );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -828,8 +843,8 @@ var forEachBlock = function ( fn, mutates, range ) {
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
}
|
}
|
||||||
|
|
||||||
var start = range.getStartBlock(),
|
var start = getStartBlockOfRange( range ),
|
||||||
end = range.getEndBlock();
|
end = getEndBlockOfRange( range );
|
||||||
if ( start && end ) {
|
if ( start && end ) {
|
||||||
do {
|
do {
|
||||||
if ( fn( start ) || start === end ) { break; }
|
if ( fn( start ) || start === end ) { break; }
|
||||||
|
@ -866,14 +881,14 @@ var modifyBlocks = function ( modify, range ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Expand range to block boundaries
|
// 3. Expand range to block boundaries
|
||||||
range.expandToBlockBoundaries();
|
expandRangeToBlockBoundaries( range );
|
||||||
|
|
||||||
// 4. Remove range.
|
// 4. Remove range.
|
||||||
range.moveBoundariesUpTree( body );
|
moveRangeBoundariesUpTree( range, body );
|
||||||
var frag = range._extractContents( body );
|
var frag = extractContentsOfRange( range, body );
|
||||||
|
|
||||||
// 5. Modify tree of fragment and reinsert.
|
// 5. Modify tree of fragment and reinsert.
|
||||||
range._insertNode( modify( frag ) );
|
insertNodeInRange( range, modify( frag ) );
|
||||||
|
|
||||||
// 6. Merge containers at edges
|
// 6. Merge containers at edges
|
||||||
if ( range.endOffset < range.endContainer.childNodes.length ) {
|
if ( range.endOffset < range.endContainer.childNodes.length ) {
|
||||||
|
@ -1457,7 +1472,7 @@ addEventListener( isIE ? 'beforepaste' : 'paste', function ( event ) {
|
||||||
|
|
||||||
// Insert pasted data
|
// Insert pasted data
|
||||||
if ( doPaste ) {
|
if ( doPaste ) {
|
||||||
range.insertTreeFragment( frag );
|
insertTreeFragmentIntoRange( range, frag );
|
||||||
docWasChanged();
|
docWasChanged();
|
||||||
|
|
||||||
range.collapse( false );
|
range.collapse( false );
|
||||||
|
@ -1531,7 +1546,7 @@ var afterDelete = function () {
|
||||||
parent = getPreviousBlock( parent );
|
parent = getPreviousBlock( parent );
|
||||||
}
|
}
|
||||||
fixCursor( parent );
|
fixCursor( parent );
|
||||||
range.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
setSelection( range );
|
setSelection( range );
|
||||||
updatePath( range );
|
updatePath( range );
|
||||||
}
|
}
|
||||||
|
@ -1572,10 +1587,10 @@ var keyHandlers = {
|
||||||
// Selected text is overwritten, therefore delete the contents
|
// Selected text is overwritten, therefore delete the contents
|
||||||
// to collapse selection.
|
// to collapse selection.
|
||||||
if ( !range.collapsed ) {
|
if ( !range.collapsed ) {
|
||||||
range._deleteContents();
|
deleteContentsOfRange( range );
|
||||||
}
|
}
|
||||||
|
|
||||||
var block = range.getStartBlock(),
|
var block = getStartBlockOfRange( range ),
|
||||||
tag = block ? block.nodeName : 'DIV',
|
tag = block ? block.nodeName : 'DIV',
|
||||||
splitTag = tagAfterSplit[ tag ],
|
splitTag = tagAfterSplit[ tag ],
|
||||||
nodeAfterSplit;
|
nodeAfterSplit;
|
||||||
|
@ -1583,7 +1598,7 @@ var keyHandlers = {
|
||||||
// If this is a malformed bit of document, just play it safe
|
// If this is a malformed bit of document, just play it safe
|
||||||
// and insert a <br>.
|
// and insert a <br>.
|
||||||
if ( !block ) {
|
if ( !block ) {
|
||||||
range._insertNode( createElement( 'BR' ) );
|
insertNodeInRange( range, createElement( 'BR' ) );
|
||||||
range.collapse( false );
|
range.collapse( false );
|
||||||
setSelection( range );
|
setSelection( range );
|
||||||
updatePath( range, true );
|
updatePath( range, true );
|
||||||
|
@ -1627,7 +1642,7 @@ var keyHandlers = {
|
||||||
}
|
}
|
||||||
range.setStart( splitNode, splitOffset );
|
range.setStart( splitNode, splitOffset );
|
||||||
range.setEnd( splitNode, splitOffset );
|
range.setEnd( splitNode, splitOffset );
|
||||||
block = range.getStartBlock();
|
block = getStartBlockOfRange( range );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !block.textContent ) {
|
if ( !block.textContent ) {
|
||||||
|
@ -1701,16 +1716,16 @@ var keyHandlers = {
|
||||||
recordUndoState( range );
|
recordUndoState( range );
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
range._deleteContents();
|
deleteContentsOfRange( range );
|
||||||
setSelection( range );
|
setSelection( range );
|
||||||
updatePath( range, true );
|
updatePath( range, true );
|
||||||
}
|
}
|
||||||
// If at beginning of block, merge with previous
|
// If at beginning of block, merge with previous
|
||||||
else if ( range.startsAtBlockBoundary() ) {
|
else if ( rangeDoesStartAtBlockBoundary( range ) ) {
|
||||||
recordUndoState( range );
|
recordUndoState( range );
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var current = range.getStartBlock(),
|
var current = getStartBlockOfRange( range ),
|
||||||
previous = current && getPreviousBlock( current );
|
previous = current && getPreviousBlock( current );
|
||||||
// Must not be at the very beginning of the text area.
|
// Must not be at the very beginning of the text area.
|
||||||
if ( previous ) {
|
if ( previous ) {
|
||||||
|
@ -1767,16 +1782,16 @@ var keyHandlers = {
|
||||||
recordUndoState( range );
|
recordUndoState( range );
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
range._deleteContents();
|
deleteContentsOfRange( range );
|
||||||
setSelection( range );
|
setSelection( range );
|
||||||
updatePath( range, true );
|
updatePath( range, true );
|
||||||
}
|
}
|
||||||
// If at end of block, merge next into this block
|
// If at end of block, merge next into this block
|
||||||
else if ( range.endsAtBlockBoundary() ) {
|
else if ( rangeDoesEndAtBlockBoundary( range ) ) {
|
||||||
recordUndoState( range );
|
recordUndoState( range );
|
||||||
getRangeAndRemoveBookmark( range );
|
getRangeAndRemoveBookmark( range );
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var current = range.getStartBlock(),
|
var current = getStartBlockOfRange( range ),
|
||||||
next = current && getNextBlock( current );
|
next = current && getNextBlock( current );
|
||||||
// Must not be at the very end of the text area.
|
// Must not be at the very end of the text area.
|
||||||
if ( next ) {
|
if ( next ) {
|
||||||
|
@ -2009,7 +2024,7 @@ editor = win.editor = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getSelectedText: function () {
|
getSelectedText: function () {
|
||||||
return getSelection().getTextContent();
|
return getTextContentInRange( getSelection() );
|
||||||
},
|
},
|
||||||
|
|
||||||
insertElement: chain( insertElement ),
|
insertElement: chain( insertElement ),
|
||||||
|
|
181
source/Range.js
181
source/Range.js
|
@ -20,9 +20,7 @@
|
||||||
fixCursor,
|
fixCursor,
|
||||||
split,
|
split,
|
||||||
mergeWithBlock,
|
mergeWithBlock,
|
||||||
mergeContainers,
|
mergeContainers
|
||||||
|
|
||||||
Range
|
|
||||||
*/
|
*/
|
||||||
/*jshint strict:false */
|
/*jshint strict:false */
|
||||||
|
|
||||||
|
@ -51,11 +49,11 @@ var getNodeAfter = function ( node, offset ) {
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
var RangePrototype = Range.prototype;
|
// ---
|
||||||
|
|
||||||
RangePrototype.forEachTextNode = function ( fn ) {
|
var forEachTextNodeInRange = function ( range, fn ) {
|
||||||
var range = this.cloneRange();
|
range = range.cloneRange();
|
||||||
range.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
|
|
||||||
var startContainer = range.startContainer,
|
var startContainer = range.startContainer,
|
||||||
endContainer = range.endContainer,
|
endContainer = range.endContainer,
|
||||||
|
@ -71,9 +69,9 @@ RangePrototype.forEachTextNode = function ( fn ) {
|
||||||
( textnode = walker.nextNode() ) ) {}
|
( textnode = walker.nextNode() ) ) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.getTextContent = function () {
|
var getTextContentInRange = function ( range ) {
|
||||||
var textContent = '';
|
var textContent = '';
|
||||||
this.forEachTextNode( function ( textnode, range ) {
|
forEachTextNodeInRange( range, function ( textnode, range ) {
|
||||||
var value = textnode.data;
|
var value = textnode.data;
|
||||||
if ( value && ( /\S/.test( value ) ) ) {
|
if ( value && ( /\S/.test( value ) ) ) {
|
||||||
if ( textnode === range.endContainer ) {
|
if ( textnode === range.endContainer ) {
|
||||||
|
@ -90,12 +88,12 @@ RangePrototype.getTextContent = function () {
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
RangePrototype._insertNode = function ( node ) {
|
var insertNodeInRange = function ( range, node ) {
|
||||||
// Insert at start.
|
// Insert at start.
|
||||||
var startContainer = this.startContainer,
|
var startContainer = range.startContainer,
|
||||||
startOffset = this.startOffset,
|
startOffset = range.startOffset,
|
||||||
endContainer = this.endContainer,
|
endContainer = range.endContainer,
|
||||||
endOffset = this.endOffset,
|
endOffset = range.endOffset,
|
||||||
parent, children, childCount, afterSplit;
|
parent, children, childCount, afterSplit;
|
||||||
|
|
||||||
// If part way through a text node, split it.
|
// If part way through a text node, split it.
|
||||||
|
@ -104,7 +102,7 @@ RangePrototype._insertNode = function ( node ) {
|
||||||
children = parent.childNodes;
|
children = parent.childNodes;
|
||||||
if ( startOffset === startContainer.length ) {
|
if ( startOffset === startContainer.length ) {
|
||||||
startOffset = indexOf.call( children, startContainer ) + 1;
|
startOffset = indexOf.call( children, startContainer ) + 1;
|
||||||
if ( this.collapsed ) {
|
if ( range.collapsed ) {
|
||||||
endContainer = parent;
|
endContainer = parent;
|
||||||
endOffset = startOffset;
|
endOffset = startOffset;
|
||||||
}
|
}
|
||||||
|
@ -138,20 +136,18 @@ RangePrototype._insertNode = function ( node ) {
|
||||||
endOffset += children.length - childCount;
|
endOffset += children.length - childCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setStart( startContainer, startOffset );
|
range.setStart( startContainer, startOffset );
|
||||||
this.setEnd( endContainer, endOffset );
|
range.setEnd( endContainer, endOffset );
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype._extractContents = function ( common ) {
|
var extractContentsOfRange = function ( range, common ) {
|
||||||
var startContainer = this.startContainer,
|
var startContainer = range.startContainer,
|
||||||
startOffset = this.startOffset,
|
startOffset = range.startOffset,
|
||||||
endContainer = this.endContainer,
|
endContainer = range.endContainer,
|
||||||
endOffset = this.endOffset;
|
endOffset = range.endOffset;
|
||||||
|
|
||||||
if ( !common ) {
|
if ( !common ) {
|
||||||
common = this.commonAncestorContainer;
|
common = range.commonAncestorContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( common.nodeType === TEXT_NODE ) {
|
if ( common.nodeType === TEXT_NODE ) {
|
||||||
|
@ -170,28 +166,28 @@ RangePrototype._extractContents = function ( common ) {
|
||||||
startNode = next;
|
startNode = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setStart( common, endNode ?
|
range.setStart( common, endNode ?
|
||||||
indexOf.call( common.childNodes, endNode ) :
|
indexOf.call( common.childNodes, endNode ) :
|
||||||
common.childNodes.length );
|
common.childNodes.length );
|
||||||
this.collapse( true );
|
range.collapse( true );
|
||||||
|
|
||||||
fixCursor( common );
|
fixCursor( common );
|
||||||
|
|
||||||
return frag;
|
return frag;
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype._deleteContents = function () {
|
var deleteContentsOfRange = function ( range ) {
|
||||||
// Move boundaries up as much as possible to reduce need to split.
|
// Move boundaries up as much as possible to reduce need to split.
|
||||||
this.moveBoundariesUpTree();
|
moveRangeBoundariesUpTree( range );
|
||||||
|
|
||||||
// Remove selected range
|
// Remove selected range
|
||||||
this._extractContents();
|
extractContentsOfRange( range );
|
||||||
|
|
||||||
// If we split into two different blocks, merge the blocks.
|
// If we split into two different blocks, merge the blocks.
|
||||||
var startBlock = this.getStartBlock(),
|
var startBlock = getStartBlockOfRange( range ),
|
||||||
endBlock = this.getEndBlock();
|
endBlock = getEndBlockOfRange( range );
|
||||||
if ( startBlock && endBlock && startBlock !== endBlock ) {
|
if ( startBlock && endBlock && startBlock !== endBlock ) {
|
||||||
mergeWithBlock( startBlock, endBlock, this );
|
mergeWithBlock( startBlock, endBlock, range );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure block has necessary children
|
// Ensure block has necessary children
|
||||||
|
@ -200,27 +196,25 @@ RangePrototype._deleteContents = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure body has a block-level element in it.
|
// Ensure body has a block-level element in it.
|
||||||
var body = this.endContainer.ownerDocument.body,
|
var body = range.endContainer.ownerDocument.body,
|
||||||
child = body.firstChild;
|
child = body.firstChild;
|
||||||
if ( !child || child.nodeName === 'BR' ) {
|
if ( !child || child.nodeName === 'BR' ) {
|
||||||
fixCursor( body );
|
fixCursor( body );
|
||||||
this.selectNodeContents( body.firstChild );
|
range.selectNodeContents( body.firstChild );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure valid range (must have only block or inline containers)
|
// Ensure valid range (must have only block or inline containers)
|
||||||
var isCollapsed = this.collapsed;
|
var isCollapsed = range.collapsed;
|
||||||
this.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
if ( isCollapsed ) {
|
if ( isCollapsed ) {
|
||||||
// Collapse
|
// Collapse
|
||||||
this.collapse( true );
|
range.collapse( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
RangePrototype.insertTreeFragment = function ( frag ) {
|
var insertTreeFragmentIntoRange = function ( range, frag ) {
|
||||||
// Check if it's all inline content
|
// Check if it's all inline content
|
||||||
var allInline = true,
|
var allInline = true,
|
||||||
children = frag.childNodes,
|
children = frag.childNodes,
|
||||||
|
@ -233,23 +227,23 @@ RangePrototype.insertTreeFragment = function ( frag ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete any selected content
|
// Delete any selected content
|
||||||
if ( !this.collapsed ) {
|
if ( !range.collapsed ) {
|
||||||
this._deleteContents();
|
deleteContentsOfRange( range );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move range down into text ndoes
|
// Move range down into text ndoes
|
||||||
this.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
|
|
||||||
// If inline, just insert at the current position.
|
// If inline, just insert at the current position.
|
||||||
if ( allInline ) {
|
if ( allInline ) {
|
||||||
this._insertNode( frag );
|
insertNodeInRange( range, frag );
|
||||||
this.collapse( false );
|
range.collapse( false );
|
||||||
}
|
}
|
||||||
// Otherwise, split up to body, insert inline before and after split
|
// Otherwise, split up to body, insert inline before and after split
|
||||||
// and insert block in between split, then merge containers.
|
// and insert block in between split, then merge containers.
|
||||||
else {
|
else {
|
||||||
var nodeAfterSplit = split( this.startContainer, this.startOffset,
|
var nodeAfterSplit = split( range.startContainer, range.startOffset,
|
||||||
this.startContainer.ownerDocument.body ),
|
range.startContainer.ownerDocument.body ),
|
||||||
nodeBeforeSplit = nodeAfterSplit.previousSibling,
|
nodeBeforeSplit = nodeAfterSplit.previousSibling,
|
||||||
startContainer = nodeBeforeSplit,
|
startContainer = nodeBeforeSplit,
|
||||||
startOffset = startContainer.childNodes.length,
|
startOffset = startContainer.childNodes.length,
|
||||||
|
@ -305,17 +299,16 @@ RangePrototype.insertTreeFragment = function ( frag ) {
|
||||||
mergeContainers( nodeBeforeSplit );
|
mergeContainers( nodeBeforeSplit );
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setStart( startContainer, startOffset );
|
range.setStart( startContainer, startOffset );
|
||||||
this.setEnd( endContainer, endOffset );
|
range.setEnd( endContainer, endOffset );
|
||||||
this.moveBoundariesDownTree();
|
moveRangeBoundariesDownTree( range );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
RangePrototype.containsNode = function ( node, partial ) {
|
var isNodeContainedInRange = function ( range, node, partial ) {
|
||||||
var range = this,
|
var nodeRange = node.ownerDocument.createRange();
|
||||||
nodeRange = node.ownerDocument.createRange();
|
|
||||||
|
|
||||||
nodeRange.selectNode( node );
|
nodeRange.selectNode( node );
|
||||||
|
|
||||||
|
@ -339,11 +332,11 @@ RangePrototype.containsNode = function ( node, partial ) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.moveBoundariesDownTree = function () {
|
var moveRangeBoundariesDownTree = function ( range ) {
|
||||||
var startContainer = this.startContainer,
|
var startContainer = range.startContainer,
|
||||||
startOffset = this.startOffset,
|
startOffset = range.startOffset,
|
||||||
endContainer = this.endContainer,
|
endContainer = range.endContainer,
|
||||||
endOffset = this.endOffset,
|
endOffset = range.endOffset,
|
||||||
child;
|
child;
|
||||||
|
|
||||||
while ( startContainer.nodeType !== TEXT_NODE ) {
|
while ( startContainer.nodeType !== TEXT_NODE ) {
|
||||||
|
@ -376,26 +369,24 @@ RangePrototype.moveBoundariesDownTree = function () {
|
||||||
// If collapsed, this algorithm finds the nearest text node positions
|
// If collapsed, this algorithm finds the nearest text node positions
|
||||||
// *outside* the range rather than inside, but also it flips which is
|
// *outside* the range rather than inside, but also it flips which is
|
||||||
// assigned to which.
|
// assigned to which.
|
||||||
if ( this.collapsed ) {
|
if ( range.collapsed ) {
|
||||||
this.setStart( endContainer, endOffset );
|
range.setStart( endContainer, endOffset );
|
||||||
this.setEnd( startContainer, startOffset );
|
range.setEnd( startContainer, startOffset );
|
||||||
} else {
|
} else {
|
||||||
this.setStart( startContainer, startOffset );
|
range.setStart( startContainer, startOffset );
|
||||||
this.setEnd( endContainer, endOffset );
|
range.setEnd( endContainer, endOffset );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.moveBoundariesUpTree = function ( common ) {
|
var moveRangeBoundariesUpTree = function ( range, common ) {
|
||||||
var startContainer = this.startContainer,
|
var startContainer = range.startContainer,
|
||||||
startOffset = this.startOffset,
|
startOffset = range.startOffset,
|
||||||
endContainer = this.endContainer,
|
endContainer = range.endContainer,
|
||||||
endOffset = this.endOffset,
|
endOffset = range.endOffset,
|
||||||
parent;
|
parent;
|
||||||
|
|
||||||
if ( !common ) {
|
if ( !common ) {
|
||||||
common = this.commonAncestorContainer;
|
common = range.commonAncestorContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( startContainer !== common && !startOffset ) {
|
while ( startContainer !== common && !startOffset ) {
|
||||||
|
@ -411,16 +402,14 @@ RangePrototype.moveBoundariesUpTree = function ( common ) {
|
||||||
endContainer = parent;
|
endContainer = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setStart( startContainer, startOffset );
|
range.setStart( startContainer, startOffset );
|
||||||
this.setEnd( endContainer, endOffset );
|
range.setEnd( endContainer, endOffset );
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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.
|
||||||
RangePrototype.getStartBlock = function () {
|
var getStartBlockOfRange = function ( range ) {
|
||||||
var container = this.startContainer,
|
var container = range.startContainer,
|
||||||
block;
|
block;
|
||||||
|
|
||||||
// If inline, get the containing block.
|
// If inline, get the containing block.
|
||||||
|
@ -429,17 +418,17 @@ RangePrototype.getStartBlock = function () {
|
||||||
} else if ( isBlock( container ) ) {
|
} else if ( isBlock( container ) ) {
|
||||||
block = container;
|
block = container;
|
||||||
} else {
|
} else {
|
||||||
block = getNodeBefore( container, this.startOffset );
|
block = getNodeBefore( container, range.startOffset );
|
||||||
block = getNextBlock( block );
|
block = getNextBlock( block );
|
||||||
}
|
}
|
||||||
// Check the block actually intersects the range
|
// Check the block actually intersects the range
|
||||||
return block && this.containsNode( block, true ) ? block : null;
|
return block && isNodeContainedInRange( range, 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.
|
||||||
RangePrototype.getEndBlock = function () {
|
var getEndBlockOfRange = function ( range ) {
|
||||||
var container = this.endContainer,
|
var container = range.endContainer,
|
||||||
block, child;
|
block, child;
|
||||||
|
|
||||||
// If inline, get the containing block.
|
// If inline, get the containing block.
|
||||||
|
@ -448,7 +437,7 @@ RangePrototype.getEndBlock = function () {
|
||||||
} else if ( isBlock( container ) ) {
|
} else if ( isBlock( container ) ) {
|
||||||
block = container;
|
block = container;
|
||||||
} else {
|
} else {
|
||||||
block = getNodeAfter( container, this.endOffset );
|
block = getNodeAfter( container, range.endOffset );
|
||||||
if ( !block ) {
|
if ( !block ) {
|
||||||
block = container.ownerDocument.body;
|
block = container.ownerDocument.body;
|
||||||
while ( child = block.lastChild ) {
|
while ( child = block.lastChild ) {
|
||||||
|
@ -459,12 +448,12 @@ RangePrototype.getEndBlock = function () {
|
||||||
|
|
||||||
}
|
}
|
||||||
// Check the block actually intersects the range
|
// Check the block actually intersects the range
|
||||||
return block && this.containsNode( block, true ) ? block : null;
|
return block && isNodeContainedInRange( range, block, true ) ? block : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.startsAtBlockBoundary = function () {
|
var rangeDoesStartAtBlockBoundary = function ( range ) {
|
||||||
var startContainer = this.startContainer,
|
var startContainer = range.startContainer,
|
||||||
startOffset = this.startOffset,
|
startOffset = range.startOffset,
|
||||||
parent, child;
|
parent, child;
|
||||||
|
|
||||||
while ( isInline( startContainer ) ) {
|
while ( isInline( startContainer ) ) {
|
||||||
|
@ -484,9 +473,9 @@ RangePrototype.startsAtBlockBoundary = function () {
|
||||||
return !startOffset;
|
return !startOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.endsAtBlockBoundary = function () {
|
var rangeDoesEndAtBlockBoundary = function ( range ) {
|
||||||
var endContainer = this.endContainer,
|
var endContainer = range.endContainer,
|
||||||
endOffset = this.endOffset,
|
endOffset = range.endOffset,
|
||||||
length = getLength( endContainer ),
|
length = getLength( endContainer ),
|
||||||
parent, child;
|
parent, child;
|
||||||
|
|
||||||
|
@ -508,17 +497,15 @@ RangePrototype.endsAtBlockBoundary = function () {
|
||||||
return endOffset === length;
|
return endOffset === length;
|
||||||
};
|
};
|
||||||
|
|
||||||
RangePrototype.expandToBlockBoundaries = function () {
|
var expandRangeToBlockBoundaries = function ( range ) {
|
||||||
var start = this.getStartBlock(),
|
var start = getStartBlockOfRange( range ),
|
||||||
end = this.getEndBlock(),
|
end = getEndBlockOfRange( range ),
|
||||||
parent;
|
parent;
|
||||||
|
|
||||||
if ( start && end ) {
|
if ( start && end ) {
|
||||||
parent = start.parentNode;
|
parent = start.parentNode;
|
||||||
this.setStart( parent, indexOf.call( parent.childNodes, start ) );
|
range.setStart( parent, indexOf.call( parent.childNodes, start ) );
|
||||||
parent = end.parentNode;
|
parent = end.parentNode;
|
||||||
this.setEnd( parent, indexOf.call( parent.childNodes, end ) + 1 );
|
range.setEnd( parent, indexOf.call( parent.childNodes, end ) + 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue