📄 dom_elementimpl.cpp
字号:
for(unsigned int i = 0; i < len; i++)
attributeChanged(namedAttrMap->attrs[i]);
}
}
bool ElementImpl::hasAttributes() const
{
updateStyleAttributeIfNeeded();
return namedAttrMap && namedAttrMap->length() > 0;
}
DOMString ElementImpl::nodeName() const
{
return tagName();
}
DOMString ElementImpl::tagName() const
{
DOMString tn = getDocument()->tagName(id());
if (m_prefix)
return DOMString(m_prefix) + ":" + tn;
return tn;
}
void ElementImpl::setPrefix( const DOMString &_prefix, int &exceptioncode )
{
checkSetPrefix(_prefix, exceptioncode);
if (exceptioncode)
return;
if (m_prefix)
m_prefix->deref();
m_prefix = _prefix.implementation();
if (m_prefix)
m_prefix->ref();
}
void ElementImpl::createAttributeMap() const
{
namedAttrMap = new NamedAttrMapImpl(const_cast<ElementImpl*>(this));
namedAttrMap->ref();
}
bool ElementImpl::isURLAttribute(AttributeImpl *attr) const
{
return false;
}
RenderStyle *ElementImpl::styleForRenderer(RenderObject *parentRenderer)
{
return getDocument()->styleSelector()->styleForElement(this);
}
RenderObject *ElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
{
if (getDocument()->documentElement() == this && style->display() == NONE) {
// Ignore display: none on root elements. Force a display of block in that case.
RenderBlock* result = new (arena) RenderBlock(this);
if (result) result->setStyle(style);
return result;
}
return RenderObject::createObject(this, style);
}
void ElementImpl::insertedIntoDocument()
{
// need to do superclass processing first so inDocument() is true
// by the time we reach updateId
NodeBaseImpl::insertedIntoDocument();
if (hasID()) {
NamedAttrMapImpl *attrs = attributes(true);
if (attrs) {
AttributeImpl *idAttr = attrs->getAttributeItem(ATTR_ID);
if (idAttr && !idAttr->isNull()) {
updateId(nullAtom, idAttr->value());
}
}
}
}
void ElementImpl::removedFromDocument()
{
if (hasID()) {
NamedAttrMapImpl *attrs = namedAttrMap;
if (attrs) {
AttributeImpl *idAttr = attrs->getAttributeItem(ATTR_ID);
if (idAttr && !idAttr->isNull()) {
updateId(idAttr->value(), nullAtom);
}
}
}
NodeBaseImpl::removedFromDocument();
}
void ElementImpl::attach()
{
#if SPEED_DEBUG < 1
createRendererIfNeeded();
#endif
NodeBaseImpl::attach();
}
void ElementImpl::recalcStyle( StyleChange change )
{
// ### should go away and be done in renderobject
RenderStyle* _style = m_render ? m_render->style() : 0;
bool hasParentRenderer = parent() ? parent()->renderer() : false;
#if 0
const char* debug;
switch(change) {
case NoChange: debug = "NoChange";
break;
case NoInherit: debug= "NoInherit";
break;
case Inherit: debug = "Inherit";
break;
case Force: debug = "Force";
break;
}
qDebug("recalcStyle(%d: %s)[%p: %s]", change, debug, this, tagName().string().latin1());
#endif
if ( hasParentRenderer && (change >= Inherit || changed()) ) {
RenderStyle *newStyle = getDocument()->styleSelector()->styleForElement(this);
newStyle->ref();
StyleChange ch = diff( _style, newStyle );
if (ch == Detach) {
if (attached()) detach();
// ### Suboptimal. Style gets calculated again.
attach();
// attach recalulates the style for all children. No need to do it twice.
setChanged( false );
setHasChangedChild( false );
newStyle->deref(getDocument()->renderArena());
return;
}
else if (ch != NoChange) {
if( m_render && newStyle ) {
//qDebug("--> setting style on render element bgcolor=%s", newStyle->backgroundColor().name().latin1());
m_render->setStyle(newStyle);
}
}
else if (changed() && m_render && newStyle && (getDocument()->usesSiblingRules() || getDocument()->usesDescendantRules())) {
// Although no change occurred, we use the new style so that the cousin style sharing code won't get
// fooled into believing this style is the same. This is only necessary if the document actually uses
// sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
// descendants.
m_render->setStyleInternal(newStyle);
}
newStyle->deref(getDocument()->renderArena());
if ( change != Force) {
if (getDocument()->usesDescendantRules())
change = Force;
else
change = ch;
}
}
NodeImpl *n;
for (n = _first; n; n = n->nextSibling()) {
//qDebug(" (%p) calling recalcStyle on child %s/%p, change=%d", this, n, n->isElementNode() ? ((ElementImpl *)n)->tagName().string().latin1() : n->isTextNode() ? "text" : "unknown", change );
if ( change >= Inherit || n->isTextNode() ||
n->hasChangedChild() || n->changed() )
n->recalcStyle( change );
}
setChanged( false );
setHasChangedChild( false );
}
// DOM Section 1.1.1
bool ElementImpl::childAllowed( NodeImpl *newChild )
{
if (!childTypeAllowed(newChild->nodeType()))
return false;
// For XML documents, we are non-validating and do not check against a DTD, even for HTML elements.
if (getDocument()->isHTMLDocument())
return checkChild(id(), newChild->id(), !getDocument()->inCompatMode());
return true;
}
bool ElementImpl::childTypeAllowed( unsigned short type )
{
switch (type) {
case Node::ELEMENT_NODE:
case Node::TEXT_NODE:
case Node::COMMENT_NODE:
case Node::PROCESSING_INSTRUCTION_NODE:
case Node::CDATA_SECTION_NODE:
case Node::ENTITY_REFERENCE_NODE:
return true;
break;
default:
return false;
}
}
void ElementImpl::dispatchAttrRemovalEvent(AttributeImpl *attr)
{
if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
return;
//int exceptioncode = 0;
// dispatchEvent(new MutationEventImpl(EventImpl::DOMATTRMODIFIED_EVENT,true,false,attr,attr->value(),
// attr->value(), getDocument()->attrName(attr->id()),MutationEvent::REMOVAL),exceptioncode);
}
void ElementImpl::dispatchAttrAdditionEvent(AttributeImpl *attr)
{
if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
return;
// int exceptioncode = 0;
// dispatchEvent(new MutationEventImpl(EventImpl::DOMATTRMODIFIED_EVENT,true,false,attr,attr->value(),
// attr->value(),getDocument()->attrName(attr->id()),MutationEvent::ADDITION),exceptioncode);
}
DOMString ElementImpl::openTagStartToString() const
{
DOMString result = DOMString("<") + tagName();
NamedAttrMapImpl *attrMap = attributes(true);
if (attrMap) {
unsigned long numAttrs = attrMap->length();
for (unsigned long i = 0; i < numAttrs; i++) {
result += " ";
AttributeImpl *attribute = attrMap->attributeItem(i);
AttrImpl *attr = attribute->attrImpl();
if (attr) {
result += attr->toString();
} else {
result += getDocument()->attrName(attribute->id());
if (!attribute->value().isNull()) {
result += "=\"";
// FIXME: substitute entities for any instances of " or '
result += attribute->value();
result += "\"";
}
}
}
}
return result;
}
DOMString ElementImpl::toString() const
{
DOMString result = openTagStartToString();
if (hasChildNodes()) {
result += ">";
for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
result += child->toString();
}
result += "</";
result += tagName();
result += ">";
} else {
result += " />";
}
return result;
}
void ElementImpl::updateId(const AtomicString& oldId, const AtomicString& newId)
{
if (!inDocument())
return;
if (oldId == newId)
return;
DocumentImpl* doc = getDocument();
if (!oldId.isEmpty())
doc->removeElementById(oldId, this);
if (!newId.isEmpty())
doc->addElementById(newId, this);
}
#ifndef NDEBUG
void ElementImpl::dump(QTextStream *stream, QString ind) const
{
updateStyleAttributeIfNeeded();
if (namedAttrMap) {
for (uint i = 0; i < namedAttrMap->length(); i++) {
AttributeImpl *attr = namedAttrMap->attributeItem(i);
*stream << " " << DOMString(getDocument()->attrName(attr->id())).string().ascii()
<< "=\"" << DOMString(attr->value()).string().ascii() << "\"";
}
}
NodeBaseImpl::dump(stream,ind);
}
#endif
#ifndef NDEBUG
void ElementImpl::formatForDebugger(char *buffer, unsigned length) const
{
DOMString result;
DOMString s;
s = nodeName();
if (s.length() > 0) {
result += s;
}
s = getAttribute(ATTR_ID);
if (s.length() > 0) {
if (result.length() > 0)
result += "; ";
result += "id=";
result += s;
}
s = getAttribute(ATTR_CLASS);
if (s.length() > 0) {
if (result.length() > 0)
result += "; ";
result += "class=";
result += s;
}
strncpy(buffer, result.string().latin1(), length - 1);
}
#endif
// -------------------------------------------------------------------------
XMLElementImpl::XMLElementImpl(DocumentPtr *doc, DOMStringImpl *_tagName)
: ElementImpl(doc)
{
m_id = doc->document()->tagId(0 /* no namespace */, _tagName, false /* allocate */);
}
XMLElementImpl::XMLElementImpl(DocumentPtr *doc, DOMStringImpl *_qualifiedName, DOMStringImpl *_namespaceURI)
: ElementImpl(doc)
{
int colonpos = -1;
for (uint i = 0; i < _qualifiedName->l; ++i)
if (_qualifiedName->s[i] == ':') {
colonpos = i;
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -