Bug 133570

Summary: [test case] Removal of attribute using DOM not reflected in CSS
Product: [Applications] konqueror Reporter: Claus Rasmussen <bugs.kde.org>
Component: khtml rendererAssignee: Konqueror Developers <konq-bugs>
Status: RESOLVED FIXED    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: Test case
Test case source

Description Claus Rasmussen 2006-09-05 00:09:58 UTC
Version:           3.5.4-2.1.fc4.kde (using KDE 3.5.4-1.1.fc4.kde, Fedora Core release 4 (Stentz))
Compiler:          Target: i386-redhat-linux
OS:                Linux (i686) release 2.6.17-1.2142_FC4smp

If you have a CSS styling of a tag that depends on the presence of an attribute that style sticks even if the attribute is removed: 

    div.test_presence {
        <default-properties>;
    }

    div.test_presence[attribute] {
        <modified-properties>
    }

Initially a DIV will be displayed with the default properties. Adding 'attribute' using setAttribute will display the DIV with the modified properties, but removing it again will not make the DIV change back to the default again.

Adding a value to the attribute and modifying that value instead of adding/removing the attribute works however.
Comment 1 Claus Rasmussen 2006-09-05 00:11:11 UTC
Created attachment 17638 [details]
Test case
Comment 2 Claus Rasmussen 2006-09-05 00:12:59 UTC
Created attachment 17639 [details]
Test case source
Comment 3 Allan Sandfeld 2006-09-05 12:11:58 UTC
SVN commit 581101 by carewolf:

Call attributeChanged to changes in attr-nodes or the attrNodeMap instead
of in setAttribute. This catches many more types of attribute changes.
BUG:133570


 M  +15 -6     dom_elementimpl.cpp  


--- branches/KDE/3.5/kdelibs/khtml/xml/dom_elementimpl.cpp #581100:581101
@@ -175,8 +175,10 @@
     m_value = v.implementation();
     m_value->ref();
 
-    if (m_element)
+    if (m_element) {
         m_element->parseAttribute(m_attrId,m_value);
+        m_element->attributeChanged(m_attrId);
+    }
 }
 
 void AttrImpl::setNodeValue( const DOMString &v, int &exceptioncode )
@@ -263,8 +265,10 @@
 	m_data.value = value;
 	m_data.value->ref();
 
-	if (element)
+	if (element) {
 	    element->parseAttribute(this);
+	    element->attributeChanged(m_attrId);
+        }
     }
     else {
 	int exceptioncode = 0;
@@ -362,7 +366,6 @@
         return;
     }
     attributes()->setValue(id, value.implementation(), (qName.isEmpty() ? 0: qName.implementation()));
-    attributeChanged(id);
 }
 
 void ElementImpl::setAttributeNS( const DOMString &namespaceURI, const DOMString &qualifiedName,
@@ -384,14 +387,12 @@
                             prefix.implementation(), localName.implementation(), false, true /*lookupHTML*/);
     attributes()->setValue(id, value.implementation(), 0, prefix.implementation(),
                            true /*nsAware*/, !namespaceURI.isNull() /*hasNS*/);
-    attributeChanged(id);
 }
 
 void ElementImpl::setAttribute(NodeImpl::Id id, const DOMString &value)
 {
     int exceptioncode = 0;
     setAttribute(id,value,DOMString(),exceptioncode);
-    attributeChanged(id);
 }
 
 void ElementImpl::setAttributeMap( NamedAttrMapImpl* list )
@@ -417,8 +418,10 @@
         assert(namedAttrMap->m_element == 0);
         namedAttrMap->setElement(this);
         unsigned long len = namedAttrMap->length();
-        for (unsigned long i = 0; i < len; i++)
+        for (unsigned long i = 0; i < len; i++) {
             parseAttribute(&namedAttrMap->m_attrs[i]);
+            attributeChanged(namedAttrMap->m_attrs[i].id());
+        }
     }
 }
 
@@ -994,6 +997,7 @@
 	    m_attrCount--;
 	    m_attrs = (AttributeImpl*)realloc(m_attrs,m_attrCount*sizeof(AttributeImpl));
 	    m_element->parseAttribute(id,0);
+	    m_element->attributeChanged(id);
 	    return removed;
 	}
     }
@@ -1062,6 +1066,7 @@
 	    m_attrs[i].m_data.attr->ref();
 	    attr->setElement(m_element);
 	    m_element->parseAttribute(&m_attrs[i]);
+	    m_element->attributeChanged(m_attrs[i].id());
 	    // ### dispatch mutation events
 	    return replaced;
 	}
@@ -1077,6 +1082,7 @@
     if (id == ATTR_ID)
         m_element->updateId(0, attr->val());
     m_element->parseAttribute(&m_attrs[m_attrCount-1]);
+    m_element->attributeChanged(m_attrs[m_attrCount-1].id());
     // ### dispatch mutation events
 
     return 0;
@@ -1184,6 +1190,7 @@
 	if (id == ATTR_ID)
 	    m_element->updateId(0, value);
 	m_element->parseAttribute(&m_attrs[m_attrCount-1]);
+	m_element->attributeChanged(m_attrs[m_attrCount-1].id());
     }
     // ### dispatch mutation events
 }
@@ -1201,6 +1208,7 @@
 	    m_attrCount--;
 	    m_attrs = (AttributeImpl*)realloc(m_attrs,m_attrCount*sizeof(AttributeImpl));
 	    m_element->parseAttribute(id,0);
+	    m_element->attributeChanged(id);
 	    // ### dispatch mutation events
 	    return removed;
 	}
@@ -1244,6 +1252,7 @@
 	if (m_attrs[i].id() == ATTR_ID)
 	   m_element->updateId(0, m_attrs[i].val());
 	m_element->parseAttribute(&m_attrs[i]);
+	m_element->attributeChanged(m_attrs[i].id());
     }
 }