rangeimpl.java

来自「JAVA 所有包」· Java 代码 · 共 1,729 行 · 第 1/5 页

JAVA
1,729
字号
        {            setStartAfter( startAncestor );            collapse( true );        }        return frag;    }    /**     * 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 <code>traverse</code> method.     *      * @param startAncestor     *               Given a common ancestor of the start and end containers,     *               this parameter is the ancestor (or self) of the start     *               container that is a direct child of the common ancestor.     *      * @param endAncestor     *               Given a common ancestor of the start and end containers,     *               this parameter is the ancestor (or self) of the end     *               container that is a direct child of the common ancestor.     *      * @param how    Specifies what type of traversal is being     *               requested (extract, clone, or delete).     *               Legal values for this argument are:     *                    *               <ol>     *               <li><code>EXTRACT_CONTENTS</code> - will produce     *               a document fragment containing the range's content.     *               Partially selected nodes are copied, but fully     *               selected nodes are moved.     *                    *               <li><code>CLONE_CONTENTS</code> - will leave the     *               context tree of the range undisturbed, but sill     *               produced cloned content in a document fragment     *                    *               <li><code>DELETE_CONTENTS</code> - will delete from     *               the context tree of the range, all fully selected     *               nodes.     *               </ol>     *      * @return Returns a document fragment containing any     *         copied or extracted nodes.  If the <code>how</code>     *         parameter was <code>DELETE_CONTENTS</code>, the     *         return value is null.     */    private DocumentFragment         traverseCommonAncestors( Node startAncestor, Node endAncestor, int how )    {        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;    }    /**     * Traverses the "right boundary" of this range and     * operates on each "boundary node" according to the     * <code>how</code> parameter.  It is a-priori assumed     * by this method that the right boundary does     * not contain the range's start container.     * <p>     * A "right boundary" is best visualized by thinking     * of a sample tree:<pre>     *                 A     *                /|\     *               / | \     *              /  |  \     *             B   C   D     *            /|\     /|\     *           E F G   H I J     * </pre>     * 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:     * <p>     * Partially Selected Nodes: B, D<br>     * Fully Selected Nodes: F, G, C, H, I     * <p>     * The "right boundary" is the highest subtree node     * that contains the ending container.  The root of     * this subtree is always partially selected.     * <p>     * In this example, the nodes that are traversed     * as "right boundary" nodes are: H, I, and D.     *      * @param root   The node that is the root of the "right boundary" subtree.     *      * @param how    Specifies what type of traversal is being     *               requested (extract, clone, or delete).     *               Legal values for this argument are:     *                    *               <ol>     *               <li><code>EXTRACT_CONTENTS</code> - will produce     *               a node containing the boundaries content.     *               Partially selected nodes are copied, but fully     *               selected nodes are moved.     *                    *               <li><code>CLONE_CONTENTS</code> - will leave the     *               context tree of the range undisturbed, but will     *               produced cloned content.     *                    *               <li><code>DELETE_CONTENTS</code> - will delete from     *               the context tree of the range, all fully selected     *               nodes within the boundary.     *               </ol>     *      * @return Returns a node that is the result of visiting nodes.     *         If the traversal operation is     *         <code>DELETE_CONTENTS</code> the return value is null.     */    private Node traverseRightBoundary( Node root, int how )    {        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;    }    /**     * Traverses the "left boundary" of this range and     * operates on each "boundary node" according to the     * <code>how</code> parameter.  It is a-priori assumed     * by this method that the left boundary does     * not contain the range's end container.     * <p>     * A "left boundary" is best visualized by thinking     * of a sample tree:<pre>     *      *                 A     *                /|\     *               / | \     *              /  |  \     *             B   C   D     *            /|\     /|\     *           E F G   H I J     * </pre>     * 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:     * <p>     * Partially Selected Nodes: B, D<br>     * Fully Selected Nodes: F, G, C, H, I     * <p>     * The "left boundary" is the highest subtree node     * that contains the starting container.  The root of     * this subtree is always partially selected.     * <p>     * In this example, the nodes that are traversed     * as "left boundary" nodes are: F, G, and B.     *      * @param root   The node that is the root of the "left boundary" subtree.     *      * @param how    Specifies what type of traversal is being     *               requested (extract, clone, or delete).     *               Legal values for this argument are:     *                    *               <ol>     *               <li><code>EXTRACT_CONTENTS</code> - will produce     *               a node containing the boundaries content.     *               Partially selected nodes are copied, but fully     *               selected nodes are moved.     *                    *               <li><code>CLONE_CONTENTS</code> - will leave the     *               context tree of the range undisturbed, but will     *               produced cloned content.     *                    *               <li><code>DELETE_CONTENTS</code> - will delete from     *               the context tree of the range, all fully selected     *               nodes within the boundary.     *               </ol>     *      * @return Returns a node that is the result of visiting nodes.     *         If the traversal operation is     *         <code>DELETE_CONTENTS</code> the return value is null.     */    private Node traverseLeftBoundary( Node root, int how )    {        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;    }    /**     * 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.     *      * @param n      The node to be traversed.     *      * @param isFullySelected     *               Set to true if the node is fully selected.  Should be      *               false otherwise.     *               Note that although the DOM 2 specification says that a      *               text node that is boththe start and end container is not     *               selected, we treat it here as if it were partially      *               selected.     *      * @param isLeft Is true if we are traversing the node as part of navigating     *               the "left boundary" of the range.  If this value is false,     *               it implies we are navigating the "right boundary" of the     *               range.     *      * @param how    Specifies what type of traversal is being     *               requested (extract, clone, or delete).     *               Legal values for this argument are:     *                    *               <ol>     *               <li><code>EXTRACT_CONTENTS</code> - will simply     *               return the original node.     *                    *               <li><code>CLONE_CONTENTS</code> - will leave the     *               context tree of the range undisturbed, but will     *               return a cloned node.     *                    *               <li><code>DELETE_CONTENTS</code> - will delete the     *               node from it's parent, but will return null.     *               </ol>     *      * @return Returns a node that is the result of visiting the node.     *         If the traversal operation is     *         <code>DELETE_CONTENTS</code> the return value is null.     */    private Node traverseNode( Node n, boolean isFullySelected, boolean isLeft, int how )    {        if ( isFullySelected )            return traverseFullySelected( n, how );        if ( n.getNodeType()==Node.TEXT_NODE )            return traverseTextNode( n, isLeft, how );        return traversePartiallySelected( n, how );    }    /**     * Utility method for traversing a single node when     * we know a-priori

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?