?? cssstyleselector.cpp
字號:
{
// FIXME: This match needs to know how to backtrack and be non-deterministic.
bool found = false;
while(!found)
{
n = n->parentNode();
if(!n || !n->isElementNode()) return false;
ElementImpl *elem = static_cast<ElementImpl *>(n);
if (checkOneSelector(sel, elem)) found = true;
}
break;
}
case CSSSelector::Child:
{
n = n->parentNode();
if (!strictParsing)
while (n && n->implicitNode()) n = n->parentNode();
if(!n || !n->isElementNode()) return false;
ElementImpl *elem = static_cast<ElementImpl *>(n);
if (!checkOneSelector(sel, elem)) return false;
break;
}
case CSSSelector::Sibling:
{
n = n->previousSibling();
while( n && !n->isElementNode() )
n = n->previousSibling();
if( !n ) return false;
ElementImpl *elem = static_cast<ElementImpl *>(n);
if (!checkOneSelector(sel, elem)) return false;
break;
}
case CSSSelector::SubSelector:
{
if (onlyHoverActive)
onlyHoverActive = (sel->match == CSSSelector::Pseudo &&
(sel->pseudoType() == CSSSelector::PseudoHover ||
sel->pseudoType() == CSSSelector::PseudoActive));
//kdDebug() << "CSSOrderedRule::checkSelector" << endl;
ElementImpl *elem = static_cast<ElementImpl *>(n);
// a selector is invalid if something follows :first-xxx
if (dynamicPseudo != RenderStyle::NOPSEUDO)
return false;
if (!checkOneSelector(sel, elem)) return false;
//kdDebug() << "CSSOrderedRule::checkSelector: passed" << endl;
break;
}
}
relation = sel->relation;
}
if (subject && havePseudo && dynamicPseudo != pseudoStyle)
return false;
// disallow *:hover, *:active, and *:hover:active except for links
if (onlyHoverActive && subject) {
if (pseudoState == PseudoUnknown)
checkPseudoState(e);
if (pseudoState == PseudoNone) {
if (!affectedByHover && style->affectedByHoverRules())
style->setAffectedByHoverRules(false);
if (!affectedByActive && style->affectedByActiveRules())
style->setAffectedByActiveRules(false);
return false;
}
}
return true;
}
bool CSSStyleSelector::checkOneSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e)
{
if(!e)
return false;
if (sel->tag != anyQName) {
int eltID = e->id();
Q_UINT16 localName = localNamePart(eltID);
Q_UINT16 ns = namespacePart(eltID);
Q_UINT16 selLocalName = localNamePart(sel->tag);
Q_UINT16 selNS = namespacePart(sel->tag);
if (localName <= ID_LAST_TAG && e->isHTMLElement())
ns = xhtmlNamespace; // FIXME: Really want to move away from this complicated hackery and just
// switch tags and attr names over to AtomicStrings.
if ((selLocalName != anyLocalName && localName != selLocalName) ||
(selNS != anyNamespace && ns != selNS))
return false;
}
if (sel->attr) {
if (sel->match == CSSSelector::Class) {
if (!e->hasClass())
return false;
for (const AtomicStringList* c = e->getClassList(); c; c = c->next())
if (c->string() == sel->value)
return true;
return false;
}
else if (sel->match == CSSSelector::Id)
return e->hasID() && e->getIDAttribute() == sel->value;
else if (style && (e != element || !htmlElement || !htmlElement->isMappedAttribute(sel->attr)))
style->setAffectedByAttributeSelectors();
const AtomicString& value = e->getAttribute(sel->attr);
if (value.isNull()) return false; // attribute is not set
switch(sel->match) {
case CSSSelector::Exact:
if ((isXMLDoc && sel->value != value) ||
(!isXMLDoc && !equalsIgnoreCase(sel->value, value)))
return false;
break;
case CSSSelector::List:
{
int spacePos = value.find(' ', 0);
if (spacePos == -1) {
// There is no list, just a single item. We can avoid
// allocing QStrings and just treat this as an exact
// match check.
if ((isXMLDoc && sel->value != value) ||
(!isXMLDoc && !equalsIgnoreCase(sel->value, value)))
return false;
break;
}
// The selector's value can't contain a space, or it's totally bogus.
spacePos = sel->value.find(' ');
if (spacePos != -1)
return false;
QString str = value.string();
QString selStr = sel->value.string();
int startSearchAt = 0;
while (true) {
int foundPos = str.find(selStr, startSearchAt, isXMLDoc);
if (foundPos == -1) return false;
if (foundPos == 0 || str[foundPos-1] == ' ') {
uint endStr = foundPos + selStr.length();
if (endStr == str.length() || str[endStr] == ' ')
break; // We found a match.
}
// No match. Keep looking.
startSearchAt = foundPos + 1;
}
break;
}
case CSSSelector::Contain:
{
//kdDebug( 6080 ) << "checking for contains match" << endl;
QString str = value.string();
QString selStr = sel->value.string();
int pos = str.find(selStr, 0, isXMLDoc);
if(pos == -1) return false;
break;
}
case CSSSelector::Begin:
{
//kdDebug( 6080 ) << "checking for beginswith match" << endl;
QString str = value.string();
QString selStr = sel->value.string();
int pos = str.find(selStr, 0, isXMLDoc);
if(pos != 0) return false;
break;
}
case CSSSelector::End:
{
//kdDebug( 6080 ) << "checking for endswith match" << endl;
QString str = value.string();
QString selStr = sel->value.string();
if (isXMLDoc && !str.endsWith(selStr)) return false;
if (!isXMLDoc) {
int pos = str.length() - selStr.length();
if (pos < 0 || pos != str.find(selStr, pos, false) )
return false;
}
break;
}
case CSSSelector::Hyphen:
{
//kdDebug( 6080 ) << "checking for hyphen match" << endl;
QString str = value.string();
QString selStr = sel->value.string();
if(str.length() < selStr.length()) return false;
// Check if str begins with selStr:
if(str.find(selStr, 0, isXMLDoc) != 0) return false;
// It does. Check for exact match or following '-':
if(str.length() != selStr.length()
&& str[selStr.length()] != '-') return false;
break;
}
default:
break;
}
}
if(sel->match == CSSSelector::Pseudo)
{
// Pseudo elements. We need to check first child here. No dynamic pseudo
// elements for the moment
// kdDebug() << "CSSOrderedRule::pseudo " << value << endl;
switch (sel->pseudoType()) {
case CSSSelector::PseudoEmpty:
if (!e->firstChild())
return true;
break;
case CSSSelector::PseudoFirstChild: {
// first-child matches the first child that is an element!
if (e->parentNode()) {
DOM::NodeImpl* n = e->previousSibling();
while ( n && !n->isElementNode() )
n = n->previousSibling();
if ( !n )
return true;
}
break;
}
case CSSSelector::PseudoLastChild: {
// last-child matches the last child that is an element!
if (e->parentNode()) {
DOM::NodeImpl* n = e->nextSibling();
while ( n && !n->isElementNode() )
n = n->nextSibling();
if ( !n )
return true;
}
break;
}
case CSSSelector::PseudoOnlyChild: {
// If both first-child and last-child apply, then only-child applies.
if (e->parentNode()) {
DOM::NodeImpl* n = e->previousSibling();
while ( n && !n->isElementNode() )
n = n->previousSibling();
if ( !n ) {
n = e->nextSibling();
while ( n && !n->isElementNode() )
n = n->nextSibling();
if ( !n )
return true;
}
}
break;
}
case CSSSelector::PseudoFirstLine:
if ( subject ) {
dynamicPseudo=RenderStyle::FIRST_LINE;
return true;
}
break;
case CSSSelector::PseudoFirstLetter:
if ( subject ) {
dynamicPseudo=RenderStyle::FIRST_LETTER;
return true;
}
break;
case CSSSelector::PseudoTarget:
if (e == e->getDocument()->getCSSTarget())
return true;
break;
case CSSSelector::PseudoAnyLink:
if (pseudoState == PseudoUnknown)
checkPseudoState(e, false);
if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited)
return true;
break;
case CSSSelector::PseudoLink:
if ( pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink )
checkPseudoState( e );
if ( pseudoState == PseudoLink )
return true;
break;
case CSSSelector::PseudoVisited:
if ( pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink )
checkPseudoState( e );
if ( pseudoState == PseudoVisited )
return true;
break;
case CSSSelector::PseudoHover: {
// If we're in quirks mode, then hover should never match anchors with no
// href. This is important for sites like wsj.com.
if (strictParsing || e->id() != ID_A || e->hasAnchor()) {
if (element == e && style)
style->setAffectedByHoverRules(true);
if (e->renderer()) {
if (element != e)
e->renderer()->style()->setAffectedByHoverRules(true);
if (e->renderer()->mouseInside())
return true;
}
}
break;
}
case CSSSelector::PseudoDrag: {
if (element == e && style)
style->setAffectedByDragRules(true);
if (e->renderer()) {
if (element != e)
e->renderer()->style()->setAffectedByDragRules(true);
if (e->renderer()->isDragging())
return true;
}
break;
}
case CSSSelector::PseudoFocus:
if (e && e->focused()) {
return true;
}
break;
case CSSSelector::PseudoActive:
// If we're in quirks mode, then :active should never match anchors with no
// href.
if (strictParsing || e->id() != ID_A || e->hasAnchor()) {
if (element == e && style)
style->setAffectedByActiveRules(true);
else if (e->renderer())
e->renderer()->style()->setAffectedByActiveRules(true);
if (e->active())
return true;
}
break;
case CSSSelector::PseudoRoot:
if (e == e->getDocument()->documentElement())
return true;
break;
case CSSSelector::PseudoNot: {
// check the simple selector
for (CSSSelector* subSel = sel->simpleSelector; subSel;
subSel = subSel->tagHistory) {
// :not cannot nest. I don't really know why this is a restriction in CSS3,
// but it is, so let's honor it.
if (subSel->simpleSelector)
break;
if (!checkOneSelector(subSel, e))
return true;
}
break;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -