📄 dom2_rangeimpl.cpp
字号:
return;}DocumentFragment RangeImpl::extractContents( ){ if( isDetached() ) throw DOMException( DOMException::INVALID_STATE_ERR ); return masterTraverse( true );}DocumentFragment RangeImpl::cloneContents( ){ if( isDetached() ) throw DOMException( DOMException::INVALID_STATE_ERR ); return masterTraverse( false );}void RangeImpl::insertNode( const Node &newNode ){ if( isDetached() ) throw DOMException( DOMException::INVALID_STATE_ERR ); if( newNode.nodeType() == Node::ATTRIBUTE_NODE || newNode.nodeType() == Node::ENTITY_NODE || newNode.nodeType() == Node::NOTATION_NODE || newNode.nodeType() == Node::DOCUMENT_NODE || newNode.nodeType() == Node::DOCUMENT_FRAGMENT_NODE) throw RangeException( RangeException::INVALID_NODE_TYPE_ERR); if( newNode.ownerDocument() != startContainer.ownerDocument() ) throw DOMException( DOMException::WRONG_DOCUMENT_ERR ); if( startContainer.nodeType() == Node::TEXT_NODE ) { Text newText; Node newParent = newNode.parentNode(); Text textNode = static_cast<Text>(startContainer); newText = textNode.splitText(startOffset); newParent.insertBefore( newNode, newText ); } else startContainer.insertBefore( newNode, startContainer.childNodes().item( startOffset ) );}void RangeImpl::surroundContents( const Node &newParent ){ if( isDetached() ) throw DOMException( DOMException::INVALID_STATE_ERR ); if( newParent.isNull() ) return; if( newParent.ownerDocument() != startContainer.ownerDocument() ) throw DOMException( DOMException::WRONG_DOCUMENT_ERR ); if( newParent.nodeType() == Node::ATTRIBUTE_NODE || newParent.nodeType() == Node::ENTITY_NODE || newParent.nodeType() == Node::NOTATION_NODE || newParent.nodeType() == Node::DOCUMENT_TYPE_NODE || newParent.nodeType() == Node::DOCUMENT_NODE || newParent.nodeType() == Node::DOCUMENT_FRAGMENT_NODE) throw RangeException( RangeException::INVALID_NODE_TYPE_ERR ); // revisit: if you set a range without optimizing it (trimming) the following exception might be // thrown incorrectly Node realStart = (startContainer.nodeType() == Node::TEXT_NODE)? startContainer.parentNode() : startContainer; Node realEnd = (endContainer.nodeType() == Node::TEXT_NODE)? endContainer.parentNode() : endContainer; if( realStart != realEnd ) throw RangeException( RangeException::BAD_BOUNDARYPOINTS_ERR ); DocumentFragment fragment = extractContents(); insertNode( newParent ); // BIC: to avoid this const_cast newParent shouldn't be const //(const_cast<Node>(newParent)).appendChild( fragment ); ((Node)(newParent)).appendChild( fragment ); selectNode( newParent ); }Range RangeImpl::cloneRange( ){ if( isDetached() ) throw DOMException( DOMException::INVALID_STATE_ERR ); return Range( this );}DOMString RangeImpl::toString( ){ if( isDetached() ) throw DOMException( DOMException::INVALID_STATE_ERR ); NodeIteratorImpl iterator( getStartContainer().childNodes().item( getStartOffset() ) ); DOMString _string; Node _node = iterator.nextNode(); while( !_node.isNull() ) { printf( "\nNodetype: %s\n", _node.nodeName().string().ascii() ); if( _node.nodeType() == Node::TEXT_NODE ) { QString str = _node.nodeValue().string(); if( _node == getStartContainer() && _node == getEndContainer() ) _string = str.mid( getStartOffset(), getEndOffset() - getStartOffset() ); else if( _node == getStartContainer() ) _string = str.mid( getStartOffset() ); else if( _node == getEndContainer() ) _string += str.left( getStartOffset() ); else _string += str; } else if( _node.nodeName() == "BR" ) _string += "\n"; else if( _node.nodeName() == "P" || _node.nodeName() == "TD" ) _string += "\n\n"; else _string += " "; _node = iterator.nextNode(); } return _string;}DOMString RangeImpl::toHTML( ){ if( isDetached() ) throw DOMException( DOMException::INVALID_STATE_ERR ); // this is just to avoid compiler warnings DOMString d; return d;}void RangeImpl::detach( ){ if( isDetached() ) throw DOMException(DOMException::INVALID_STATE_ERR); else detached = true;}bool RangeImpl::isDetached() const{ return detached;}DocumentFragment RangeImpl::masterTraverse(bool contentExtract){ /* function description easy case, startContainer == endContainer * If we have a text node simply clone/extract the contents between * start & end and put them into the fragment * If we don't have a text node, find the offset and copy/clone the content * between the two offsets * We end with returning the fragment of course */ Node _clone; DocumentFragment _endFragment( ownerDocument.createDocumentFragment() ); if(startContainer == endContainer) { if(startOffset == endOffset) // we have a collapsed range return DocumentFragment(); // TODO: we need to delete the text Node if a whole text is selected!! if( startContainer.nodeType() == Node::TEXT_NODE ) // we have a text node.. special :) { _clone = startContainer.cloneNode(false); _clone.nodeValue().remove(0, startOffset); // we need to get the SUBSTRING _clone.nodeValue().remove(endOffset, _clone.nodeValue().length() - endOffset); if(contentExtract) { // full trim :) startContainer.nodeValue().remove(startOffset, endOffset - startOffset); } _endFragment.appendChild(_clone); } else // we have the same container class but we are not a text node { Node _tempCurrent = startContainer.firstChild(); unsigned int i; for(i=0; i < startOffset; i++) // get the node given by the offset _tempCurrent = _tempCurrent.nextSibling(); /* now copy (or move) all the nodes in the range into the document fragment */ unsigned int range = endOffset - startOffset; Node _nextCurrent = _tempCurrent; // to keep track of which node to take next for(i=0; i<range && !_tempCurrent.isNull(); i++) // check of isNull in case of strange errors { _nextCurrent = _tempCurrent.nextSibling(); if(contentExtract) { _endFragment.appendChild(_tempCurrent); } else { _clone = _tempCurrent.cloneNode(true); _endFragment.appendChild(_clone); } _tempCurrent = _nextCurrent; } } return _endFragment; }// END COMMON CONTAINER HERE!!! /* Ok here we go for the harder part, first a general desription: * First we copy all the border nodes (the have to be copied as long * as they are partially selected) from the startContainer to the CmnAContainer. Then we do * the same for the endContainer. After this we add all fully selected * nodes that are between these two! */ Node _cmnRoot = getCommonAncestorContainer(); Node _tempCurrent = startContainer; Node _tempPartial; // we still have Node _clone!! // Special case text is first: if( _tempCurrent.nodeType() == Node::TEXT_NODE ) { _clone = _tempCurrent.cloneNode(false); _clone.nodeValue().remove(0, startOffset); if(contentExtract) { startContainer.nodeValue().split(startOffset); } } else { _tempCurrent = _tempCurrent.firstChild(); unsigned int i; for(i=0; i < startOffset; i++) _tempCurrent = _tempCurrent.nextSibling(); if(contentExtract) _clone = _tempCurrent.cloneNode(true); else _clone = _tempCurrent; } Node _tempParent; // we use this to traverse upwords trough the tree Node _cloneParent; // this one is used to copy the current parent Node _fragmentRoot; // this is eventually becomming the root of the DocumentFragment while( _tempCurrent != _cmnRoot ) // traversing from the Container, all the way up to the commonAncestor { // all these node must be cloned as they are partially selected _tempParent = _tempCurrent.parentNode(); if(_tempParent == _cmnRoot) { _cloneParent = _endFragment; _fragmentRoot = _tempCurrent; } else { _cloneParent = _tempParent.cloneNode(false); if( _tempPartial.isNull() && _tempParent != _cmnRoot ) { _tempPartial = _tempParent; // TODO: this means we should collapse after I think... :)) } } // we must not forget to grab with us the rest of this nodes siblings Node _nextCurrent; _tempCurrent = _tempCurrent.nextSibling(); _cloneParent.appendChild( _clone ); while( !_tempCurrent.isNull() ) { _nextCurrent = _tempCurrent.nextSibling(); if( !_tempCurrent.isNull() && _tempParent != _cmnRoot) // the isNull() part should be unessesary { if(contentExtract) { _cloneParent.appendChild(_tempCurrent); } else { _clone = _tempCurrent.cloneNode(true); _cloneParent.appendChild(_clone); } } _tempCurrent = _nextCurrent; } _tempCurrent = _tempParent; _clone = _cloneParent; } //****** we should now be FINISHED with startContainer ********** _tempCurrent = endContainer; Node _tempEnd; // we still have Node _clone!! // Special case text is first: if( _tempCurrent.nodeType() == Node::TEXT_NODE ) { _clone = _tempCurrent.cloneNode(false); _clone.nodeValue().split(endOffset); if(contentExtract) { endContainer.nodeValue().remove(endOffset, endContainer.nodeValue().length() - endOffset ); } } else { if(endOffset == 0) _tempCurrent = endContainer; else { _tempCurrent = _tempCurrent.firstChild(); unsigned int i; for(i=0; i< endOffset; i++) _tempCurrent = _tempCurrent.nextSibling(); } if(contentExtract) _clone = _tempCurrent; else _clone = _tempCurrent.cloneNode(true); } while( _tempCurrent != _cmnRoot ) // traversing from the Container, all the way up to the commonAncestor { // all these node must be cloned as they are partially selected _tempParent = _tempCurrent.parentNode(); if(_tempParent == _cmnRoot) { _cloneParent = _endFragment; _fragmentRoot = _tempCurrent; } else { _cloneParent = _tempParent.cloneNode(false); if( _tempPartial.isNull() && _tempParent != _cmnRoot ) { _tempPartial = _tempParent; // TODO: this means we should collapse before I think... :)) } } // we must not forget to grab with us the rest of this nodes siblings Node _nextCurrent; Node _stopNode = _tempCurrent; _tempCurrent = _tempParent.firstChild(); _cloneParent.appendChild(_clone); while( _tempCurrent != _stopNode && !_tempCurrent.isNull() ) { _nextCurrent = _tempCurrent.nextSibling(); if( !_tempCurrent.isNull() && _tempParent != _cmnRoot) // the isNull() part should be unessesary { if(contentExtract) { _cloneParent.appendChild(_tempCurrent); } else { _clone = _tempCurrent.cloneNode(true); _cloneParent.appendChild(_clone); } } _tempCurrent = _nextCurrent; } _tempCurrent = _tempParent; _clone = _cloneParent; } // To end the balade we grab with us any nodes that are between the two topmost parents under // the commonRoot Node _clonePrevious = _endFragment.lastChild(); _tempCurrent = _tempEnd.previousSibling(); Node _nextCurrent; while( (_nextCurrent != _fragmentRoot) && (!_tempCurrent.isNull()) ) { _nextCurrent = _tempCurrent.previousSibling(); if(contentExtract) _clone = _tempCurrent.cloneNode(true); else _clone = _tempCurrent; _endFragment.insertBefore(_clone, _clonePrevious); _tempCurrent = _nextCurrent; _clonePrevious = _tempCurrent; } // WHAT ABOUT THE COLLAPSES?? return _endFragment;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -