📄 range.py
字号:
########################################################################
#
# File Name: Range.py
#
# Documentation: http://docs.4suite.com/4DOM/Range.py.html
#
"""
WWW: http://4suite.com/4DOM e-mail: support@4suite.com
Copyright (c) 2000 Fourthought Inc, USA. All Rights Reserved.
See http://4suite.com/COPYRIGHT for license and copyright information
"""
from xml.dom import InvalidStateErr
from xml.dom import InvalidNodeTypeErr
from xml.dom import BadBoundaryPointsErr
from xml.dom import IndexSizeErr
from xml.dom import WrongDocumentErr
from xml.dom import Node
class Range:
readOnly =['startContainer',
'startOffset',
'endContainer',
'endOffset',
'collapsed',
'commonAncestorContainer',
]
POSITION_EQUAL = 1
POSITION_LESS_THAN = 2
POSITION_GREATER_THAN = 3
START_TO_START = 0
START_TO_END = 1
END_TO_END = 2
END_TO_START = 3
def __init__(self,ownerDocument):
self._ownerDocument = ownerDocument
self.__dict__['startContainer'] = ownerDocument
self.__dict__['startOffset'] = 0
self.__dict__['endContainer'] = ownerDocument
self.__dict__['endOffset'] = 0
self.__dict__['collapsed'] = 1
self.__dict__['commonAncestorContainer'] = ownerDocument
self.__dict__['detached'] = 0
def __setattr__(self,name,value):
if name in self.readOnly:
raise AttributeError, name
self.__dict__[name] = value
def __getattr__(self,name):
if name in self.readOnly:
#Means we are detached
raise InvalidStateErr()
raise AttributeError, name
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
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
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
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
def deleteContents(self):
"""Delete the contents defined by this range"""
#NOTE Use 4DOM ReleaseNode cause it is interface safe
from xml.dom.ext import ReleaseNode
if self.detached:
raise InvalidStateErr()
if self.startContainer == self.endContainer:
if self.startOffset == self.endOffset:
return
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -