📄 html_elementimpl.cpp
字号:
switch (attr->id())
{
case ATTR_ALIGN:
if (strcasecmp(attr->value(), "middle" ) == 0)
addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, "center");
else
addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, attr->value());
break;
// the core attributes...
case ATTR_ID:
// unique id
setHasID(!attr->isNull());
if (namedAttrMap) {
if (attr->isNull())
namedAttrMap->setID(nullAtom);
else if (getDocument()->inCompatMode() && !attr->value().implementation()->isLower())
namedAttrMap->setID(AtomicString(attr->value().domString().lower()));
else
namedAttrMap->setID(attr->value());
}
setChanged();
break;
case ATTR_CLASS:
// class
setHasClass(!attr->isNull());
if (namedAttrMap) static_cast<HTMLNamedAttrMapImpl*>(namedAttrMap)->parseClassAttribute(attr->value());
setChanged();
break;
case ATTR_CONTENTEDITABLE:
setContentEditable(attr);
break;
case ATTR_STYLE:
setHasStyle(!attr->isNull());
if (attr->isNull())
destroyInlineStyleDecl();
else
getInlineStyleDecl()->parseDeclaration(attr->value());
m_isStyleAttributeValid = true;
setChanged();
break;
case ATTR_TABINDEX:
indexstring=getAttribute(ATTR_TABINDEX);
if (indexstring.length())
setTabIndex(indexstring.toInt());
break;
// i18n attributes
case ATTR_LANG:
break;
case ATTR_DIR:
addCSSProperty(attr, CSS_PROP_DIRECTION, attr->value());
addCSSProperty(attr, CSS_PROP_UNICODE_BIDI, CSS_VAL_EMBED);
break;
// standard events
case ATTR_ONCLICK:
setHTMLEventListener(EventImpl::KHTML_CLICK_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONCONTEXTMENU:
setHTMLEventListener(EventImpl::CONTEXTMENU_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONDBLCLICK:
setHTMLEventListener(EventImpl::KHTML_DBLCLICK_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONMOUSEDOWN:
setHTMLEventListener(EventImpl::MOUSEDOWN_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONMOUSEMOVE:
setHTMLEventListener(EventImpl::MOUSEMOVE_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONMOUSEOUT:
setHTMLEventListener(EventImpl::MOUSEOUT_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONMOUSEOVER:
setHTMLEventListener(EventImpl::MOUSEOVER_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONMOUSEUP:
setHTMLEventListener(EventImpl::MOUSEUP_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONFOCUS:
setHTMLEventListener(EventImpl::DOMFOCUSIN_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONKEYDOWN:
setHTMLEventListener(EventImpl::KEYDOWN_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONKEYPRESS:
setHTMLEventListener(EventImpl::KEYPRESS_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONKEYUP:
setHTMLEventListener(EventImpl::KEYUP_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONSCROLL:
setHTMLEventListener(EventImpl::SCROLL_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONBEFORECUT:
setHTMLEventListener(EventImpl::BEFORECUT_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONCUT:
setHTMLEventListener(EventImpl::CUT_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONBEFORECOPY:
setHTMLEventListener(EventImpl::BEFORECOPY_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONCOPY:
setHTMLEventListener(EventImpl::COPY_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONBEFOREPASTE:
setHTMLEventListener(EventImpl::BEFOREPASTE_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONPASTE:
setHTMLEventListener(EventImpl::PASTE_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONDRAGENTER:
setHTMLEventListener(EventImpl::DRAGENTER_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONDRAGOVER:
setHTMLEventListener(EventImpl::DRAGOVER_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONDRAGLEAVE:
setHTMLEventListener(EventImpl::DRAGLEAVE_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONDROP:
setHTMLEventListener(EventImpl::DROP_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONDRAGSTART:
setHTMLEventListener(EventImpl::DRAGSTART_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONDRAG:
setHTMLEventListener(EventImpl::DRAG_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONDRAGEND:
setHTMLEventListener(EventImpl::DRAGEND_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONSELECTSTART:
setHTMLEventListener(EventImpl::SELECTSTART_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
// other misc attributes
default:
#ifdef UNSUPPORTED_ATTR
kdDebug(6030) << "UATTR: <" << this->nodeName().string() << "> ["
<< attr->name().string() << "]=[" << attr->value().string() << "]" << endl;
#endif
break;
}
}
void HTMLElementImpl::createAttributeMap() const
{
namedAttrMap = new HTMLNamedAttrMapImpl(const_cast<HTMLElementImpl*>(this));
namedAttrMap->ref();
}
CSSMutableStyleDeclarationImpl* HTMLElementImpl::getInlineStyleDecl()
{
if (!m_inlineStyleDecl)
createInlineStyleDecl();
return m_inlineStyleDecl;
}
CSSMutableStyleDeclarationImpl* HTMLElementImpl::additionalAttributeStyleDecl()
{
return 0;
}
const AtomicStringList* HTMLElementImpl::getClassList() const
{
return namedAttrMap ? static_cast<HTMLNamedAttrMapImpl*>(namedAttrMap)->getClassList() : 0;
}
static inline bool isHexDigit( const QChar &c ) {
return ( c >= '0' && c <= '9' ) ||
( c >= 'a' && c <= 'f' ) ||
( c >= 'A' && c <= 'F' );
}
static inline int toHex( const QChar &c ) {
return ( (c >= '0' && c <= '9')
? (c.unicode() - '0')
: ( ( c >= 'a' && c <= 'f' )
? (c.unicode() - 'a' + 10)
: ( ( c >= 'A' && c <= 'F' )
? (c.unicode() - 'A' + 10)
: -1 ) ) );
}
void HTMLElementImpl::addCSSProperty(HTMLAttributeImpl* attr, int id, const DOMString &value)
{
if (!attr->decl()) createMappedDecl(attr);
attr->decl()->setProperty(id, value, false);
}
void HTMLElementImpl::addCSSProperty(HTMLAttributeImpl* attr, int id, int value)
{
if (!attr->decl()) createMappedDecl(attr);
attr->decl()->setProperty(id, value, false);
}
void HTMLElementImpl::addCSSStringProperty(HTMLAttributeImpl* attr, int id, const DOMString &value, CSSPrimitiveValue::UnitTypes type)
{
if (!attr->decl()) createMappedDecl(attr);
attr->decl()->setStringProperty(id, value, type, false);
}
void HTMLElementImpl::addCSSImageProperty(HTMLAttributeImpl* attr, int id, const DOMString &URL)
{
if (!attr->decl()) createMappedDecl(attr);
attr->decl()->setImageProperty(id, URL, false);
}
void HTMLElementImpl::addCSSLength(HTMLAttributeImpl* attr, int id, const DOMString &value)
{
// FIXME: This function should not spin up the CSS parser, but should instead just figure out the correct
// length unit and make the appropriate parsed value.
if (!attr->decl()) createMappedDecl(attr);
// strip attribute garbage..
DOMStringImpl* v = value.implementation();
if ( v ) {
unsigned int l = 0;
while ( l < v->l && v->s[l].unicode() <= ' ') l++;
for ( ;l < v->l; l++ ) {
char cc = v->s[l].latin1();
if ( cc > '9' || ( cc < '0' && cc != '*' && cc != '%' && cc != '.') )
break;
}
if ( l != v->l ) {
attr->decl()->setLengthProperty(id, DOMString( v->s, l ), false);
return;
}
}
attr->decl()->setLengthProperty(id, value, false);
}
/* color parsing that tries to match as close as possible IE 6. */
void HTMLElementImpl::addHTMLColor(HTMLAttributeImpl* attr, int id, const DOMString &c)
{
// this is the only case no color gets applied in IE.
if ( !c.length() )
return;
if (!attr->decl()) createMappedDecl(attr);
if (attr->decl()->setProperty(id, c, false) )
return;
QString color = c.string();
// not something that fits the specs.
// we're emulating IEs color parser here. It maps transparent to black, otherwise it tries to build a rgb value
// out of everyhting you put in. The algorithm is experimentally determined, but seems to work for all test cases I have.
// the length of the color value is rounded up to the next
// multiple of 3. each part of the rgb triple then gets one third
// of the length.
//
// Each triplet is parsed byte by byte, mapping
// each number to a hex value (0-9a-fA-F to their values
// everything else to 0).
//
// The highest non zero digit in all triplets is remembered, and
// used as a normalization point to normalize to values between 0
// and 255.
if ( color.lower() != "transparent" ) {
if ( color[0] == '#' )
color.remove( 0, 1 );
int basicLength = (color.length() + 2) / 3;
if ( basicLength > 1 ) {
// IE ignores colors with three digits or less
// qDebug("trying to fix up color '%s'. basicLength=%d, length=%d",
// color.latin1(), basicLength, color.length() );
int colors[3] = { 0, 0, 0 };
int component = 0;
int pos = 0;
int maxDigit = basicLength-1;
while ( component < 3 ) {
// search forward for digits in the string
int numDigits = 0;
while ( pos < (int)color.length() && numDigits < basicLength ) {
int hex = toHex( color[pos] );
colors[component] = (colors[component] << 4);
if ( hex > 0 ) {
colors[component] += hex;
maxDigit = QMIN( maxDigit, numDigits );
}
numDigits++;
pos++;
}
while ( numDigits++ < basicLength )
colors[component] <<= 4;
component++;
}
maxDigit = basicLength - maxDigit;
// qDebug("color is %x %x %x, maxDigit=%d", colors[0], colors[1], colors[2], maxDigit );
// normalize to 00-ff. The highest filled digit counts, minimum is 2 digits
maxDigit -= 2;
colors[0] >>= 4*maxDigit;
colors[1] >>= 4*maxDigit;
colors[2] >>= 4*maxDigit;
// qDebug("normalized color is %x %x %x", colors[0], colors[1], colors[2] );
// assert( colors[0] < 0x100 && colors[1] < 0x100 && colors[2] < 0x100 );
color.sprintf("#%02x%02x%02x", colors[0], colors[1], colors[2] );
// qDebug( "trying to add fixed color string '%s'", color.latin1() );
if ( attr->decl()->setProperty(id, DOMString(color), false) )
return;
}
}
attr->decl()->setProperty(id, CSS_VAL_BLACK, false);
}
void HTMLElementImpl::createMappedDecl(HTMLAttributeImpl* attr)
{
CSSMappedAttributeDeclarationImpl* decl = new CSSMappedAttributeDeclarationImpl(0);
attr->setDecl(decl);
decl->setParent(getDocument()->elementSheet());
decl->setNode(this);
decl->setStrictParsing(false); // Mapped attributes are just always quirky.
}
DOMString HTMLElementImpl::innerHTML() const
{
if (id()==ID_BODY || id()==ID_HTML)
return "fastinnerhtml!";
return createMarkup(this, ChildrenOnly);
}
DOMString HTMLElementImpl::outerHTML() const
{
return createMarkup(this);
}
DOMString HTMLElementImpl::innerText() const
{
// We need to update layout, since plainText uses line boxes in the render tree.
getDocument()->updateLayout();
return plainText(Range(const_cast<HTMLElementImpl *>(this), 0,
const_cast<HTMLElementImpl *>(this), childNodeCount()));
}
DOMString HTMLElementImpl::outerText() const
{
// Getting outerText is the same as getting innerText, only
// setting is different. You would think this should get the plain
// text for the outer range, but this is wrong, <br> for instance
// would return different values for inner and outer text by such
// a rule, but it doesn't in WinIE, and we want to match that.
return innerText();
}
DocumentFragmentImpl *HTMLElementImpl::createContextualFragment(const DOMString &html)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -