Beispiel #1
0
    def insertNode(self, newNode):
        """Insert a node at the starting point"""

        if self.detached:
            raise InvalidStateErr()

        if newNode.nodeType in [
                Node.ATTRIBUTE_NODE,
                Node.ENTITY_NODE,
                Node.NOTATION_NODE,
                Node.DOCUMENT_NODE,
        ]:
            raise InvalidNodeTypeErr()

        if self.startContainer.nodeType == Node.TEXT_NODE:
            #Split the text at the boundary.  Insert the node after this
            otherText = self.startContainer.substringData(
                self.startOffset, len(self.startContainer.data))
            self.startContainer.deleteData(self.startOffset,
                                           len(self.startContainer.data))
            newText = self._ownerDocument.createTextNode(otherText)
            self.startContainer.parentNode.insertBefore(
                newText, self.startContainer.nextSibling)

            newText.parentNode.insertBefore(newNode, newText)
        elif self.startContainer.nodeType in [
                Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE
        ]:
            raise HierarchyRequestErr()
        else:
            curNode = self.startContainer.childNodes[self.startOffset]
            self.startContainer.insertBefore(newNode, curNode.nextSibling)
Beispiel #2
0
    def cloneRange(self):
        if self.detached:
            raise InvalidStateErr()

        newRange = Range(self._ownerDocument)
        newRange.setStart(self.startContainer, self.startOffset)
        newRange.setEnd(self.endContainer, self.endOffset)
        return newRange
Beispiel #3
0
 def previousNode(self):
     if self._detached:
         raise InvalidStateErr()
     prev_node = self._regress()
     while (prev_node and not (
         self._checkWhatToShow(prev_node) and
         self._checkFilter(prev_node) == NodeFilter.FILTER_ACCEPT)):
         prev_node = self._regress()
     return prev_node
Beispiel #4
0
 def nextNode(self):
     if self._detached:
         raise InvalidStateErr()
     next_node = self._advance()
     while (next_node and not (
         self._checkWhatToShow(next_node) and
         self._checkFilter(next_node) == NodeFilter.FILTER_ACCEPT)):
         next_node = self._advance()
     return next_node
Beispiel #5
0
    def toString(self):
        if self.detached:
            raise InvalidStateErr()

        df = self.cloneContents()

        res = self.__recurseToString(df)

        from pyxml.dom.ext import ReleaseNode
        ReleaseNode(df)

        return res
Beispiel #6
0
    def collapse(self, toStart):
        """Collapse the range"""
        if self.detached:
            raise InvalidStateErr()

        if toStart:
            self.__dict__['endContainer'] = self.startContainer
            self.__dict__['endOffset'] = self.startOffset
        else:
            self.__dict__['startContainer'] = self.endContainer
            self.__dict__['startOffset'] = self.endOffset

        self.__dict__['collapsed'] = 1
        self.__dict__['commonAncestorContainer'] = self.startContainer
Beispiel #7
0
    def selectNodeContents(self, refNode):
        """Select a node"""
        if self.detached:
            raise InvalidStateErr()

        self.__validateBoundary(refNode, 0)

        self.__dict__['startContainer'] = refNode
        self.__dict__['endContainer'] = refNode

        self.__dict__['startOffset'] = 0
        self.__dict__['endOffset'] = len(refNode.childNodes)

        self.__dict__['collapsed'] = self.startOffset == self.endOffset
        self.__dict__['commonAncestorContainer'] = refNode
Beispiel #8
0
    def selectNode(self, refNode):
        """Select a node"""
        if self.detached:
            raise InvalidStateErr()

        self.__validateRefNode(refNode)

        self.__dict__['startContainer'] = refNode.parentNode
        self.__dict__['endContainer'] = refNode.parentNode

        index = refNode.parentNode.childNodes.index(refNode)
        self.__dict__['startOffset'] = index
        self.__dict__['endOffset'] = index + 1

        self.__dict__['collapsed'] = 0
        self.__dict__['commonAncestorContainer'] = refNode.parentNode
Beispiel #9
0
    def surroundContents(self, newParent):
        """Surround the range with this node"""
        if self.detached:
            raise InvalidStateErr()

        if newParent.nodeType in [
                Node.ATTRIBUTE_NODE, Node.ENTITY_NODE, Node.DOCUMENT_TYPE_NODE,
                Node.NOTATION_NODE, Node.DOCUMENT_NODE,
                Node.DOCUMENT_FRAGMENT_NODE
        ]:
            raise InvalidNodeTypeErr()

        #See is we have element nodes that are partially selected
        if self.startContainer.nodeType not in [
                Node.TEXT_NODE, Node.COMMENT_NODE,
                Node.PROCESSING_INSTRUCTION_NODE
        ]:
            if self.commonAncestorContainer not in [
                    self.startContainer, self.startContainer.parentNode
            ]:
                #This is partially selected because our parent is not the common ancestor
                raise BadBoundaryPointsErr()
        if self.endContainer.nodeType not in [
                Node.TEXT_NODE, Node.COMMENT_NODE,
                Node.PROCESSING_INSTRUCTION_NODE
        ]:
            if self.commonAncestorContainer not in [
                    self.endContainer, self.endContainer.parentNode
            ]:
                #This is partially selected because our parent is not the common ancestor
                raise BadBoundaryPointsErr()

        #All good, do the insert
        #Remove children from newPArent
        for c in newParent.childNodes:
            newParent.removeChild(c)

        df = self.extractContents()

        self.insertNode(newParent)

        newParent.appendChild(df)

        self.selectNode(newParent)
Beispiel #10
0
    def setStart(self, parent, offset):
        """Set the ranges start container and offset"""

        #Check for errors
        if self.detached:
            raise InvalidStateErr()

        self.__validateBoundary(parent, offset)

        self.__dict__['startContainer'] = parent
        self.__dict__['startOffset'] = offset

        pos = self.__comparePositions(parent, offset, self.endContainer,
                                      self.endOffset)
        self.__dict__['collapsed'] = (pos == self.POSITION_EQUAL)

        if pos == self.POSITION_GREATER_THAN:
            self.__dict__['endContainer'] = parent
            self.__dict__['endOffset'] = offset
            self.__dict__['collapsed'] = 1

        self.__calculateCommonAncestor()
Beispiel #11
0
    def compareBoundaryPoints(self, how, sourceRange):
        if self.detached:
            raise InvalidStateErr()

        if not hasattr(
                sourceRange, '_ownerDocument'
        ) or sourceRange._ownerDocument != self._ownerDocument or not isinstance(
                sourceRange, Range):
            raise WrongDocumentErr()

        if how == self.START_TO_START:
            ac = self.startContainer
            ao = self.startOffset
            bc = sourceRange.startContainer
            bo = sourceRange.startOffset
        elif how == self.START_TO_END:
            ac = self.startContainer
            ao = self.startOffset
            bc = sourceRange.endContainer
            bo = sourceRange.endOffset
        elif how == self.END_TO_END:
            ac = self.endContainer
            ao = self.endOffset
            bc = sourceRange.endContainer
            bo = sourceRange.endOffset
        elif how == self.END_TO_START:
            ac = self.endContainer
            ao = self.endOffset
            bc = sourceRange.startContainer
            bo = sourceRange.startOffset
        else:
            raise TypeError, how

        pos = self.__comparePositions(ac, ao, bc, bo)
        if pos == self.POSITION_EQUAL:
            return 0
        elif pos == self.POSITION_LESS_THAN:
            return -1
        return 1
Beispiel #12
0
    def cloneContents(self):
        """Clone the contents defined by this range"""

        if self.detached:
            raise InvalidStateErr()

        df = self._ownerDocument.createDocumentFragment()

        if self.startContainer == self.endContainer:
            if self.startOffset == self.endOffset:
                return df
            if self.startContainer.nodeType in [
                    Node.TEXT_NODE, Node.COMMENT_NODE,
                    Node.PROCESSING_INSTRUCTION_NODE
            ]:
                #Adjust the character data
                data = self.startContainer.substringData(
                    self.startOffset, 1 + self.endOffset - self.startOffset)
                tx = self._ownerDocument.createTextNode(data)
                df.appendChild(tx)

            else:
                #Clone a set number of children
                numDel = self.endOffset - self.startOffset + 1
                for ctr in range(numDel):
                    c = self.startContainer.childNodes[self.startOffset +
                                                       ctr].cloneNode(1)
                    df.appendChild(c)

        elif self.startContainer == self.commonAncestorContainer:
            #Clone up the endContainer
            #From the start to the end
            lastKids = []
            copyData = None
            if self.endContainer.nodeType in [
                    Node.TEXT_NODE, Node.COMMENT_NODE,
                    Node.PROCESSING_INSTRUCTION_NODE
            ]:
                #Adjust the character data
                copyData = self.endContainer.substringData(0, self.endOffset)
            else:
                numDel = self.endOffset
                for ctr in range(numDel):
                    lastKids.append(
                        self.endContainer.childNodes[ctr].cloneNode(1))

            cur = self.endContainer
            while cur.parentNode != self.commonAncestorContainer:

                #Clone all of the way up
                newCur = cur.cloneNode(0)
                if copyData:
                    newCur.data = copyData
                    copyData = None
                for k in lastKids:
                    newCur.appendChild(k)

                lastKids = []
                index = cur.parentNode.childNodes.index(cur)
                for ctr in range(index):
                    lastKids.append(
                        cur.parentNode.childNodes[ctr].cloneNode(1))
                lastKids.append(newCur)
                cur = cur.parentNode

            newEnd = cur.cloneNode(0)
            for k in lastKids:
                newEnd.appendChild(k)

            endAncestorChild = cur

            #Extract up to the ancestor of end
            for c in self.startContainer.childNodes:
                if c == endAncestorChild:
                    break
                df.appendChild(c.cloneNode(1))
            df.appendChild(newEnd)

        elif self.endContainer == self.commonAncestorContainer:
            lastKids = []
            copyData = None
            if self.startContainer.nodeType in [
                    Node.TEXT_NODE, Node.COMMENT_NODE,
                    Node.PROCESSING_INSTRUCTION_NODE
            ]:
                #Adjust the character data

                copyData = self.startContainer.substringData(
                    self.startOffset,
                    1 + len(self.startContainer.data) - self.startOffset)
            else:
                numDel = len(self.startContainer.childNodes) - self.startOffset
                for ctr in range(numDel):
                    c = self.startContainer.childNodes[self.startOffset +
                                                       ctr].cloneNode(1)
                    lastKids.append(c)

            cur = self.startContainer
            while cur.parentNode != self.commonAncestorContainer:
                #Clone all of the way up
                newCur = cur.cloneNode(0)
                if copyData:
                    newCur.data = copyData
                    copyData = None
                for k in lastKids:
                    newCur.appendChild(k)
                lastKids = [newCur]

                index = cur.parentNode.childNodes.index(cur)
                for ctr in range(index + 1, len(cur.parentNode.childNodes)):
                    lastKids.append(
                        cur.parentNode.childNodes[ctr].cloneNode(1))
                cur = cur.parentNode

            startAncestorChild = cur
            newStart = cur.cloneNode(0)
            for k in lastKids:
                newStart.appendChild(k)

            df.appendChild(newStart)

            #Extract up to the ancestor of start
            startAncestorChild = cur
            startIndex = self.endContainer.childNodes.index(cur)
            lastAdded = None
            for ctr in range(startIndex + 1, self.endOffset + 1):
                c = self.endContainer.childNodes[ctr].cloneNode(1)
                df.insertBefore(c, lastAdded)
                lastAdded = c

        else:
            #From the start to the end
            lastStartKids = []
            startCopyData = None
            if self.startContainer.nodeType in [
                    Node.TEXT_NODE, Node.COMMENT_NODE,
                    Node.PROCESSING_INSTRUCTION_NODE
            ]:
                #Adjust the character data

                startCopyData = self.startContainer.substringData(
                    self.startOffset,
                    1 + len(self.startContainer.data) - self.startOffset)
            else:
                numDel = len(self.startContainer.childNodes) - self.startOffset
                for ctr in range(numDel):
                    c = self.startContainer.childNodes[self.startOffset +
                                                       ctr].cloneNode(1)
                    lastStartKids.append(c)

            cur = self.startContainer
            while cur.parentNode != self.commonAncestorContainer:
                #Clone all of the way up
                newCur = cur.cloneNode(0)
                if startCopyData:
                    newCur.data = startCopyData
                    startCopyData = None
                for k in lastStartKids:
                    newCur.appendChild(k)
                lastStartKids = [newCur]

                index = cur.parentNode.childNodes.index(cur)
                for ctr in range(index + 1, len(cur.parentNode.childNodes)):
                    lastStartKids.append(
                        cur.parentNode.childNodes[ctr].cloneNode(1))
                cur = cur.parentNode

            startAncestorChild = cur

            newStart = cur.cloneNode(0)
            for k in lastStartKids:
                newStart.appendChild(k)

            df.appendChild(newStart)

            lastEndKids = []
            endCopyData = None
            #Delete up the endContainer
            #From the start to the end
            if self.endContainer.nodeType in [
                    Node.TEXT_NODE, Node.COMMENT_NODE,
                    Node.PROCESSING_INSTRUCTION_NODE
            ]:
                #Adjust the character data
                endCopyData = self.endContainer.substringData(
                    0, self.endOffset)
            else:
                numDel = self.endOffset
                for ctr in range(numDel):
                    c = self.endContainer.childNodes[ctr].cloneNode(1)
                    lastEndKids.append(c)

            cur = self.endContainer
            while cur.parentNode != self.commonAncestorContainer:
                newCur = cur.cloneNode(0)
                if endCopyData:
                    newCur.data = endCopyData
                    endCopyData = None
                for k in lastEndKids:
                    newCur.appendChild(k)

                lastEndKids = []
                index = cur.parentNode.childNodes.index(cur)
                for ctr in range(index):
                    lastEndKids.append(
                        cur.parentNode.childNodes[ctr].cloneNode(1))
                lastEndKids.append(newCur)
                cur = cur.parentNode

            endAncestorChild = cur

            newEnd = cur.cloneNode(0)
            for k in lastEndKids:
                newEnd.appendChild(k)

            cur = startAncestorChild
            #Extract everything between us
            startIndex = startAncestorChild.parentNode.childNodes.index(
                startAncestorChild)
            endIndex = endAncestorChild.parentNode.childNodes.index(
                endAncestorChild)
            for ctr in range(startIndex + 1, endIndex):
                c = startAncestorChild.parentNode.childNodes[ctr]
                df.appendChild(c.cloneNode(1))
            df.appendChild(newEnd)

        #Adjust the containers
        #FIXME What the heck is the spec talking about??
        self.__dict__['endContainer'] = self.startContainer
        self.__dict__['endOffset'] = self.startContainer
        self.__dict__['commonAncestorContainer'] = self.startContainer
        self.__dict__['collapsed'] = 1

        return df
Beispiel #13
0
 def __getattr__(self, name):
     if name in self.readOnly:
         #Means we are detached
         raise InvalidStateErr()
     raise AttributeError, name
Beispiel #14
0
    def deleteContents(self):
        """Delete the contents defined by this range"""

        #NOTE Use 4DOM ReleaseNode cause it is interface safe
        from pyxml.dom.ext import ReleaseNode

        if self.detached:
            raise InvalidStateErr()

        if self.startContainer == self.endContainer:
            if self.startOffset == self.endOffset:
                return
            if self.startContainer.nodeType in [
                    Node.TEXT_NODE, Node.COMMENT_NODE,
                    Node.PROCESSING_INSTRUCTION_NODE
            ]:
                #Adjust the character data
                self.startContainer.deleteData(
                    self.startOffset, 1 + self.endOffset - self.startOffset)

            else:
                #Delete a set number of children
                numDel = self.endOffset - self.startOffset + 1
                for ctr in range(numDel):
                    c = self.startContainer.removeChild(
                        self.startContainer.childNodes[self.startOffset])
                    ReleaseNode(c)

            self.__dict__['endContainer'] = self.startContainer
            self.__dict__['endOffset'] = self.endContainer
            self.__dict__['commonAncestorContainer'] = self.endContainer
            self.__dict__['collapsed'] = 1

        elif self.startContainer == self.commonAncestorContainer:
            #Delete up the endContainer
            #From the start to the end
            if self.endContainer.nodeType in [
                    Node.TEXT_NODE, Node.COMMENT_NODE,
                    Node.PROCESSING_INSTRUCTION_NODE
            ]:
                #Adjust the character data
                self.endContainer.deleteData(0, self.endOffset)
            else:
                numDel = self.endOffset
                for ctr in range(numDel):
                    c = self.endContainer.removeChild(
                        self.endContainer.childNodes[0])
                    ReleaseNode(c)

            cur = self.endContainer
            while cur.parentNode != self.commonAncestorContainer:
                while cur.previousSibling:
                    c = cur.parentNode.removeChild(cur.previousSibling)
                    ReleaseNode(c)
                cur = cur.parentNode

            #Delete up to the ancestor of end
            endAncestorChild = cur
            while self.startContainer.firstChild != endAncestorChild:
                c = self.startContainer.removeChild(
                    self.startContainer.firstChild)
                ReleaseNode(c)
        elif self.endContainer == self.commonAncestorContainer:
            if self.startContainer.nodeType in [
                    Node.TEXT_NODE, Node.COMMENT_NODE,
                    Node.PROCESSING_INSTRUCTION_NODE
            ]:
                #Adjust the character data
                self.startContainer.deleteData(
                    self.startOffset,
                    1 + len(self.startContainer.data) - self.startOffset)
            else:
                numDel = len(self.startContainer.childNodes) - self.startOffset
                for ctr in range(numDel):
                    c = self.startContainer.removeChild(
                        self.startContainer.childNodes[self.startOffset])
                    ReleaseNode(c)

            cur = self.startContainer
            while cur.parentNode != self.commonAncestorContainer:
                while cur.nextSibling:
                    c = cur.parentNode.removeChild(cur.nextSibling)
                    ReleaseNode(c)
                cur = cur.parentNode

            startAncestorChild = cur

            #Delete up to the ancestor of start
            startAncestorChild = cur
            startIndex = self.endContainer.childNodes.index(cur)
            numDel = self.endOffset - startIndex
            for ctr in range(numDel):
                c = self.endContainer.removeChild(
                    startAncestorChild.nextSibling)
                ReleaseNode(c)

        else:
            #From the start to the end
            if self.startContainer.nodeType in [
                    Node.TEXT_NODE, Node.COMMENT_NODE,
                    Node.PROCESSING_INSTRUCTION_NODE
            ]:
                #Adjust the character data
                self.startContainer.deleteData(
                    self.startOffset,
                    1 + len(self.startContainer.data) - self.startOffset)
            else:
                numDel = len(self.startContainer.childNodes) - self.startOffset
                for ctr in range(numDel):
                    c = self.startContainer.removeChild(
                        self.startContainer.childNodes[self.startOffset])
                    ReleaseNode(c)

            cur = self.startContainer
            while cur.parentNode != self.commonAncestorContainer:
                while cur.nextSibling:
                    c = cur.parentNode.removeChild(cur.nextSibling)
                    ReleaseNode(c)
                cur = cur.parentNode

            startAncestorChild = cur
            #Delete up the endContainer
            #From the start to the end
            if self.endContainer.nodeType in [
                    Node.TEXT_NODE, Node.COMMENT_NODE,
                    Node.PROCESSING_INSTRUCTION_NODE
            ]:
                #Adjust the character data
                self.endContainer.deleteData(0, self.endOffset)
            else:
                numDel = self.endOffset
                for ctr in range(numDel):
                    c = self.endContainer.removeChild(
                        self.endContainer.childNodes[0])
                    ReleaseNode(c)

            cur = self.endContainer
            while cur.parentNode != self.commonAncestorContainer:
                while cur.previousSibling:
                    c = cur.parentNode.removeChild(cur.previousSibling)
                    ReleaseNode(c)
                cur = cur.parentNode

            endAncestorChild = cur

            cur = startAncestorChild
            #Delete everything between us
            while cur.nextSibling != endAncestorChild:
                c = cur.parentNode.removeChild(cur.nextSibling)
                ReleaseNode(c)

        #Adjust the containers
        #FIXME What the heck is the spec talking about??
        self.__dict__['endContainer'] = self.startContainer
        self.__dict__['endOffset'] = self.startContainer
        self.__dict__['commonAncestorContainer'] = self.startContainer
        self.__dict__['collapsed'] = 1

        return None