dom_element.cpp
00001 00023 #include "dom/dom_exception.h" 00024 #include "xml/dom_docimpl.h" 00025 #include "xml/dom_elementimpl.h" 00026 #include "html/html_formimpl.h" 00027 00028 using namespace DOM; 00029 00030 Attr::Attr() : Node() 00031 { 00032 } 00033 00034 Attr::Attr(const Attr &other) : Node(other) 00035 { 00036 } 00037 00038 Attr::Attr( AttrImpl *_impl ) 00039 { 00040 impl= _impl; 00041 if (impl) impl->ref(); 00042 } 00043 00044 Attr &Attr::operator = (const Node &other) 00045 { 00046 NodeImpl* ohandle = other.handle(); 00047 if ( impl != ohandle ) { 00048 if (!ohandle || !ohandle->isAttributeNode()) { 00049 if (impl) impl->deref(); 00050 impl = 0; 00051 } else { 00052 Node::operator =(other); 00053 } 00054 } 00055 return *this; 00056 } 00057 00058 Attr &Attr::operator = (const Attr &other) 00059 { 00060 Node::operator =(other); 00061 return *this; 00062 } 00063 00064 Attr::~Attr() 00065 { 00066 } 00067 00068 DOMString Attr::name() const 00069 { 00070 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00071 return ((AttrImpl *)impl)->name(); 00072 } 00073 00074 bool Attr::specified() const 00075 { 00076 if (impl) return ((AttrImpl *)impl)->specified(); 00077 return 0; 00078 } 00079 00080 Element Attr::ownerElement() const 00081 { 00082 if (!impl) return 0; 00083 return static_cast<AttrImpl*>(impl)->ownerElement(); 00084 } 00085 00086 DOMString Attr::value() const 00087 { 00088 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00089 return impl->nodeValue(); 00090 } 00091 00092 void Attr::setValue( const DOMString &newValue ) 00093 { 00094 if (!impl) 00095 return; 00096 00097 int exceptioncode = 0; 00098 ((AttrImpl *)impl)->setValue(newValue,exceptioncode); 00099 if (exceptioncode) 00100 throw DOMException(exceptioncode); 00101 } 00102 00103 // --------------------------------------------------------------------------- 00104 00105 Element::Element() : Node() 00106 { 00107 } 00108 00109 Element::Element(const Element &other) : Node(other) 00110 { 00111 } 00112 00113 Element::Element(ElementImpl *impl) : Node(impl) 00114 { 00115 } 00116 00117 Element &Element::operator = (const Node &other) 00118 { 00119 NodeImpl* ohandle = other.handle(); 00120 if ( impl != ohandle ) { 00121 if (!ohandle || !ohandle->isElementNode()) { 00122 if (impl) impl->deref(); 00123 impl = 0; 00124 } else { 00125 Node::operator =(other); 00126 } 00127 } 00128 return *this; 00129 } 00130 00131 Element &Element::operator = (const Element &other) 00132 { 00133 Node::operator =(other); 00134 return *this; 00135 } 00136 00137 Element::~Element() 00138 { 00139 } 00140 00141 DOMString Element::tagName() const 00142 { 00143 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00144 return static_cast<ElementImpl*>(impl)->tagName(); 00145 } 00146 00147 DOMString Element::getAttribute( const DOMString &name ) 00148 { 00149 // ### getAttribute() and getAttributeNS() are supposed to return the empty string if the attribute 00150 // does not exist. However, there are a number of places around khtml that expect a null string 00151 // for nonexistent attributes. These need to be changed to use hasAttribute() instead. 00152 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00153 if (!name.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR); 00154 00155 NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId,name.implementation(),true,true); 00156 if (!id) return DOMString(); 00157 00158 ElementImpl* e = static_cast<ElementImpl*>(impl); 00159 return e->getAttribute(id, false, name); 00160 } 00161 00162 void Element::setAttribute( const DOMString &name, const DOMString &value ) 00163 { 00164 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00165 int exceptioncode = 0; 00166 NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), false /* allocate */, 00167 true, &exceptioncode); 00168 00169 static_cast<ElementImpl*>(impl)->setAttribute(id, value, name, exceptioncode); 00170 if ( exceptioncode ) 00171 throw DOMException( exceptioncode ); 00172 } 00173 00174 void Element::removeAttribute( const DOMString &name ) 00175 { 00176 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00177 NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), true, true); 00178 if (!id) return; 00179 00180 int exceptioncode = 0; 00181 NamedNodeMapImpl *attributes = static_cast<ElementImpl*>(impl)->attributes(false); 00182 attributes->removeNamedItem(id, false, name.implementation(), exceptioncode); 00183 // it's allowed to remove attributes that don't exist. 00184 if ( exceptioncode && exceptioncode != DOMException::NOT_FOUND_ERR ) 00185 throw DOMException( exceptioncode ); 00186 } 00187 00188 Attr Element::getAttributeNode( const DOMString &name ) 00189 { 00190 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00191 if (!name.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR); 00192 NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), true, true); 00193 if (!id) return 0; 00194 00195 ElementImpl* e = static_cast<ElementImpl*>(impl); 00196 if (!e->attributes()) return 0; 00197 00198 return static_cast<AttrImpl*>(e->attributes()->getNamedItem(id, false, name.implementation())); 00199 } 00200 00201 Attr Element::setAttributeNode( const Attr &newAttr ) 00202 { 00203 if (!impl || newAttr.isNull()) 00204 throw DOMException(DOMException::NOT_FOUND_ERR); 00205 // WRONG_DOCUMENT_ERR and INUSE_ATTRIBUTE_ERR are already tested & thrown by setNamedItem 00206 00207 int exceptioncode = 0; 00208 Attr r = static_cast<ElementImpl*>(impl)->attributes(false)->setNamedItem(newAttr.handle(), false, 00209 newAttr.handle()->nodeName().implementation(), exceptioncode); 00210 if ( exceptioncode ) 00211 throw DOMException( exceptioncode ); 00212 static_cast<AttrImpl *>(newAttr.handle())->setOwnerElement( static_cast<ElementImpl*>(impl) ); 00213 return r; 00214 } 00215 00216 Attr Element::removeAttributeNode( const Attr &oldAttr ) 00217 { 00218 if (!impl || oldAttr.isNull() || oldAttr.ownerElement().handle() != impl) 00219 throw DOMException(DOMException::NOT_FOUND_ERR); 00220 00221 if (impl->isReadOnly()) 00222 throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR); 00223 00224 if (!static_cast<ElementImpl*>(impl)->attributes(true)) 00225 throw DOMException(DOMException::NOT_FOUND_ERR); 00226 00227 NamedAttrMapImpl *attributes = static_cast<ElementImpl*>(impl)->attributes(false); 00228 return attributes->removeAttr(static_cast<AttrImpl*>(static_cast<AttrImpl*>(oldAttr.handle()))); 00229 } 00230 00231 NodeList Element::getElementsByTagName( const DOMString &tagName ) 00232 { 00233 if (!impl) return 0; 00234 NodeImpl::Id id; 00235 if ( tagName == "*" ) 00236 id = 0; 00237 else 00238 id = impl->getDocument()->getId(NodeImpl::ElementId, tagName.implementation(), false, true); 00239 return new TagNodeListImpl( impl, id ); 00240 } 00241 00242 NodeList Element::getElementsByTagNameNS( const DOMString &namespaceURI, 00243 const DOMString &localName ) 00244 { 00245 if (!impl) return 0; 00246 return new TagNodeListImpl( impl, namespaceURI, localName ); 00247 } 00248 00249 DOMString Element::getAttributeNS( const DOMString &namespaceURI, 00250 const DOMString &localName) 00251 { 00252 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00253 if (!localName.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR); 00254 NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, namespaceURI.implementation(), 0/*prefix*/, localName.implementation(), true, true); 00255 ElementImpl* e = static_cast<ElementImpl*>(impl); 00256 return e->getAttribute(id, true); 00257 } 00258 00259 void Element::setAttributeNS( const DOMString &namespaceURI, 00260 const DOMString &qualifiedName, 00261 const DOMString &value) 00262 { 00263 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00264 00265 int exceptioncode = 0; 00266 static_cast<ElementImpl*>(impl)->setAttributeNS(namespaceURI, qualifiedName, value, exceptioncode); 00267 if ( exceptioncode ) 00268 throw DOMException( exceptioncode ); 00269 } 00270 00271 void Element::removeAttributeNS( const DOMString &namespaceURI, 00272 const DOMString &localName ) 00273 { 00274 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00275 00276 int exceptioncode = 0; 00277 NamedNodeMapImpl *attributes = static_cast<ElementImpl*>(impl)->attributes(false); 00278 NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, namespaceURI.implementation(), 0/*prefix*/, localName.implementation(), false, true); 00279 attributes->removeNamedItem(id, true, 0, exceptioncode); 00280 if ( exceptioncode ) 00281 throw DOMException( exceptioncode ); 00282 } 00283 00284 Attr Element::getAttributeNodeNS( const DOMString &namespaceURI, 00285 const DOMString &localName ) 00286 { 00287 if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR); 00288 if (!localName.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR); 00289 NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, namespaceURI.implementation(), 00290 0/*prefix*/, localName.implementation(), true, true); 00291 ElementImpl* e = static_cast<ElementImpl*>(impl); 00292 if (!e->attributes()) return 0; 00293 00294 return static_cast<AttrImpl*>(e->attributes()->getNamedItem(id, true)); 00295 } 00296 00297 Attr Element::setAttributeNodeNS( const Attr &newAttr ) 00298 { 00299 if (!impl || newAttr.isNull()) 00300 throw DOMException(DOMException::NOT_FOUND_ERR); 00301 // WRONG_DOCUMENT_ERR and INUSE_ATTRIBUTE_ERR are already tested & thrown by setNamedItem 00302 00303 int exceptioncode = 0; 00304 Attr r = static_cast<ElementImpl*>(impl)->attributes(false)->setNamedItem(newAttr.handle(), true, 0, exceptioncode); 00305 if ( exceptioncode ) 00306 throw DOMException( exceptioncode ); 00307 static_cast<AttrImpl *>(newAttr.handle())->setOwnerElement( static_cast<ElementImpl*>(impl) ); 00308 return r; 00309 } 00310 00311 00312 bool Element::hasAttribute( const DOMString& name ) 00313 { 00314 if (!impl || !static_cast<ElementImpl*>(impl)->attributes()) return false; // ### throw ? 00315 NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), true, true); 00316 if (!id) return false; 00317 00318 if (!static_cast<ElementImpl*>(impl)->attributes(true /*readonly*/)) return false; 00319 return static_cast<ElementImpl*>(impl)->attributes(true)->getValue(id, false, name.implementation()) != 0; 00320 } 00321 00322 bool Element::hasAttributeNS( const DOMString &namespaceURI, 00323 const DOMString &localName ) 00324 { 00325 if (!impl || !static_cast<ElementImpl*>(impl)->attributes()) return false; // ### throw ? 00326 if (!static_cast<ElementImpl*>(impl)->attributes(true /*readonly*/)) return false; 00327 NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId,namespaceURI.implementation(), 00328 0/*prefix*/, localName.implementation(), true, true); 00329 return static_cast<ElementImpl*>(impl)->attributes(true)->getValue(id, true) != 0; 00330 } 00331 00332 bool Element::isHTMLElement() const 00333 { 00334 if(!impl) return false; 00335 return ((ElementImpl *)impl)->isHTMLElement(); 00336 } 00337 00338 Element Element::form() const 00339 { 00340 if (!impl || !impl->isGenericFormElement()) return 0; 00341 return static_cast<HTMLGenericFormElementImpl*>(impl)->form(); 00342 ElementImpl* f = static_cast<HTMLGenericFormElementImpl*>( impl )->form(); 00343 00344 if( f && f->implicitNode() ) 00345 return 0; 00346 return f; 00347 } 00348 00349 CSSStyleDeclaration Element::style() 00350 { 00351 if (impl) return ((ElementImpl *)impl)->styleRules(); 00352 return 0; 00353 } 00354 00355 bool Element::contentEditable() const { 00356 if(!impl) return false; 00357 return static_cast<ElementImpl *>(impl)->contentEditable(); 00358 } 00359 00360 void Element::setContentEditable(bool enabled) { 00361 if(!impl) 00362 throw DOMException(DOMException::INVALID_STATE_ERR); 00363 00364 static_cast<ElementImpl *>(impl)->setContentEditable(enabled); 00365 } 00366 00367 bool Element::khtmlValidAttrName(const DOMString &name) 00368 { 00369 // Check if name is valid 00370 // http://www.w3.org/TR/2000/REC-xml-20001006#NT-Name 00371 DOMStringImpl* _name = name.implementation(); 00372 QChar ch = _name->s[0]; 00373 if ( !ch.isLetter() && ch != '_' && ch != ':' ) 00374 return false; // first char isn't valid 00375 for ( uint i = 0; i < _name->l; ++i ) 00376 { 00377 ch = _name->s[i]; 00378 if ( !ch.isLetter() && !ch.isDigit() && ch != '.' 00379 && ch != '-' && ch != '_' && ch != ':' 00380 && ch.category() != QChar::Mark_SpacingCombining 00381 /* no idea what "extender is" */ ) 00382 return false; 00383 } 00384 return true; 00385 } 00386 00387 bool Element::khtmlValidPrefix(const DOMString &name) 00388 { 00389 // Null prefix is ok. If not null, reuse code from khtmlValidAttrName 00390 return !name.implementation() || khtmlValidAttrName(name); 00391 } 00392 00393 bool Element::khtmlValidQualifiedName(const DOMString &name) 00394 { 00395 return khtmlValidAttrName(name); 00396 } 00397 00398 bool Element::khtmlMalformedQualifiedName(const DOMString &name) 00399 { 00400 // #### Not clearly defined in the DOM spec... 00401 // But we know for sure that a null qualified name is malformed 00402 return name.isNull(); 00403 } 00404 00405 bool Element::khtmlMalformedPrefix(const DOMString &/*name*/) 00406 { 00407 // #### 00408 return false; 00409 }