📄 dom2_rangeimpl.cpp
字号:
else
cmnRoot->removeChild(n,exceptioncode);
}
}
if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents)
fragment->appendChild(rightContents,exceptioncode);
// collapse to the proper position - see spec section 2.6
if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
if (!partialStart && !partialEnd)
collapse(true,exceptioncode);
else if (partialStart) {
setStartContainer(partialStart->parentNode());
setEndContainer(partialStart->parentNode());
m_startOffset = m_endOffset = partialStart->nodeIndex()+1;
}
else if (partialEnd) {
setStartContainer(partialEnd->parentNode());
setEndContainer(partialEnd->parentNode());
m_startOffset = m_endOffset = partialEnd->nodeIndex();
}
}
return fragment;
}
DocumentFragmentImpl *RangeImpl::extractContents( int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return 0;
}
checkDeleteExtract(exceptioncode);
if (exceptioncode)
return 0;
return processContents(EXTRACT_CONTENTS,exceptioncode);
}
DocumentFragmentImpl *RangeImpl::cloneContents( int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return 0;
}
return processContents(CLONE_CONTENTS,exceptioncode);
}
void RangeImpl::insertNode( NodeImpl *newNode, int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return;
}
// NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
// the Range is read-only.
if (containedByReadOnly()) {
exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
return;
}
// WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
// not created from the same document.
if (newNode->getDocument() != m_startContainer->getDocument()) {
exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
return;
}
// HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
// does not allow children of the type of newNode or if newNode is an ancestor of the container.
// an extra one here - if a text node is going to split, it must have a parent to insert into
if (m_startContainer->nodeType() == Node::TEXT_NODE && !m_startContainer->parentNode()) {
exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
return;
}
// In the case where the container is a text node, we check against the container's parent, because
// text nodes get split up upon insertion.
NodeImpl *checkAgainst;
if (m_startContainer->nodeType() == Node::TEXT_NODE)
checkAgainst = m_startContainer->parentNode();
else
checkAgainst = m_startContainer;
if (newNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
// check each child node, not the DocumentFragment itself
NodeImpl *c;
for (c = newNode->firstChild(); c; c = c->nextSibling()) {
if (!checkAgainst->childTypeAllowed(c->nodeType())) {
exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
return;
}
}
}
else {
if (!checkAgainst->childTypeAllowed(newNode->nodeType())) {
exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
return;
}
}
for (NodeImpl *n = m_startContainer; n; n = n->parentNode()) {
if (n == newNode) {
exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
return;
}
}
// INVALID_NODE_TYPE_ERR: Raised if newNode is an Attr, Entity, Notation, or Document node.
if( newNode->nodeType() == Node::ATTRIBUTE_NODE ||
newNode->nodeType() == Node::ENTITY_NODE ||
newNode->nodeType() == Node::NOTATION_NODE ||
newNode->nodeType() == Node::DOCUMENT_NODE) {
exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
return;
}
if( m_startContainer->nodeType() == Node::TEXT_NODE ||
m_startContainer->nodeType() == Node::CDATA_SECTION_NODE )
{
TextImpl *newText = static_cast<TextImpl*>(m_startContainer)->splitText(m_startOffset,exceptioncode);
if (exceptioncode)
return;
m_startContainer->parentNode()->insertBefore( newNode, newText, exceptioncode );
}
else {
m_startContainer->insertBefore( newNode, m_startContainer->childNode( m_startOffset ), exceptioncode );
}
}
DOMString RangeImpl::toString( int &exceptioncode ) const
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return DOMString();
}
DOMString text = "";
NodeImpl *pastEnd = pastEndNode();
for (NodeImpl *n = startNode(); n != pastEnd; n = n->traverseNextNode()) {
if (n->nodeType() == DOM::Node::TEXT_NODE || n->nodeType() == DOM::Node::CDATA_SECTION_NODE) {
DOMString str = static_cast<TextImpl *>(n)->data().copy();
if (n == m_endContainer)
str.truncate(m_endOffset);
if (n == m_startContainer)
str.remove(0, m_startOffset);
text += str;
}
}
return text;
}
DOMString RangeImpl::toHTML() const
{
return createMarkup(this);
}
DOMString RangeImpl::text() const
{
if (m_detached)
return DOMString();
// We need to update layout, since plainText uses line boxes in the render tree.
// FIXME: As with innerText, we'd like this to work even if there are no render objects.
m_startContainer->getDocument()->updateLayout();
// FIXME: Maybe DOMRange constructor should take const DOMRangeImpl*; if it did we would not need this const_cast.
return plainText(const_cast<RangeImpl *>(this));
}
DocumentFragmentImpl *RangeImpl::createContextualFragment ( DOMString &html, int &exceptioncode ) const
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return NULL;
}
if (! m_startContainer->isHTMLElement()) {
exceptioncode = DOMException::NOT_SUPPORTED_ERR;
return NULL;
}
HTMLElementImpl *e = static_cast<HTMLElementImpl *>(m_startContainer);
DocumentFragmentImpl *fragment = e->createContextualFragment(html);
if (!fragment) {
exceptioncode = DOMException::NOT_SUPPORTED_ERR;
return NULL;
}
return fragment;
}
void RangeImpl::detach( int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return;
}
if (m_startContainer)
m_startContainer->deref();
m_startContainer = 0;
if (m_endContainer)
m_endContainer->deref();
m_endContainer = 0;
m_detached = true;
}
bool RangeImpl::isDetached() const
{
return m_detached;
}
void RangeImpl::checkNodeWOffset( NodeImpl *n, int offset, int &exceptioncode) const
{
if( offset < 0 ) {
exceptioncode = DOMException::INDEX_SIZE_ERR;
}
switch (n->nodeType()) {
case Node::ENTITY_NODE:
case Node::NOTATION_NODE:
case Node::DOCUMENT_TYPE_NODE:
exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
break;
case Node::TEXT_NODE:
case Node::COMMENT_NODE:
case Node::CDATA_SECTION_NODE:
if ( (unsigned long)offset > static_cast<CharacterDataImpl*>(n)->length() )
exceptioncode = DOMException::INDEX_SIZE_ERR;
break;
case Node::PROCESSING_INSTRUCTION_NODE:
// ### are we supposed to check with just data or the whole contents?
if ( (unsigned long)offset > static_cast<ProcessingInstructionImpl*>(n)->data().length() )
exceptioncode = DOMException::INDEX_SIZE_ERR;
break;
default:
if ( (unsigned long)offset > n->childNodeCount() )
exceptioncode = DOMException::INDEX_SIZE_ERR;
break;
}
}
void RangeImpl::checkNodeBA( NodeImpl *n, int &exceptioncode ) const
{
// INVALID_NODE_TYPE_ERR: Raised if the root container of refNode is not an
// Attr, Document or DocumentFragment node or if refNode is a Document,
// DocumentFragment, Attr, Entity, or Notation node.
NodeImpl *root = n;
while (root->parentNode())
root = root->parentNode();
if (!(root->nodeType() == Node::ATTRIBUTE_NODE ||
root->nodeType() == Node::DOCUMENT_NODE ||
root->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)) {
exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
return;
}
if( n->nodeType() == Node::DOCUMENT_NODE ||
n->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
n->nodeType() == Node::ATTRIBUTE_NODE ||
n->nodeType() == Node::ENTITY_NODE ||
n->nodeType() == Node::NOTATION_NODE )
exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
}
RangeImpl *RangeImpl::cloneRange(int &exceptioncode) const
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return 0;
}
return new RangeImpl(m_ownerDocument,m_startContainer,m_startOffset,m_endContainer,m_endOffset);
}
void RangeImpl::setStartAfter( NodeImpl *refNode, int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return;
}
if (!refNode) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return;
}
if (refNode->getDocument() != m_ownerDocument->document()) {
exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
return;
}
checkNodeBA( refNode, exceptioncode );
if (exceptioncode)
return;
setStart( refNode->parentNode(), refNode->nodeIndex()+1, exceptioncode );
}
void RangeImpl::setEndBefore( NodeImpl *refNode, int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return;
}
if (!refNode) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return;
}
if (refNode->getDocument() != m_ownerDocument->document()) {
exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
return;
}
checkNodeBA( refNode, exceptioncode );
if (exceptioncode)
return;
setEnd( refNode->parentNode(), refNode->nodeIndex(), exceptioncode );
}
void RangeImpl::setEndAfter( NodeImpl *refNode, int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return;
}
if (!refNode) {
exceptioncode = DOMException::NOT_FOUND_ERR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -