📄 dom_nodeimpl.cpp
字号:
NodeImpl *NodeBaseImpl::childNode(unsigned long index){ unsigned long i; NodeImpl *n = firstChild(); for (i = 0; n && i < index; i++) n = n->nextSibling(); return n;}void NodeBaseImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode ){ if (getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) { MutationEventImpl* const evt = new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT,true,false,this,DOMString(),DOMString(),DOMString(),0); evt->ref(); child->dispatchEvent(evt,exceptioncode,true); evt->deref(); if (exceptioncode) return; } // dispatch the DOMNodeInsertedIntoDocument event to all descendants bool hasInsertedListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER); NodeImpl *p = this; while (p->parentNode()) p = p->parentNode(); if (p->nodeType() == Node::DOCUMENT_NODE) { for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) { c->insertedIntoDocument(); if (hasInsertedListeners) { MutationEventImpl* const evt = new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT,false,false,0,DOMString(),DOMString(),DOMString(),0); evt->ref(); c->dispatchEvent(evt,exceptioncode,true); evt->deref(); if (exceptioncode) return; } } }}void NodeBaseImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode ){ // Dispatch pre-removal mutation events getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) { MutationEventImpl* const evt = new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,true,false,this,DOMString(),DOMString(),DOMString(),0); evt->ref(); child->dispatchEvent(evt,exceptioncode,true); evt->deref(); if (exceptioncode) return; } bool hasRemovalListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER); // dispatch the DOMNodeRemovedFromDocument event to all descendants NodeImpl *p = this; while (p->parentNode()) p = p->parentNode(); if (p->nodeType() == Node::DOCUMENT_NODE) { for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) { if (hasRemovalListeners) { MutationEventImpl* const evt = new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT,false,false,0,DOMString(),DOMString(),DOMString(),0); evt->ref(); c->dispatchEvent(evt,exceptioncode,true); evt->deref(); if (exceptioncode) return; } } }}// ---------------------------------------------------------------------------NodeImpl *NodeListImpl::item( unsigned long index ) const{ unsigned long requestIndex = index; m_cache->updateNodeListInfo(m_refNode->getDocument()); NodeImpl* n; bool usedCache = false; if (m_cache->current.node) { //Compute distance from the requested index to the cache node long cacheDist = QABS(long(index) - long(m_cache->position)); if (cacheDist < index) { //Closer to the cached position usedCache = true; if (index >= m_cache->position) { //Go ahead unsigned long relIndex = index - m_cache->position; n = recursiveItem(m_refNode, m_cache->current.node, relIndex); } else { //Go backwards unsigned long relIndex = m_cache->position - index; n = recursiveItemBack(m_refNode, m_cache->current.node, relIndex); } } } if (!usedCache) n = recursiveItem(m_refNode, m_refNode->firstChild(), index); //We always update the cache state, to make starting iteration //where it was left off easy. m_cache->current.node = n; m_cache->position = requestIndex; return n;}unsigned long NodeListImpl::length() const{ m_cache->updateNodeListInfo(m_refNode->getDocument()); if (!m_cache->hasLength) { m_cache->length = recursiveLength( m_refNode ); m_cache->hasLength = true; } return m_cache->length;}unsigned long NodeListImpl::recursiveLength(NodeImpl *start) const{ unsigned long len = 0; for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) { bool recurse = true; if (nodeMatches(n, recurse)) len++; if (recurse) len+= recursiveLength(n); } return len;}NodeListImpl::NodeListImpl( NodeImpl *n, int type, CacheFactory* factory ){ m_refNode = n; m_refNode->ref(); m_cache = m_refNode->getDocument()->acquireCachedNodeListInfo( factory ? factory : Cache::make, n, type );}NodeListImpl::~NodeListImpl(){ m_refNode->getDocument()->releaseCachedNodeListInfo(m_cache); m_refNode->deref();}/** Next item in the pre-order walk of tree from node, but not going outside absStart*/static NodeImpl* helperNext(NodeImpl* node, NodeImpl* absStart){ //Walk up until we wind a sibling to go to. while (!node->nextSibling() && node != absStart) node = node->parentNode(); if (node != absStart) return node->nextSibling(); else return 0;}NodeImpl *NodeListImpl::recursiveItem ( NodeImpl* absStart, NodeImpl *start, unsigned long &offset ) const{ for(NodeImpl *n = start; n != 0; n = helperNext(n, absStart)) { bool recurse = true; if (nodeMatches(n, recurse)) if (!offset--) return n; NodeImpl *depthSearch = recurse ? recursiveItem(n, n->firstChild(), offset) : 0; if (depthSearch) return depthSearch; } return 0; // no matching node in this subtree}NodeImpl *NodeListImpl::recursiveItemBack ( NodeImpl* absStart, NodeImpl *start, unsigned long &offset ) const{ //### it might be cleaner/faster to split nodeMatches and recursion //filtering. bool dummy = true; NodeImpl* n = start; do { bool recurse = true; //Check whether the current node matches. if (nodeMatches(n, dummy)) if (!offset--) return n; if (n->previousSibling()) { //Move to the last node of this whole subtree that we should recurse into n = n->previousSibling(); recurse = true; while (n->lastChild()) { (void)nodeMatches(n, recurse); if (!recurse) break; //Don't go there n = n->lastChild(); } } else { //We're done with this whole subtree, so move up n = n->parentNode(); } } while (n && n != absStart); return 0;}NodeListImpl::Cache::~Cache(){}void NodeListImpl::Cache::clear(DocumentImpl* doc){ hasLength = false; current.node = 0; version = doc->domTreeVersion();}void NodeListImpl::Cache::updateNodeListInfo(DocumentImpl* doc){ //If version doesn't match, clear if (doc->domTreeVersion() != version) clear(doc);}ChildNodeListImpl::ChildNodeListImpl( NodeImpl *n ): NodeListImpl(n, CHILD_NODES){}bool ChildNodeListImpl::nodeMatches( NodeImpl* /*testNode*/, bool& doRecurse ) const{ doRecurse = false; return true;}TagNodeListImpl::TagNodeListImpl( NodeImpl *n, NodeImpl::Id id ) : NodeListImpl(n, UNCACHEABLE), m_id(id), m_namespaceAware(false){ // An id of 0 here means "*" (match all nodes) m_matchAllNames = (id == 0); m_matchAllNamespaces = false;}TagNodeListImpl::TagNodeListImpl( NodeImpl *n, const DOMString &namespaceURI, const DOMString &localName ) : NodeListImpl(n, UNCACHEABLE), m_id(0), m_namespaceURI(namespaceURI), m_localName(localName), m_namespaceAware(true){ m_matchAllNames = (localName == "*"); m_matchAllNamespaces = (namespaceURI == "*");}bool TagNodeListImpl::nodeMatches( NodeImpl *testNode, bool& /*doRecurse*/ ) const{ if ( testNode->nodeType() != Node::ELEMENT_NODE ) return false; if (m_namespaceAware) return (m_matchAllNamespaces || testNode->namespaceURI() == m_namespaceURI) && (m_matchAllNames || testNode->localName() == m_localName); else { NodeImpl::Id testId = testNode->id(); //we have to strip the namespaces if we compare in a namespace unaware fashion if ( !m_namespaceAware ) testId &= ~NodeImpl_IdNSMask; return (m_id == 0 || m_id == testId); }}NameNodeListImpl::NameNodeListImpl(NodeImpl *n, const DOMString &t ) : NodeListImpl(n, UNCACHEABLE), nodeName(t){}bool NameNodeListImpl::nodeMatches( NodeImpl *testNode, bool& /*doRecurse*/ ) const{ if ( testNode->nodeType() != Node::ELEMENT_NODE ) return false; return static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;}// ---------------------------------------------------------------------------NamedNodeMapImpl::NamedNodeMapImpl(){}NamedNodeMapImpl::~NamedNodeMapImpl(){}// ----------------------------------------------------------------------------GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentPtr* doc) : NamedNodeMapImpl(){ m_doc = doc->document(); m_contents = new QPtrList<NodeImpl>;}GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl(){ while (!m_contents->isEmpty()) m_contents->take(0)->deref(); delete m_contents;}NodeImpl *GenericRONamedNodeMapImpl::getNamedItem ( NodeImpl::Id id, bool /*nsAware*/, DOMStringImpl* /*qName*/ ) const{ // ## do we need namespace support in this class? QPtrListIterator<NodeImpl> it(*m_contents); for (; it.current(); ++it) if (it.current()->id() == id) return it.current(); return 0;}Node GenericRONamedNodeMapImpl::setNamedItem ( NodeImpl* /*arg*/, bool /*nsAware*/, DOMStringImpl* /*qName*/, int &exceptioncode ){ // can't modify this list through standard DOM functions // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return 0;}Node GenericRONamedNodeMapImpl::removeNamedItem ( NodeImpl::Id /*id*/, bool /*nsAware*/, DOMStringImpl* /*qName*/, int &exceptioncode ){ // can't modify this list through standard DOM functions // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return 0;}NodeImpl *GenericRONamedNodeMapImpl::item ( unsigned long index ) const{ if (index >= m_contents->count()) return 0; return m_contents->at(index);}unsigned long GenericRONamedNodeMapImpl::length( ) const{ return m_contents->count();}void GenericRONamedNodeMapImpl::addNode(NodeImpl *n){ // The spec says that in the case of duplicates we only keep the first one if (getNamedItem(n->id(), false, 0)) return; n->ref(); m_contents->append(n);}NodeImpl::Id GenericRONamedNodeMapImpl::mapId(DOMStringImpl* namespaceURI, DOMStringImpl* localName, bool readonly){ if (!m_doc) return 0; return m_doc->getId(NodeImpl::ElementId, namespaceURI, 0, localName, readonly, false /*don't lookupHTML*/);}// -----------------------------------------------------------------------------void RegisteredListenerList::addEventListener(int id, EventListener *listener, const bool useCapture){ RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture); if (!listeners) listeners = new QValueList<RegisteredEventListener>; // if this id/listener/useCapture combination is already registered, do nothing. // the DOM2 spec says that "duplicate instances are discarded", and this keeps // the listener order intact. QValueList<RegisteredEventListener>::iterator it; for (it = listeners->begin(); it != listeners->end(); ++it) if (*it == rl) return; listeners->append(rl);}void RegisteredListenerList::removeEventListener(int id, EventListener *listener, bool useCapture){ if (!listeners) // nothing to remove return; RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture); QValueList<RegisteredEventListener>::iterator it; for (it = listeners->begin(); it != listeners->end(); ++it) if (*it == rl) { listeners->remove(it); return; }}bool RegisteredListenerList::isHTMLEventListener(EventListener* listener){ return (listener->eventListenerType() == "_khtml_HTMLEventListener");}void RegisteredListenerList::setHTMLEventListener(int id, EventListener *listener){ if (!listeners) listeners = new QValueList<RegisteredEventListener>; QValueList<RegisteredEventListener>::iterator it; if (!listener) { for (it = listeners->begin(); it != listeners->end(); ++it) { if ((*it).id == id && isHTMLEventListener((*it).listener)) { listeners->remove(it); break; } } return; } // if this event already has a registered handler, insert the new one in // place of the old one, to preserve the order. RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,false); int i; for (i = 0, it = listeners->begin(); it != listeners->end(); ++it, ++i) if ((*it).id == id && isHTMLEventListener((*it).listener)) { listeners->insert(it, rl); listeners->remove(it); return; } listeners->append(rl);}EventListener *RegisteredListenerList::getHTMLEventListener(int id){ if (!listeners) return 0; QValueList<RegisteredEventListener>::iterator it; for (it = listeners->begin(); it != listeners->end(); ++it) if ((*it).id == id && isHTMLEventListener((*it).listener)) { return (*it).listener; } return 0;}bool RegisteredListenerList::hasEventListener(int id){ if (!listeners) return false; QValueList<RegisteredEventListener>::iterator it; for (it = listeners->begin(); it != listeners->end(); ++it) if ((*it).id == id) return true; return false;}void RegisteredListenerList::clear(){ delete listeners; listeners = 0;}bool RegisteredListenerList::stillContainsListener(const RegisteredEventListener& listener){ if (!listeners) return false; return listeners->find(listener) != listeners->end();}RegisteredListenerList::~RegisteredListenerList() { delete listeners; listeners = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -