RangeImplpublic class RangeImpl extends Object implements RangeThe RangeImpl class implements the org.w3c.dom.range.Range interface.
Please see the API documentation for the interface classes
and use the interfaces in your client programs. |
Fields Summary |
---|
DocumentImpl | fDocument | Node | fStartContainer | Node | fEndContainer | int | fStartOffset | int | fEndOffset | boolean | fIsCollapsed | boolean | fDetach | Node | fInsertNode | Node | fDeleteNode | Node | fSplitNode | boolean | fInsertedFromRange | Node | fRemoveChildThis function is called within Range
instead of Node.removeChild,
so that the range can remember that it is actively
removing this child. | static final int | EXTRACT_CONTENTS | static final int | CLONE_CONTENTS | static final int | DELETE_CONTENTS |
Constructors Summary |
---|
public RangeImpl(DocumentImpl document)The constructor. Clients must use DocumentRange.createRange(),
because it registers the Range with the document, so it can
be fixed-up.
fDocument = document;
fStartContainer = document;
fEndContainer = document;
fStartOffset = 0;
fEndOffset = 0;
fDetach = false;
|
Methods Summary |
---|
void | checkIndex(org.w3c.dom.Node refNode, int offset)
if (offset < 0) {
throw new DOMException(
DOMException.INDEX_SIZE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null));
}
int type = refNode.getNodeType();
// If the node contains text, ensure that the
// offset of the range is <= to the length of the text
if (type == Node.TEXT_NODE
|| type == Node.CDATA_SECTION_NODE
|| type == Node.COMMENT_NODE
|| type == Node.PROCESSING_INSTRUCTION_NODE) {
if (offset > refNode.getNodeValue().length()) {
throw new DOMException(DOMException.INDEX_SIZE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null));
}
}
else {
// Since the node is not text, ensure that the offset
// is valid with respect to the number of child nodes
if (offset > refNode.getChildNodes().getLength()) {
throw new DOMException(DOMException.INDEX_SIZE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null));
}
}
| public org.w3c.dom.DocumentFragment | cloneContents()
return traverseContents(CLONE_CONTENTS);
| public org.w3c.dom.ranges.Range | cloneRange()
if( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
Range range = fDocument.createRange();
range.setStart(fStartContainer, fStartOffset);
range.setEnd(fEndContainer, fEndOffset);
return range;
| public void | collapse(boolean toStart)
if( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if (toStart) {
fEndContainer = fStartContainer;
fEndOffset = fStartOffset;
} else {
fStartContainer = fEndContainer;
fStartOffset = fEndOffset;
}
| public short | compareBoundaryPoints(short how, org.w3c.dom.ranges.Range sourceRange)
if (fDocument.errorChecking) {
if( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
// WRONG_DOCUMENT_ERR: Raised if the two Ranges are not in the same Document or DocumentFragment.
if ((fDocument != sourceRange.getStartContainer().getOwnerDocument()
&& fDocument != sourceRange.getStartContainer()
&& sourceRange.getStartContainer() != null)
|| (fDocument != sourceRange.getEndContainer().getOwnerDocument()
&& fDocument != sourceRange.getEndContainer()
&& sourceRange.getStartContainer() != null)) {
throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage( DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
}
}
Node endPointA;
Node endPointB;
int offsetA;
int offsetB;
if (how == START_TO_START) {
endPointA = sourceRange.getStartContainer();
endPointB = fStartContainer;
offsetA = sourceRange.getStartOffset();
offsetB = fStartOffset;
} else
if (how == START_TO_END) {
endPointA = sourceRange.getStartContainer();
endPointB = fEndContainer;
offsetA = sourceRange.getStartOffset();
offsetB = fEndOffset;
} else
if (how == END_TO_START) {
endPointA = sourceRange.getEndContainer();
endPointB = fStartContainer;
offsetA = sourceRange.getEndOffset();
offsetB = fStartOffset;
} else {
endPointA = sourceRange.getEndContainer();
endPointB = fEndContainer;
offsetA = sourceRange.getEndOffset();
offsetB = fEndOffset;
}
// The DOM Spec outlines four cases that need to be tested
// to compare two range boundary points:
// case 1: same container
// case 2: Child C of container A is ancestor of B
// case 3: Child C of container B is ancestor of A
// case 4: preorder traversal of context tree.
// case 1: same container
if (endPointA == endPointB) {
if (offsetA < offsetB) return 1;
if (offsetA == offsetB) return 0;
return -1;
}
// case 2: Child C of container A is ancestor of B
// This can be quickly tested by walking the parent chain of B
for ( Node c = endPointB, p = c.getParentNode();
p != null;
c = p, p = p.getParentNode())
{
if (p == endPointA) {
int index = indexOf(c, endPointA);
if (offsetA <= index) return 1;
return -1;
}
}
// case 3: Child C of container B is ancestor of A
// This can be quickly tested by walking the parent chain of A
for ( Node c = endPointA, p = c.getParentNode();
p != null;
c = p, p = p.getParentNode())
{
if (p == endPointB) {
int index = indexOf(c, endPointB);
if (index < offsetB) return 1;
return -1;
}
}
// case 4: preorder traversal of context tree.
// Instead of literally walking the context tree in pre-order,
// we use relative node depth walking which is usually faster
int depthDiff = 0;
for ( Node n = endPointA; n != null; n = n.getParentNode() )
depthDiff++;
for ( Node n = endPointB; n != null; n = n.getParentNode() )
depthDiff--;
while (depthDiff > 0) {
endPointA = endPointA.getParentNode();
depthDiff--;
}
while (depthDiff < 0) {
endPointB = endPointB.getParentNode();
depthDiff++;
}
for (Node pA = endPointA.getParentNode(),
pB = endPointB.getParentNode();
pA != pB;
pA = pA.getParentNode(), pB = pB.getParentNode() )
{
endPointA = pA;
endPointB = pB;
}
for ( Node n = endPointA.getNextSibling();
n != null;
n = n.getNextSibling() )
{
if (n == endPointB) {
return 1;
}
}
return -1;
| public void | deleteContents()
traverseContents(DELETE_CONTENTS);
| void | deleteData(org.w3c.dom.CharacterData node, int offset, int count)This function inserts text into a Node and invokes
a method to fix-up all other Ranges.
fDeleteNode = node;
node.deleteData( offset, count);
fDeleteNode = null;
| public void | detach()
if( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
fDetach = true;
fDocument.removeRange(this);
| public org.w3c.dom.DocumentFragment | extractContents()
return traverseContents(EXTRACT_CONTENTS);
| public boolean | getCollapsed()
if ( fDetach ) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
return (fStartContainer == fEndContainer
&& fStartOffset == fEndOffset);
| public org.w3c.dom.Node | getCommonAncestorContainer()
if ( fDetach ) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
Vector startV = new Vector();
Node node;
for (node=fStartContainer; node != null;
node=node.getParentNode())
{
startV.addElement(node);
}
Vector endV = new Vector();
for (node=fEndContainer; node != null;
node=node.getParentNode())
{
endV.addElement(node);
}
int s = startV.size()-1;
int e = endV.size()-1;
Object result = null;
while (s>=0 && e>=0) {
if (startV.elementAt(s) == endV.elementAt(e)) {
result = startV.elementAt(s);
} else {
break;
}
--s;
--e;
}
return (Node)result;
| public org.w3c.dom.Node | getEndContainer()
if ( fDetach ) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
return fEndContainer;
| public int | getEndOffset()
if ( fDetach ) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
return fEndOffset;
| private org.w3c.dom.Node | getRootContainer(org.w3c.dom.Node node)Given a node, calculate what the Range's root container
for that node would be.
if ( node==null )
return null;
while( node.getParentNode()!=null )
node = node.getParentNode();
return node;
| private org.w3c.dom.Node | getSelectedNode(org.w3c.dom.Node container, int offset)Utility method to retrieve a child node by index. This method
assumes the caller is trying to find out which node is
selected by the given index. Note that if the index is
greater than the number of children, this implies that the
first node selected is the parent node itself.
if ( container.getNodeType() == Node.TEXT_NODE )
return container;
// This case is an important convenience for
// traverseRightBoundary()
if ( offset<0 )
return container;
Node child = container.getFirstChild();
while( child!=null && offset > 0 )
{
--offset;
child = child.getNextSibling();
}
if ( child!=null )
return child;
return container;
| public org.w3c.dom.Node | getStartContainer()
if ( fDetach ) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
return fStartContainer;
| public int | getStartOffset()
if ( fDetach ) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
return fStartOffset;
| private boolean | hasLegalRootContainer(org.w3c.dom.Node node)Finds the root container for the given node and determines
if that root container is legal with respect to the
DOM 2 specification. At present, that means the root
container must be either an attribute, a document,
or a document fragment.
if ( node==null )
return false;
Node rootContainer = getRootContainer( node );
switch( rootContainer.getNodeType() )
{
case Node.ATTRIBUTE_NODE:
case Node.DOCUMENT_NODE:
case Node.DOCUMENT_FRAGMENT_NODE:
return true;
}
return false;
| int | indexOf(org.w3c.dom.Node child, org.w3c.dom.Node parent)what is the index of the child in the parent
if (child.getParentNode() != parent) return -1;
int i = 0;
for(Node node = parent.getFirstChild(); node!= child; node=node.getNextSibling()) {
i++;
}
return i;
| void | insertData(org.w3c.dom.CharacterData node, int index, java.lang.String insert)This function inserts text into a Node and invokes
a method to fix-up all other Ranges.
fInsertNode = node;
node.insertData( index, insert);
fInsertNode = null;
| public void | insertNode(org.w3c.dom.Node newNode)
if ( newNode == null ) return; //throw exception?
int type = newNode.getNodeType();
if (fDocument.errorChecking) {
if (fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if ( fDocument != newNode.getOwnerDocument() ) {
throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
}
if (type == Node.ATTRIBUTE_NODE
|| type == Node.ENTITY_NODE
|| type == Node.NOTATION_NODE
|| type == Node.DOCUMENT_NODE)
{
throw new RangeExceptionImpl(
RangeException.INVALID_NODE_TYPE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
}
}
Node cloneCurrent;
Node current;
int currentChildren = 0;
fInsertedFromRange = true;
//boolean MULTIPLE_MODE = false;
if (fStartContainer.getNodeType() == Node.TEXT_NODE) {
Node parent = fStartContainer.getParentNode();
currentChildren = parent.getChildNodes().getLength(); //holds number of kids before insertion
// split text node: results is 3 nodes..
cloneCurrent = fStartContainer.cloneNode(false);
((TextImpl)cloneCurrent).setNodeValueInternal(
(cloneCurrent.getNodeValue()).substring(fStartOffset));
((TextImpl)fStartContainer).setNodeValueInternal(
(fStartContainer.getNodeValue()).substring(0,fStartOffset));
Node next = fStartContainer.getNextSibling();
if (next != null) {
if (parent != null) {
parent.insertBefore(newNode, next);
parent.insertBefore(cloneCurrent, next);
}
} else {
if (parent != null) {
parent.appendChild(newNode);
parent.appendChild(cloneCurrent);
}
}
//update ranges after the insertion
if ( fEndContainer == fStartContainer) {
fEndContainer = cloneCurrent; //endContainer is the new Node created
fEndOffset -= fStartOffset;
}
else if ( fEndContainer == parent ) { //endContainer was not a text Node.
//endOffset + = number_of_children_added
fEndOffset += (parent.getChildNodes().getLength() - currentChildren);
}
// signal other Ranges to update their start/end containers/offsets
signalSplitData(fStartContainer, cloneCurrent, fStartOffset);
} else { // ! TEXT_NODE
if ( fEndContainer == fStartContainer ) //need to remember number of kids
currentChildren= fEndContainer.getChildNodes().getLength();
current = fStartContainer.getFirstChild();
int i = 0;
for(i = 0; i < fStartOffset && current != null; i++) {
current=current.getNextSibling();
}
if (current != null) {
fStartContainer.insertBefore(newNode, current);
} else {
fStartContainer.appendChild(newNode);
}
//update fEndOffset. ex:<body><p/></body>. Range(start;end): body,0; body,1
// insert <h1>: <body></h1><p/></body>. Range(start;end): body,0; body,2
if ( fEndContainer == fStartContainer && fEndOffset != 0 ) { //update fEndOffset if not 0
fEndOffset += (fEndContainer.getChildNodes().getLength() - currentChildren);
}
}
fInsertedFromRange = false;
| public void | insertedNodeFromDOM(org.w3c.dom.Node node)This function is called from the DOM.
This node has already been inserted into the DOM.
Fix-up any offsets.
if (node == null) return;
if (fInsertNode == node) return;
if (fInsertedFromRange) return; // Offsets are adjusted in Range.insertNode
Node parent = node.getParentNode();
if (parent == fStartContainer) {
int index = indexOf(node, fStartContainer);
if (index < fStartOffset) {
fStartOffset++;
}
}
if (parent == fEndContainer) {
int index = indexOf(node, fEndContainer);
if (index < fEndOffset) {
fEndOffset++;
}
}
| boolean | isAncestorOf(org.w3c.dom.Node a, org.w3c.dom.Node b)is a an ancestor of b ?
for (Node node=b; node != null; node=node.getParentNode()) {
if (node == a) return true;
}
return false;
| private boolean | isLegalContainedNode(org.w3c.dom.Node node)Returns true IFF the given node can be contained by
a range.
if ( node==null )
return false;
switch( node.getNodeType() )
{
case Node.DOCUMENT_NODE:
case Node.DOCUMENT_FRAGMENT_NODE:
case Node.ATTRIBUTE_NODE:
case Node.ENTITY_NODE:
case Node.NOTATION_NODE:
return false;
}
return true;
| private boolean | isLegalContainer(org.w3c.dom.Node node)Returns true IFF the given node can serve as a container
for a range's boundary points.
if ( node==null )
return false;
while( node!=null )
{
switch( node.getNodeType() )
{
case Node.ENTITY_NODE:
case Node.NOTATION_NODE:
case Node.DOCUMENT_TYPE_NODE:
return false;
}
node = node.getParentNode();
}
return true;
| org.w3c.dom.Node | nextNode(org.w3c.dom.Node node, boolean visitChildren)
if (node == null) return null;
Node result;
if (visitChildren) {
result = node.getFirstChild();
if (result != null) {
return result;
}
}
// if hasSibling, return sibling
result = node.getNextSibling();
if (result != null) {
return result;
}
// return parent's 1st sibling.
Node parent = node.getParentNode();
while (parent != null
&& parent != fDocument
) {
result = parent.getNextSibling();
if (result != null) {
return result;
} else {
parent = parent.getParentNode();
}
} // while (parent != null && parent != fRoot) {
// end of list, return null
return null;
| void | receiveDeletedText(org.w3c.dom.Node node, int offset, int count)This function is called from DOM.
The text has already beeen inserted.
Fix-up any offsets.
if (node == null) return;
if (fDeleteNode == node) return;
if (node == fStartContainer
&& fStartContainer.getNodeType() == Node.TEXT_NODE) {
if (fStartOffset > offset+count) {
fStartOffset = offset+(fStartOffset-(offset+count));
} else
if (fStartOffset > offset) {
fStartOffset = offset;
}
}
if (node == fEndContainer
&& fEndContainer.getNodeType() == Node.TEXT_NODE) {
if (fEndOffset > offset+count) {
fEndOffset = offset+(fEndOffset-(offset+count));
} else
if (fEndOffset > offset) {
fEndOffset = offset;
}
}
| void | receiveInsertedText(org.w3c.dom.Node node, int index, int len)This function is called from DOM.
The text has already beeen inserted.
Fix-up any offsets.
if (node == null) return;
if (fInsertNode == node) return;
if (node == fStartContainer
&& fStartContainer.getNodeType() == Node.TEXT_NODE) {
if (index < fStartOffset) {
fStartOffset = fStartOffset+len;
}
}
if (node == fEndContainer
&& fEndContainer.getNodeType() == Node.TEXT_NODE) {
if (index < fEndOffset) {
fEndOffset = fEndOffset+len;
}
}
| void | receiveReplacedText(org.w3c.dom.Node node)This function is called from DOM.
The text has already beeen replaced.
Fix-up any offsets.
if (node == null) return;
if (node == fStartContainer
&& fStartContainer.getNodeType() == Node.TEXT_NODE) {
fStartOffset = 0;
}
if (node == fEndContainer
&& fEndContainer.getNodeType() == Node.TEXT_NODE) {
fEndOffset = 0;
}
| void | receiveSplitData(org.w3c.dom.Node node, org.w3c.dom.Node newNode, int offset)Fix up this Range if another Range has split a Text Node
into 2 Nodes.
if (node == null || newNode == null) return;
if (fSplitNode == node) return;
if (node == fStartContainer
&& fStartContainer.getNodeType() == Node.TEXT_NODE) {
if (fStartOffset > offset) {
fStartOffset = fStartOffset - offset;
fStartContainer = newNode;
}
}
if (node == fEndContainer
&& fEndContainer.getNodeType() == Node.TEXT_NODE) {
if (fEndOffset > offset) {
fEndOffset = fEndOffset-offset;
fEndContainer = newNode;
}
}
| org.w3c.dom.Node | removeChild(org.w3c.dom.Node parent, org.w3c.dom.Node child)
fRemoveChild = child;
Node n = parent.removeChild(child);
fRemoveChild = null;
return n;
| void | removeNode(org.w3c.dom.Node node)This function must be called by the DOM _BEFORE_
a node is deleted, because at that time it is
connected in the DOM tree, which we depend on.
if (node == null) return;
if (fRemoveChild == node) return;
Node parent = node.getParentNode();
if (parent == fStartContainer) {
int index = indexOf(node, fStartContainer);
if (index < fStartOffset) {
fStartOffset--;
}
}
if (parent == fEndContainer) {
int index = indexOf(node, fEndContainer);
if (index < fEndOffset) {
fEndOffset--;
}
}
//startContainer or endContainer or both is/are the ancestor(s) of the Node to be deleted
if (parent != fStartContainer
|| parent != fEndContainer) {
if (isAncestorOf(node, fStartContainer)) {
fStartContainer = parent;
fStartOffset = indexOf( node, parent);
}
if (isAncestorOf(node, fEndContainer)) {
fEndContainer = parent;
fEndOffset = indexOf( node, parent);
}
}
| public void | selectNode(org.w3c.dom.Node refNode)
if (fDocument.errorChecking) {
if (fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if ( !isLegalContainer( refNode.getParentNode() ) ||
!isLegalContainedNode( refNode ) ) {
throw new RangeExceptionImpl(
RangeException.INVALID_NODE_TYPE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
}
if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
throw new DOMException(
DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
}
}
Node parent = refNode.getParentNode();
if (parent != null ) // REVIST: what to do if it IS null?
{
fStartContainer = parent;
fEndContainer = parent;
int i = 0;
for (Node n = refNode; n!=null; n = n.getPreviousSibling()) {
i++;
}
fStartOffset = i-1;
fEndOffset = fStartOffset+1;
}
| public void | selectNodeContents(org.w3c.dom.Node refNode)
if (fDocument.errorChecking) {
if( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if ( !isLegalContainer(refNode)) {
throw new RangeExceptionImpl(
RangeException.INVALID_NODE_TYPE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
}
if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
throw new DOMException(
DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
}
}
fStartContainer = refNode;
fEndContainer = refNode;
Node first = refNode.getFirstChild();
fStartOffset = 0;
if (first == null) {
fEndOffset = 0;
} else {
int i = 0;
for (Node n = first; n!=null; n = n.getNextSibling()) {
i++;
}
fEndOffset = i;
}
| public void | setEnd(org.w3c.dom.Node refNode, int offset)
if (fDocument.errorChecking) {
if (fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if ( !isLegalContainer(refNode)) {
throw new RangeExceptionImpl(
RangeException.INVALID_NODE_TYPE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
}
if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
throw new DOMException(
DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
}
}
checkIndex(refNode, offset);
fEndContainer = refNode;
fEndOffset = offset;
// If one boundary-point of a Range is set to have a root container
// other
// than the current one for the Range, the Range should be collapsed to
// the new position.
// The start position of a Range should never be after the end position.
if (getCommonAncestorContainer() == null
|| (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
collapse(false);
}
| public void | setEndAfter(org.w3c.dom.Node refNode)
if (fDocument.errorChecking) {
if( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if ( !hasLegalRootContainer(refNode) ||
!isLegalContainedNode(refNode)) {
throw new RangeExceptionImpl(
RangeException.INVALID_NODE_TYPE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
}
if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
throw new DOMException(
DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
}
}
fEndContainer = refNode.getParentNode();
int i = 0;
for (Node n = refNode; n!=null; n = n.getPreviousSibling()) {
i++;
}
fEndOffset = i;
// If one boundary-point of a Range is set to have a root container
// other
// than the current one for the Range, the Range should be collapsed to
// the new position.
// The start position of a Range should never be after the end position.
if (getCommonAncestorContainer() == null
|| (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
collapse(false);
}
| public void | setEndBefore(org.w3c.dom.Node refNode)
if (fDocument.errorChecking) {
if (fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if ( !hasLegalRootContainer(refNode) ||
!isLegalContainedNode(refNode)) {
throw new RangeExceptionImpl(
RangeException.INVALID_NODE_TYPE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
}
if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
throw new DOMException(
DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
}
}
fEndContainer = refNode.getParentNode();
int i = 0;
for (Node n = refNode; n!=null; n = n.getPreviousSibling()) {
i++;
}
fEndOffset = i-1;
// If one boundary-point of a Range is set to have a root container
// other
// than the current one for the Range, the Range should be collapsed to
// the new position.
// The start position of a Range should never be after the end position.
if (getCommonAncestorContainer() == null
|| (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
collapse(false);
}
| public void | setStart(org.w3c.dom.Node refNode, int offset)
if (fDocument.errorChecking) {
if ( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if ( !isLegalContainer(refNode)) {
throw new RangeExceptionImpl(
RangeException.INVALID_NODE_TYPE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
}
if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
throw new DOMException(
DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
}
}
checkIndex(refNode, offset);
fStartContainer = refNode;
fStartOffset = offset;
// If one boundary-point of a Range is set to have a root container
// other
// than the current one for the Range, the Range should be collapsed to
// the new position.
// The start position of a Range should never be after the end position.
if (getCommonAncestorContainer() == null
|| (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
collapse(true);
}
| public void | setStartAfter(org.w3c.dom.Node refNode)
if (fDocument.errorChecking) {
if (fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if ( !hasLegalRootContainer(refNode) ||
!isLegalContainedNode(refNode)) {
throw new RangeExceptionImpl(
RangeException.INVALID_NODE_TYPE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
}
if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
throw new DOMException(
DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
}
}
fStartContainer = refNode.getParentNode();
int i = 0;
for (Node n = refNode; n!=null; n = n.getPreviousSibling()) {
i++;
}
fStartOffset = i;
// If one boundary-point of a Range is set to have a root container
// other
// than the current one for the Range, the Range should be collapsed to
// the new position.
// The start position of a Range should never be after the end position.
if (getCommonAncestorContainer() == null
|| (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
collapse(true);
}
| public void | setStartBefore(org.w3c.dom.Node refNode)
if (fDocument.errorChecking) {
if (fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if ( !hasLegalRootContainer(refNode) ||
!isLegalContainedNode(refNode) )
{
throw new RangeExceptionImpl(
RangeException.INVALID_NODE_TYPE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
}
if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) {
throw new DOMException(
DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null));
}
}
fStartContainer = refNode.getParentNode();
int i = 0;
for (Node n = refNode; n!=null; n = n.getPreviousSibling()) {
i++;
}
fStartOffset = i-1;
// If one boundary-point of a Range is set to have a root container
// other
// than the current one for the Range, the Range should be collapsed to
// the new position.
// The start position of a Range should never be after the end position.
if (getCommonAncestorContainer() == null
|| (fStartContainer == fEndContainer && fEndOffset < fStartOffset)) {
collapse(true);
}
| void | signalSplitData(org.w3c.dom.Node node, org.w3c.dom.Node newNode, int offset)Signal other Ranges to update their start/end
containers/offsets. The data has already been split
into the two Nodes.
fSplitNode = node;
// notify document
fDocument.splitData(node, newNode, offset);
fSplitNode = null;
| public void | surroundContents(org.w3c.dom.Node newParent)
if (newParent==null) return;
int type = newParent.getNodeType();
if (fDocument.errorChecking) {
if (fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
if (type == Node.ATTRIBUTE_NODE
|| type == Node.ENTITY_NODE
|| type == Node.NOTATION_NODE
|| type == Node.DOCUMENT_TYPE_NODE
|| type == Node.DOCUMENT_NODE
|| type == Node.DOCUMENT_FRAGMENT_NODE)
{
throw new RangeExceptionImpl(
RangeException.INVALID_NODE_TYPE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null));
}
}
Node realStart = fStartContainer;
Node realEnd = fEndContainer;
if (fStartContainer.getNodeType() == Node.TEXT_NODE) {
realStart = fStartContainer.getParentNode();
}
if (fEndContainer.getNodeType() == Node.TEXT_NODE) {
realEnd = fEndContainer.getParentNode();
}
if (realStart != realEnd) {
throw new RangeExceptionImpl(
RangeException.BAD_BOUNDARYPOINTS_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "BAD_BOUNDARYPOINTS_ERR", null));
}
DocumentFragment frag = extractContents();
insertNode(newParent);
newParent.appendChild(frag);
selectNode(newParent);
| public java.lang.String | toString()
if( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
Node node = fStartContainer;
Node stopNode = fEndContainer;
StringBuffer sb = new StringBuffer();
if (fStartContainer.getNodeType() == Node.TEXT_NODE
|| fStartContainer.getNodeType() == Node.CDATA_SECTION_NODE
) {
if (fStartContainer == fEndContainer) {
sb.append(fStartContainer.getNodeValue().substring(fStartOffset, fEndOffset));
return sb.toString();
}
sb.append(fStartContainer.getNodeValue().substring(fStartOffset));
node=nextNode (node,true); //fEndContainer!=fStartContainer
}
else { //fStartContainer is not a TextNode
node=node.getFirstChild();
if (fStartOffset>0) { //find a first node within a range, specified by fStartOffset
int counter=0;
while (counter<fStartOffset && node!=null) {
node=node.getNextSibling();
counter++;
}
}
if (node == null) {
node = nextNode(fStartContainer,false);
}
}
if ( fEndContainer.getNodeType()!= Node.TEXT_NODE &&
fEndContainer.getNodeType()!= Node.CDATA_SECTION_NODE ){
int i=fEndOffset;
stopNode = fEndContainer.getFirstChild();
while( i>0 && stopNode!=null ){
--i;
stopNode = stopNode.getNextSibling();
}
if ( stopNode == null )
stopNode = nextNode( fEndContainer, false );
}
while (node != stopNode) { //look into all kids of the Range
if (node == null) break;
if (node.getNodeType() == Node.TEXT_NODE
|| node.getNodeType() == Node.CDATA_SECTION_NODE) {
sb.append(node.getNodeValue());
}
node = nextNode(node, true);
}
if (fEndContainer.getNodeType() == Node.TEXT_NODE
|| fEndContainer.getNodeType() == Node.CDATA_SECTION_NODE) {
sb.append(fEndContainer.getNodeValue().substring(0,fEndOffset));
}
return sb.toString();
| private org.w3c.dom.DocumentFragment | traverseCommonAncestors(org.w3c.dom.Node startAncestor, org.w3c.dom.Node endAncestor, int how)Visits the nodes selected by this range when we know
a-priori that the start and end containers are not
the same, and we also know that neither the start
nor end container is an ancestor of the other.
This method is invoked by
the generic traverse method.
DocumentFragment frag = null;
if ( how!=DELETE_CONTENTS)
frag = fDocument.createDocumentFragment();
Node n = traverseLeftBoundary( startAncestor, how );
if ( frag!=null )
frag.appendChild( n );
Node commonParent = startAncestor.getParentNode();
int startOffset = indexOf( startAncestor, commonParent );
int endOffset = indexOf( endAncestor, commonParent );
++startOffset;
int cnt = endOffset - startOffset;
Node sibling = startAncestor.getNextSibling();
while( cnt > 0 )
{
Node nextSibling = sibling.getNextSibling();
n = traverseFullySelected( sibling, how );
if ( frag!=null )
frag.appendChild( n );
sibling = nextSibling;
--cnt;
}
n = traverseRightBoundary( endAncestor, how );
if ( frag!=null )
frag.appendChild( n );
if ( how != CLONE_CONTENTS )
{
setStartAfter( startAncestor );
collapse( true );
}
return frag;
| private org.w3c.dom.DocumentFragment | traverseCommonEndContainer(org.w3c.dom.Node startAncestor, int how)Visits the nodes selected by this range when we know
a-priori that the start and end containers are not the
same, but the end container is an ancestor of the
start container. This method is invoked by the generic
traverse method.
DocumentFragment frag = null;
if ( how!=DELETE_CONTENTS)
frag = fDocument.createDocumentFragment();
Node n = traverseLeftBoundary( startAncestor, how );
if ( frag!=null )
frag.appendChild( n );
int startIdx = indexOf( startAncestor, fEndContainer );
++startIdx; // Because we already traversed it....
int cnt = fEndOffset - startIdx;
n = startAncestor.getNextSibling();
while( cnt > 0 )
{
Node sibling = n.getNextSibling();
Node xferNode = traverseFullySelected( n, how );
if ( frag!=null )
frag.appendChild( xferNode );
--cnt;
n = sibling;
}
if ( how != CLONE_CONTENTS )
{
setStartAfter( startAncestor );
collapse( true );
}
return frag;
| private org.w3c.dom.DocumentFragment | traverseCommonStartContainer(org.w3c.dom.Node endAncestor, int how)Visits the nodes selected by this range when we know
a-priori that the start and end containers are not the
same, but the start container is an ancestor of the
end container. This method is invoked by the generic
traverse method.
DocumentFragment frag = null;
if ( how!=DELETE_CONTENTS)
frag = fDocument.createDocumentFragment();
Node n = traverseRightBoundary( endAncestor, how );
if ( frag!=null )
frag.appendChild( n );
int endIdx = indexOf( endAncestor, fStartContainer );
int cnt = endIdx - fStartOffset;
if ( cnt <=0 )
{
// Collapse to just before the endAncestor, which
// is partially selected.
if ( how != CLONE_CONTENTS )
{
setEndBefore( endAncestor );
collapse( false );
}
return frag;
}
n = endAncestor.getPreviousSibling();
while( cnt > 0 )
{
Node sibling = n.getPreviousSibling();
Node xferNode = traverseFullySelected( n, how );
if ( frag!=null )
frag.insertBefore( xferNode, frag.getFirstChild() );
--cnt;
n = sibling;
}
// Collapse to just before the endAncestor, which
// is partially selected.
if ( how != CLONE_CONTENTS )
{
setEndBefore( endAncestor );
collapse( false );
}
return frag;
| private org.w3c.dom.DocumentFragment | traverseContents(int how)This is the master routine invoked to visit the nodes
selected by this range. For each such node, different
actions are taken depending on the value of the
how argument.
if (fStartContainer == null || fEndContainer == null) {
return null; // REVIST: Throw exception?
}
//Check for a detached range.
if( fDetach) {
throw new DOMException(
DOMException.INVALID_STATE_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null));
}
/*
Traversal is accomplished by first determining the
relationship between the endpoints of the range.
For each of four significant relationships, we will
delegate the traversal call to a method that
can make appropriate assumptions.
*/
// case 1: same container
if ( fStartContainer == fEndContainer )
return traverseSameContainer( how );
// case 2: Child C of start container is ancestor of end container
// This can be quickly tested by walking the parent chain of
// end container
int endContainerDepth = 0;
for ( Node c = fEndContainer, p = c.getParentNode();
p != null;
c = p, p = p.getParentNode())
{
if (p == fStartContainer)
return traverseCommonStartContainer( c, how );
++endContainerDepth;
}
// case 3: Child C of container B is ancestor of A
// This can be quickly tested by walking the parent chain of A
int startContainerDepth = 0;
for ( Node c = fStartContainer, p = c.getParentNode();
p != null;
c = p, p = p.getParentNode())
{
if (p == fEndContainer)
return traverseCommonEndContainer( c, how );
++startContainerDepth;
}
// case 4: There is a common ancestor container. Find the
// ancestor siblings that are children of that container.
int depthDiff = startContainerDepth - endContainerDepth;
Node startNode = fStartContainer;
while (depthDiff > 0) {
startNode = startNode.getParentNode();
depthDiff--;
}
Node endNode = fEndContainer;
while (depthDiff < 0) {
endNode = endNode.getParentNode();
depthDiff++;
}
// ascend the ancestor hierarchy until we have a common parent.
for( Node sp = startNode.getParentNode(), ep = endNode.getParentNode();
sp!=ep;
sp = sp.getParentNode(), ep = ep.getParentNode() )
{
startNode = sp;
endNode = ep;
}
return traverseCommonAncestors( startNode, endNode, how );
| private org.w3c.dom.Node | traverseFullySelected(org.w3c.dom.Node n, int how)Utility method for traversing a single node when
we know a-priori that the node if fully
selected.
switch( how )
{
case CLONE_CONTENTS:
return n.cloneNode( true );
case EXTRACT_CONTENTS:
if ( n.getNodeType()==Node.DOCUMENT_TYPE_NODE )
{
// TBD: This should be a HIERARCHY_REQUEST_ERR
throw new DOMException(
DOMException.HIERARCHY_REQUEST_ERR,
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));
}
return n;
case DELETE_CONTENTS:
n.getParentNode().removeChild(n);
return null;
}
return null;
| private org.w3c.dom.Node | traverseLeftBoundary(org.w3c.dom.Node root, int how)Traverses the "left boundary" of this range and
operates on each "boundary node" according to the
how parameter. It is a-priori assumed
by this method that the left boundary does
not contain the range's end container.
A "left boundary" is best visualized by thinking
of a sample tree:
A
/|\
/ | \
/ | \
B C D
/|\ /|\
E F G H I J
Imagine first a range that begins between the
"E" and "F" nodes and ends between the
"I" and "J" nodes. The start container is
"B" and the end container is "D". Given this setup,
the following applies:
Partially Selected Nodes: B, D
Fully Selected Nodes: F, G, C, H, I
The "left boundary" is the highest subtree node
that contains the starting container. The root of
this subtree is always partially selected.
In this example, the nodes that are traversed
as "left boundary" nodes are: F, G, and B.
Node next = getSelectedNode( getStartContainer(), getStartOffset() );
boolean isFullySelected = ( next!=getStartContainer() );
if ( next==root )
return traverseNode( next, isFullySelected, true, how );
Node parent = next.getParentNode();
Node clonedParent = traverseNode( parent, false, true, how );
while( parent!=null )
{
while( next!=null )
{
Node nextSibling = next.getNextSibling();
Node clonedChild =
traverseNode( next, isFullySelected, true, how );
if ( how!=DELETE_CONTENTS )
clonedParent.appendChild(clonedChild);
isFullySelected = true;
next = nextSibling;
}
if ( parent==root )
return clonedParent;
next = parent.getNextSibling();
parent = parent.getParentNode();
Node clonedGrandParent = traverseNode( parent, false, true, how );
if ( how!=DELETE_CONTENTS )
clonedGrandParent.appendChild( clonedParent );
clonedParent = clonedGrandParent;
}
// should never occur
return null;
| private org.w3c.dom.Node | traverseNode(org.w3c.dom.Node n, boolean isFullySelected, boolean isLeft, int how)Utility method for traversing a single node.
Does not properly handle a text node containing both the
start and end offsets. Such nodes should
have been previously detected and been routed to traverseTextNode.
if ( isFullySelected )
return traverseFullySelected( n, how );
if ( n.getNodeType()==Node.TEXT_NODE )
return traverseTextNode( n, isLeft, how );
return traversePartiallySelected( n, how );
| private org.w3c.dom.Node | traversePartiallySelected(org.w3c.dom.Node n, int how)Utility method for traversing a single node when
we know a-priori that the node if partially
selected and is not a text node.
switch( how )
{
case DELETE_CONTENTS:
return null;
case CLONE_CONTENTS:
case EXTRACT_CONTENTS:
return n.cloneNode( false );
}
return null;
| private org.w3c.dom.Node | traverseRightBoundary(org.w3c.dom.Node root, int how)Traverses the "right boundary" of this range and
operates on each "boundary node" according to the
how parameter. It is a-priori assumed
by this method that the right boundary does
not contain the range's start container.
A "right boundary" is best visualized by thinking
of a sample tree:
A
/|\
/ | \
/ | \
B C D
/|\ /|\
E F G H I J
Imagine first a range that begins between the
"E" and "F" nodes and ends between the
"I" and "J" nodes. The start container is
"B" and the end container is "D". Given this setup,
the following applies:
Partially Selected Nodes: B, D
Fully Selected Nodes: F, G, C, H, I
The "right boundary" is the highest subtree node
that contains the ending container. The root of
this subtree is always partially selected.
In this example, the nodes that are traversed
as "right boundary" nodes are: H, I, and D.
Node next = getSelectedNode( fEndContainer, fEndOffset-1 );
boolean isFullySelected = ( next!=fEndContainer );
if ( next==root )
return traverseNode( next, isFullySelected, false, how );
Node parent = next.getParentNode();
Node clonedParent = traverseNode( parent, false, false, how );
while( parent!=null )
{
while( next!=null )
{
Node prevSibling = next.getPreviousSibling();
Node clonedChild =
traverseNode( next, isFullySelected, false, how );
if ( how!=DELETE_CONTENTS )
{
clonedParent.insertBefore(
clonedChild,
clonedParent.getFirstChild()
);
}
isFullySelected = true;
next = prevSibling;
}
if ( parent==root )
return clonedParent;
next = parent.getPreviousSibling();
parent = parent.getParentNode();
Node clonedGrandParent = traverseNode( parent, false, false, how );
if ( how!=DELETE_CONTENTS )
clonedGrandParent.appendChild( clonedParent );
clonedParent = clonedGrandParent;
}
// should never occur
return null;
| private org.w3c.dom.DocumentFragment | traverseSameContainer(int how)Visits the nodes selected by this range when we know
a-priori that the start and end containers are the same.
This method is invoked by the generic traverse
method.
DocumentFragment frag = null;
if ( how!=DELETE_CONTENTS)
frag = fDocument.createDocumentFragment();
// If selection is empty, just return the fragment
if ( fStartOffset==fEndOffset )
return frag;
// Text node needs special case handling
if ( fStartContainer.getNodeType()==Node.TEXT_NODE )
{
// get the substring
String s = fStartContainer.getNodeValue();
String sub = s.substring( fStartOffset, fEndOffset );
// set the original text node to its new value
if ( how != CLONE_CONTENTS )
{
((TextImpl)fStartContainer).deleteData(fStartOffset,
fEndOffset-fStartOffset) ;
// Nothing is partially selected, so collapse to start point
collapse( true );
}
if ( how==DELETE_CONTENTS)
return null;
frag.appendChild( fDocument.createTextNode(sub) );
return frag;
}
// Copy nodes between the start/end offsets.
Node n = getSelectedNode( fStartContainer, fStartOffset );
int cnt = fEndOffset - fStartOffset;
while( cnt > 0 )
{
Node sibling = n.getNextSibling();
Node xferNode = traverseFullySelected( n, how );
if ( frag!=null )
frag.appendChild( xferNode );
--cnt;
n = sibling;
}
// Nothing is partially selected, so collapse to start point
if ( how != CLONE_CONTENTS )
collapse( true );
return frag;
| private org.w3c.dom.Node | traverseTextNode(org.w3c.dom.Node n, boolean isLeft, int how)Utility method for traversing a text node that we know
a-priori to be on a left or right boundary of the range.
This method does not properly handle text nodes that contain
both the start and end points of the range.
String txtValue = n.getNodeValue();
String newNodeValue;
String oldNodeValue;
if ( isLeft )
{
int offset = getStartOffset();
newNodeValue = txtValue.substring( offset );
oldNodeValue = txtValue.substring( 0, offset );
}
else
{
int offset = getEndOffset();
newNodeValue = txtValue.substring( 0, offset );
oldNodeValue = txtValue.substring( offset );
}
if ( how != CLONE_CONTENTS )
n.setNodeValue( oldNodeValue );
if ( how==DELETE_CONTENTS )
return null;
Node newNode = n.cloneNode( false );
newNode.setNodeValue( newNodeValue );
return newNode;
|
|