Пример #1
0
 ParagraphsToMerge(Location previous, List <List <IDomNode> > selected, OffsetInElement start, OffsetInElement end)
 {
     m_previous = previous;
     m_selected = selected;
     m_start    = start;
     m_end      = end;
 }
Пример #2
0
        static ParagraphsToMerge create(IDomRange domRange)
        {
            //find the block-level element associated with the start of the range
            IDomNode startBlock = findBlock(domRange.startContainer, domRange.startOffset, true);
            //find the block-level element associated with the end of the range
            IDomNode endBlock = findBlock(domRange.endContainer, domRange.endOffset, false);

            //block may be null if it's positioned directly under a <td>
            //which (removing things from a table) isn't a scenario supported by this class
            if ((startBlock == null) || (endBlock == null))
            {
                return(null);
            }

            //iterate the inline-level elements to be moved
            List <List <IDomNode> > selected = new List <List <IDomNode> >();

            IDomNode currentBlock = startBlock;

            for (; ;)
            {
                //get the inline elements inside this block
                List <IDomNode> children     = null;
                bool            childIsBlock = false;
                foreach (IDomNode child in currentBlock.childNodes.elements)
                {
                    if (!isBlock(child))
                    {
                        //found an inline child
                        if (children == null)
                        {
                            children = new List <IDomNode>();
                        }
                        children.Add(child);
                    }
                    else
                    {
                        //child of this block is itself a block
                        currentBlock = child;
                        childIsBlock = true;
                        break;
                    }
                }
                if (children != null)
                {
                    //found some inline children
                    selected.Add(children);
                }
                if (childIsBlock)
                {
                    //descend: iterate this child block
                    continue;
                }
                //else finished iterating children of currentBlock

                if (ReferenceEquals(currentBlock, endBlock))
                {
                    //currentBlock is the last block we wanted to iterate
                    break;
                }

                //find the next block to iterate
                for (; ;)
                {
                    IDomNode currentParent = currentBlock.parentNode;
                    int      currentIndex  = currentParent.childNodes.indexOf(currentBlock);
                    if (currentIndex < (currentParent.childNodes.count - 1))
                    {
                        //next we'll iterate the next sibling after currentBlock
                        currentBlock = currentParent.childNodes.itemAt(currentIndex + 1);
                        break;
                    }
                    else
                    {
                        //no next sibling after currentBlock
                        //so iterate next sibling after parent block
                        currentBlock = currentParent;
                        continue;
                    }
                }

                if (!isBlock(currentBlock))
                {
                    //this can happen if an 'anonymous block' is not the first block of a parent block
                    //which isn't supported by the current version of the renderer
                    throw new ApplicationException("unexpected");
                }
            }

            //find the block before the selected block
            //into which we'll merge the inline elements
            currentBlock = startBlock;
            Location previous;

            for (; ;)
            {
                //find the block before the first block
                IDomNode parent = currentBlock.parentNode;
                int      index  = parent.childNodes.indexOf(currentBlock);
                if (index > 0)
                {
                    //found a previous element
                    IDomNode previousNode = parent.childNodes.itemAt(index - 1);
                    if (isBlock(previousNode))
                    {
                        //previous element is a block
                        //but it might have block-level descendents
                        while ((previousNode.childNodes.count > 0) && isBlock(previousNode.childNodes.itemAt(previousNode.childNodes.count - 1)))
                        {
                            previousNode = previousNode.childNodes.itemAt(previousNode.childNodes.count - 1);
                        }
                        //want to insert at the end (after the last child) of the previousNode
                        previous = new Location(previousNode, null);
                        break;
                    }
                    else
                    {
                        //previous is not a block,
                        //so it's an anonymous block
                        //near the start of a list item or table cell
                        previous = new Location(parent, previousNode);
                        break;
                    }
                }
                if (parent.nodeName == "body")
                {
                    //startBlock is the first block in the body
                    //there is no previous block
                    //so don't merge
                    return(null);
                }
                currentBlock = parent;
                continue;
            }

            //search up to find the <body> element
            IDomNode body = startBlock;

            while (body.nodeName != "body")
            {
                body = body.parentNode;
            }

            //remember whether the selection range starts and ends
            //in order to restore it after we edit the DOM
            OffsetInElement start = new OffsetInElement(body, domRange.startContainer, domRange.startOffset);
            OffsetInElement end   = new OffsetInElement(body, domRange.endContainer, domRange.endOffset);

            return(new ParagraphsToMerge(previous, selected, start, end));
        }