📄 html_elementimpl.cpp
字号:
// the following is in accordance with the definition as used by IE
if( endTagRequirement(id()) == FORBIDDEN )
return NULL;
// IE disallows innerHTML on inline elements. I don't see why we should have this restriction, as our
// dhtml engine can cope with it. Lars
//if ( isInline() ) return false;
switch( id() ) {
case ID_COL:
case ID_COLGROUP:
case ID_FRAMESET:
case ID_HEAD:
case ID_STYLE:
case ID_TITLE:
return NULL;
default:
break;
}
if ( !getDocument()->isHTMLDocument() )
return NULL;
DocumentFragmentImpl *fragment = new DocumentFragmentImpl( docPtr() );
fragment->ref();
{
HTMLTokenizer tok(docPtr(), fragment);
tok.setForceSynchronous(true); // disable asynchronous parsing
tok.write( html.string(), true );
tok.finish();
assert(!tok.processingData()); // make sure we're done (see 3963151)
}
// Exceptions are ignored because none ought to happen here.
int ignoredExceptionCode;
// we need to pop <html> and <body> elements and remove <head> to
// accomadate folks passing complete HTML documents to make the
// child of an element.
NodeImpl *nextNode;
for (NodeImpl *node = fragment->firstChild(); node != NULL; node = nextNode) {
nextNode = node->nextSibling();
node->ref();
if (node->id() == ID_HTML || node->id() == ID_BODY) {
NodeImpl *firstChild = node->firstChild();
if (firstChild != NULL) {
nextNode = firstChild;
}
NodeImpl *nextChild;
for (NodeImpl *child = firstChild; child != NULL; child = nextChild) {
nextChild = child->nextSibling();
child->ref();
node->removeChild(child, ignoredExceptionCode);
fragment->insertBefore(child, node, ignoredExceptionCode);
child->deref();
}
fragment->removeChild(node, ignoredExceptionCode);
} else if (node->id() == ID_HEAD) {
fragment->removeChild(node, ignoredExceptionCode);
}
// Important to do this deref after removeChild, because if the only thing
// keeping a node around is a parent that is non-0, removeChild will not
// delete the node. This works fine in JavaScript because there's always
// a ref of the node, but here in C++ we need to do it explicitly.
node->deref();
}
// Trick to get the fragment back to the floating state, with 0
// refs but not destroyed.
fragment->setParent(this);
fragment->deref();
fragment->setParent(0);
return fragment;
}
bool HTMLElementImpl::setInnerHTML( const DOMString &html )
{
DocumentFragmentImpl *fragment = createContextualFragment( html );
if (fragment == NULL) {
return false;
}
removeChildren();
int ec = 0;
appendChild( fragment, ec );
return !ec;
}
bool HTMLElementImpl::setOuterHTML( const DOMString &html )
{
DocumentFragmentImpl *fragment = createContextualFragment( html );
if (fragment == NULL) {
return false;
}
int ec = 0;
if (parentNode()) {
parentNode()->replaceChild(fragment, this, ec);
}
return !ec;
}
bool HTMLElementImpl::setInnerText( const DOMString &text )
{
// following the IE specs.
if( endTagRequirement(id()) == FORBIDDEN )
return false;
// IE disallows innerText on inline elements. I don't see why we should have this restriction, as our
// dhtml engine can cope with it. Lars
//if ( isInline() ) return false;
switch( id() ) {
case ID_COL:
case ID_COLGROUP:
case ID_FRAMESET:
case ID_HEAD:
case ID_HTML:
case ID_TABLE:
case ID_TBODY:
case ID_TFOOT:
case ID_THEAD:
case ID_TR:
return false;
default:
break;
}
removeChildren();
TextImpl *t = new TextImpl( docPtr(), text );
int ec = 0;
appendChild( t, ec );
if ( !ec )
return true;
return false;
}
bool HTMLElementImpl::setOuterText( const DOMString &text )
{
// following the IE specs.
if( endTagRequirement(id()) == FORBIDDEN )
return false;
switch( id() ) {
case ID_COL:
case ID_COLGROUP:
case ID_FRAMESET:
case ID_HEAD:
case ID_HTML:
case ID_TABLE:
case ID_TBODY:
case ID_TFOOT:
case ID_THEAD:
case ID_TR:
return false;
default:
break;
}
NodeBaseImpl *parent = static_cast<NodeBaseImpl *>(parentNode());
if (!parent) {
return false;
}
TextImpl *t = new TextImpl( docPtr(), text );
int ec = 0;
parent->replaceChild(t, this, ec);
if ( ec )
return false;
// is previous node a text node? if so, merge into it
NodeImpl *prev = t->previousSibling();
if (prev && prev->isTextNode()) {
TextImpl *textPrev = static_cast<TextImpl *>(prev);
textPrev->appendData(t->data(), ec);
t->parentNode()->removeChild(t, ec);
t = textPrev;
}
if ( ec )
return false;
// is next node a text node? if so, merge it in
NodeImpl *next = t->nextSibling();
if (next && next->isTextNode()) {
TextImpl *textNext = static_cast<TextImpl *>(next);
t->appendData(textNext->data(), ec);
textNext->parentNode()->removeChild(textNext, ec);
}
if ( ec )
return false;
return true;
}
DOMString HTMLElementImpl::namespaceURI() const
{
// For HTML documents, we treat HTML elements as having no namespace. But for XML documents
// the elements have the namespace defined in the XHTML spec
if (getDocument()->isHTMLDocument())
return DOMString();
else
return XHTML_NAMESPACE;
}
void HTMLElementImpl::addHTMLAlignment(HTMLAttributeImpl* attr)
{
//qDebug("alignment is %s", alignment.string().latin1() );
// vertical alignment with respect to the current baseline of the text
// right or left means floating images
int propfloat = -1;
int propvalign = -1;
const AtomicString& alignment = attr->value();
if ( strcasecmp( alignment, "absmiddle" ) == 0 ) {
propvalign = CSS_VAL_MIDDLE;
} else if ( strcasecmp( alignment, "absbottom" ) == 0 ) {
propvalign = CSS_VAL_BOTTOM;
} else if ( strcasecmp( alignment, "left" ) == 0 ) {
propfloat = CSS_VAL_LEFT;
propvalign = CSS_VAL_TOP;
} else if ( strcasecmp( alignment, "right" ) == 0 ) {
propfloat = CSS_VAL_RIGHT;
propvalign = CSS_VAL_TOP;
} else if ( strcasecmp( alignment, "top" ) == 0 ) {
propvalign = CSS_VAL_TOP;
} else if ( strcasecmp( alignment, "middle" ) == 0 ) {
propvalign = CSS_VAL__KHTML_BASELINE_MIDDLE;
} else if ( strcasecmp( alignment, "center" ) == 0 ) {
propvalign = CSS_VAL_MIDDLE;
} else if ( strcasecmp( alignment, "bottom" ) == 0 ) {
propvalign = CSS_VAL_BASELINE;
} else if ( strcasecmp ( alignment, "texttop") == 0 ) {
propvalign = CSS_VAL_TEXT_TOP;
}
if ( propfloat != -1 )
addCSSProperty( attr, CSS_PROP_FLOAT, propfloat );
if ( propvalign != -1 )
addCSSProperty( attr, CSS_PROP_VERTICAL_ALIGN, propvalign );
}
bool HTMLElementImpl::isFocusable() const
{
return isContentEditable() && parent() && !parent()->isContentEditable();
}
bool HTMLElementImpl::isContentEditable() const
{
if (getDocument()->part() && getDocument()->part()->isContentEditable())
return true;
getDocument()->updateRendering();
if (!renderer()) {
if (parentNode())
return parentNode()->isContentEditable();
else
return false;
}
return renderer()->style()->userModify() == READ_WRITE;
}
DOMString HTMLElementImpl::contentEditable() const
{
getDocument()->updateRendering();
if (!renderer())
return "false";
switch (renderer()->style()->userModify()) {
case READ_WRITE:
return "true";
case READ_ONLY:
return "false";
default:
return "inherit";
}
return "inherit";
}
void HTMLElementImpl::setContentEditable(HTMLAttributeImpl* attr)
{
KHTMLPart *part = getDocument()->part();
const AtomicString& enabled = attr->value();
if (enabled.isEmpty() || strcasecmp(enabled, "true") == 0) {
addCSSProperty(attr, CSS_PROP__KHTML_USER_MODIFY, CSS_VAL_READ_WRITE);
if (part)
part->applyEditingStyleToElement(this);
}
else if (strcasecmp(enabled, "false") == 0) {
addCSSProperty(attr, CSS_PROP__KHTML_USER_MODIFY, CSS_VAL_READ_ONLY);
if (part)
part->removeEditingStyleFromElement(this);
}
else if (strcasecmp(enabled, "inherit") == 0) {
addCSSProperty(attr, CSS_PROP__KHTML_USER_MODIFY, CSS_VAL_INHERIT);
if (part)
part->removeEditingStyleFromElement(this);
}
}
void HTMLElementImpl::setContentEditable(const DOMString &enabled) {
if (enabled == "inherit") {
int exceptionCode;
removeAttribute(ATTR_CONTENTEDITABLE, exceptionCode);
}
else
setAttribute(ATTR_CONTENTEDITABLE, enabled.isEmpty() ? "true" : enabled);
}
void HTMLElementImpl::click(bool sendMouseEvents)
{
int x = 0;
int y = 0;
RenderObject *r = renderer();
if (r)
r->absolutePosition(x,y);
// send mousedown and mouseup before the click, if requested
if (sendMouseEvents) {
QMouseEvent pressEvt(QEvent::MouseButtonPress, QPoint(x,y), Qt::LeftButton, 0);
dispatchMouseEvent(&pressEvt, EventImpl::MOUSEDOWN_EVENT);
QMouseEvent upEvent(QEvent::MouseButtonRelease, QPoint(x,y), Qt::LeftButton, 0);
dispatchMouseEvent(&upEvent, EventImpl::MOUSEUP_EVENT);
}
// always send click
QMouseEvent clickEvent(QEvent::MouseButtonRelease, QPoint(x,y), Qt::LeftButton, 0);
dispatchMouseEvent(&clickEvent, EventImpl::KHTML_CLICK_EVENT);
}
// accessKeyAction is used by the accessibility support code
// to send events to elements that our JavaScript caller does
// does not. The elements JS is interested in have subclasses
// that override this method to direct the click appropriately.
// Here in the base class, then, we only send the click if
// the caller wants it to go to any HTMLElementImpl, and we say
// to send the mouse events in addition to the click.
void HTMLElementImpl::accessKeyAction(bool sendToAnyElement)
{
if (sendToAnyElement)
click(true);
}
DOMString HTMLElementImpl::toString() const
{
if (!hasChildNodes()) {
DOMString result = openTagStartToString();
result += ">";
if (endTagRequirement(id()) == REQUIRED) {
result += "</";
result += tagName();
result += ">";
}
return result;
}
return ElementImpl::toString();
}
// -------------------------------------------------------------------------
HTMLGenericElementImpl::HTMLGenericElementImpl(DocumentPtr *doc, ushort i)
: HTMLElementImpl(doc)
{
_id = i;
}
HTMLGenericElementImpl::~HTMLGenericElementImpl()
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -