📄 dom_elementimpl.cpp
字号:
/**
* This file is part of the DOM implementation for KDE.
*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Peter Kelly (pmk@post.com)
* (C) 2001 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
//#define EVENT_DEBUG
#include "dom/dom_exception.h"
#include "dom/dom_node.h"
#include "xml/dom_textimpl.h"
#include "xml/dom_docimpl.h"
#include "xml/dom2_eventsimpl.h"
#include "xml/dom_elementimpl.h"
#include "khtml_part.h"
#include "khtmlview.h"
#include "html/dtd.h"
#include "html/htmlparser.h"
#include "rendering/render_canvas.h"
#include "misc/htmlhashes.h"
#include "css/css_valueimpl.h"
#include "css/css_stylesheetimpl.h"
#include "css/cssstyleselector.h"
#include "xml/dom_xmlimpl.h"
#include <qtextstream.h>
#include <kdebug.h>
using namespace DOM;
using namespace khtml;
AttributeImpl* AttributeImpl::clone(bool) const
{
AttributeImpl* result = new AttributeImpl(m_id, _value);
result->setPrefix(_prefix);
return result;
}
void AttributeImpl::allocateImpl(ElementImpl* e) {
_impl = new AttrImpl(e, e->docPtr(), this);
}
AttrImpl::AttrImpl(ElementImpl* element, DocumentPtr* docPtr, AttributeImpl* a)
: NodeBaseImpl(docPtr),
m_element(element),
m_attribute(a)
{
assert(!m_attribute->_impl);
m_attribute->_impl = this;
m_attribute->ref();
m_specified = true;
}
AttrImpl::~AttrImpl()
{
assert(m_attribute->_impl == this);
m_attribute->_impl = 0;
m_attribute->deref();
}
DOMString AttrImpl::nodeName() const
{
return getDocument()->attrName(m_attribute->id());
}
unsigned short AttrImpl::nodeType() const
{
return Node::ATTRIBUTE_NODE;
}
DOMString AttrImpl::prefix() const
{
return m_attribute->prefix();
}
void AttrImpl::setPrefix(const DOMString &_prefix, int &exceptioncode )
{
checkSetPrefix(_prefix, exceptioncode);
if (exceptioncode)
return;
m_attribute->setPrefix(_prefix.implementation());
}
DOMString AttrImpl::nodeValue() const {
return m_attribute->value();
}
void AttrImpl::setValue( const DOMString &v, int &exceptioncode )
{
exceptioncode = 0;
// ### according to the DOM docs, we should create an unparsed Text child
// node here
// do not interprete entities in the string, its literal!
// NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
if (isReadOnly()) {
exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
return;
}
// ### what to do on 0 ?
if (v.isNull()) {
exceptioncode = DOMException::DOMSTRING_SIZE_ERR;
return;
}
m_attribute->setValue(v.implementation());
if (m_element)
m_element->attributeChanged(m_attribute);
}
void AttrImpl::setNodeValue( const DOMString &v, int &exceptioncode )
{
exceptioncode = 0;
// NO_MODIFICATION_ALLOWED_ERR: taken care of by setValue()
setValue(v, exceptioncode);
}
NodeImpl *AttrImpl::cloneNode ( bool /*deep*/)
{
return new AttrImpl(0, docPtr(), m_attribute->clone());
}
// DOM Section 1.1.1
bool AttrImpl::childAllowed( NodeImpl *newChild )
{
if(!newChild)
return false;
return childTypeAllowed(newChild->nodeType());
}
bool AttrImpl::childTypeAllowed( unsigned short type )
{
switch (type) {
case Node::TEXT_NODE:
case Node::ENTITY_REFERENCE_NODE:
return true;
break;
default:
return false;
}
}
DOMString AttrImpl::toString() const
{
DOMString result;
result += nodeName();
// FIXME: substitute entities for any instances of " or ' --
// maybe easier to just use text value and ignore existing
// entity refs?
if (firstChild() != NULL) {
result += "=\"";
for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
result += child->toString();
}
result += "\"";
}
return result;
}
// -------------------------------------------------------------------------
ElementImpl::ElementImpl(DocumentPtr *doc)
: NodeBaseImpl(doc)
{
namedAttrMap = 0;
m_prefix = 0;
}
ElementImpl::~ElementImpl()
{
if (namedAttrMap) {
namedAttrMap->detachFromElement();
namedAttrMap->deref();
}
if (m_prefix)
m_prefix->deref();
}
void ElementImpl::removeAttribute( NodeImpl::Id id, int &exceptioncode )
{
if (namedAttrMap) {
namedAttrMap->removeNamedItem(id, exceptioncode);
if (exceptioncode == DOMException::NOT_FOUND_ERR) {
exceptioncode = 0;
}
}
}
void ElementImpl::setAttribute(NodeImpl::Id id, const DOMString &value)
{
int exceptioncode = 0;
setAttribute(id,value.implementation(),exceptioncode);
}
NamedAttrMapImpl* ElementImpl::attributes(bool readonly) const
{
updateStyleAttributeIfNeeded();
if (!readonly && !namedAttrMap) createAttributeMap();
return namedAttrMap;
}
unsigned short ElementImpl::nodeType() const
{
return Node::ELEMENT_NODE;
}
const AtomicStringList* ElementImpl::getClassList() const
{
return 0;
}
const AtomicString& ElementImpl::getIDAttribute() const
{
return namedAttrMap ? namedAttrMap->id() : nullAtom;
}
const AtomicString& ElementImpl::getAttribute(NodeImpl::Id id) const
{
if (id == ATTR_STYLE)
updateStyleAttributeIfNeeded();
if (namedAttrMap) {
AttributeImpl* a = namedAttrMap->getAttributeItem(id);
if (a) return a->value();
}
return nullAtom;
}
void ElementImpl::scrollIntoView(bool alignToTop)
{
QRect bounds = this->getRect();
if (m_render && m_render->enclosingLayer()) {
if (alignToTop)
m_render->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
else
m_render->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignBottomAlways);
}
}
void ElementImpl::focus()
{
DocumentImpl *doc = getDocument();
if (doc) {
doc->updateLayout();
if (isFocusable() && renderer()) {
doc->setFocusNode(this);
renderer()->enclosingLayer()->scrollRectToVisible(getRect());
}
}
}
void ElementImpl::blur()
{
DocumentImpl* doc = getDocument();
if (doc && doc->focusNode() == this)
doc->setFocusNode(0);
}
const AtomicString& ElementImpl::getAttributeNS(const DOMString &namespaceURI,
const DOMString &localName) const
{
NodeImpl::Id id = getDocument()->attrId(namespaceURI.implementation(),
localName.implementation(), true);
if (!id) return nullAtom;
return getAttribute(id);
}
void ElementImpl::setAttribute(NodeImpl::Id id, DOMStringImpl* value, int &exceptioncode )
{
if (inDocument())
getDocument()->incDOMTreeVersion();
// allocate attributemap if necessary
AttributeImpl* old = attributes(false)->getAttributeItem(id);
// NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
if (namedAttrMap->isReadOnly()) {
exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
return;
}
if (id == ATTR_ID) {
updateId(old ? old->value() : nullAtom, value);
}
if (old && !value)
namedAttrMap->removeAttribute(id);
else if (!old && value)
namedAttrMap->addAttribute(createAttribute(id, value));
else if (old && value) {
old->setValue(value);
attributeChanged(old);
}
}
AttributeImpl* ElementImpl::createAttribute(NodeImpl::Id id, DOMStringImpl* value)
{
return new AttributeImpl(id, value);
}
void ElementImpl::setAttributeMap( NamedAttrMapImpl* list )
{
if (inDocument())
getDocument()->incDOMTreeVersion();
// If setting the whole map changes the id attribute, we need to
// call updateId.
AttributeImpl *oldId = namedAttrMap ? namedAttrMap->getAttributeItem(ATTR_ID) : 0;
AttributeImpl *newId = list ? list->getAttributeItem(ATTR_ID) : 0;
if (oldId || newId) {
updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
}
if(namedAttrMap)
namedAttrMap->deref();
namedAttrMap = list;
if(namedAttrMap) {
namedAttrMap->ref();
namedAttrMap->element = this;
unsigned int len = namedAttrMap->length();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -