auto merge of #1318 : therealglazou/servo/therealglazou/nth-pseudos, r=SimonSapin

Implement :nth-child, :nth-last-child, :nth-of-type, :nth-last-of-type, :first-of-type, :last-of-type and :only-of-type Selectors Level 3 pseudo-classes. Reftests included.
This commit is contained in:
bors-servo 2013-11-29 03:22:16 -08:00
commit 7dbabdd9e4
17 changed files with 1207 additions and 6 deletions

View file

@ -489,14 +489,24 @@ fn matches_simple_selector<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: Ele
}
}
}
FirstChild => matches_first_child(element),
LastChild => matches_last_child(element),
OnlyChild => matches_first_child(element) && matches_last_child(element),
OnlyChild => matches_first_child(element) &&
matches_last_child(element),
Root => matches_root(element),
NthChild(a, b) => matches_generic_nth_child(element, a, b, false, false),
NthLastChild(a, b) => matches_generic_nth_child(element, a, b, false, true),
NthOfType(a, b) => matches_generic_nth_child(element, a, b, true, false),
NthLastOfType(a, b) => matches_generic_nth_child(element, a, b, true, true),
FirstOfType => matches_generic_nth_child(element, 0, 1, true, false),
LastOfType => matches_generic_nth_child(element, 0, 1, true, true),
OnlyOfType => matches_generic_nth_child(element, 0, 1, true, false) &&
matches_generic_nth_child(element, 0, 1, true, true),
Negation(ref negated) => {
!negated.iter().all(|s| matches_simple_selector(s, element))
},
@ -510,6 +520,66 @@ fn url_is_visited(_url: &str) -> bool {
false
}
#[inline]
fn matches_generic_nth_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
element: &T, a: i32, b: i32, is_of_type: bool, is_from_end: bool) -> bool {
let mut node = element.clone();
// fail if we can't find a parent or if the node is the root element
// of the document (Cf. Selectors Level 3)
match node.node().parent_node() {
Some(parent) => if parent.is_document() {
return false;
},
None => return false
};
let mut local_name = "";
if is_of_type {
// FIXME this is wrong
// TODO when the DOM supports namespaces on elements
do element.with_imm_element_like |element: &E| {
local_name = element.get_local_name();
}
}
let mut index = 1;
loop {
if is_from_end {
match node.node().next_sibling() {
None => break,
Some(next_sibling) => node = next_sibling
}
} else {
match node.node().prev_sibling() {
None => break,
Some(prev_sibling) => node = prev_sibling
}
}
if node.is_element() {
if is_of_type {
// FIXME this is wrong
// TODO when the DOM supports namespaces on elements
do node.with_imm_element_like |node: &E| {
if local_name == node.get_local_name() {
index += 1;
}
}
} else {
index += 1;
}
}
}
if a == 0 {
return b == index;
}
let (n, r) = (index - b).div_rem(&a);
n >= 0 && r == 0
}
#[inline]
fn matches_root<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>(
element: &T) -> bool {

View file

@ -5,6 +5,7 @@
use std::{vec, iter};
use std::ascii::StrAsciiExt;
use cssparser::ast::*;
use cssparser::parse_nth;
use namespaces::NamespaceMap;
@ -66,7 +67,13 @@ pub enum SimpleSelector {
// Empty,
Root,
// Lang(~str),
// NthChild(i32, i32),
NthChild(i32, i32),
NthLastChild(i32, i32),
NthOfType(i32, i32),
NthLastOfType(i32, i32),
FirstOfType,
LastOfType,
OnlyOfType
// ...
}
@ -192,7 +199,10 @@ fn compute_specificity(mut selector: &CompoundSelector,
| &AttrPrefixMatch(*) | &AttrSubstringMatch(*) | &AttrSuffixMatch(*)
| &AnyLink | &Link | &Visited
| &FirstChild | &LastChild | &OnlyChild | &Root
// | &Empty | &Lang(*) | &NthChild(*)
// | &Empty | &Lang(*)
| &NthChild(*) | &NthLastChild(*)
| &NthOfType(*) | &NthLastOfType(*)
| &FirstOfType | &LastOfType | &OnlyOfType
=> specificity.class_like_selectors += 1,
&NamespaceSelector(*) => (),
&Negation(ref negated)
@ -441,6 +451,9 @@ fn parse_simple_pseudo_class(name: &str) -> Option<SimpleSelector> {
"last-child" => Some(LastChild),
"only-child" => Some(OnlyChild),
"root" => Some(Root),
"first-of-type" => Some(FirstOfType),
"last-of-type" => Some(LastOfType),
"only-of-type" => Some(OnlyOfType),
// "empty" => Some(Empty),
_ => None
}
@ -452,7 +465,10 @@ fn parse_functional_pseudo_class(name: ~str, arguments: ~[ComponentValue],
-> Option<SimpleSelector> {
match name.to_ascii_lower().as_slice() {
// "lang" => parse_lang(arguments),
// "nth-child" => parse_nth(arguments).map(|&(a, b)| NthChild(a, b)),
"nth-child" => parse_nth(arguments).map(|(a, b)| NthChild(a, b)),
"nth-last-child" => parse_nth(arguments).map(|(a, b)| NthLastChild(a, b)),
"nth-of-type" => parse_nth(arguments).map(|(a, b)| NthOfType(a, b)),
"nth-last-of-type" => parse_nth(arguments).map(|(a, b)| NthLastOfType(a, b)),
"not" => if inside_negation { None } else { parse_negation(arguments, namespaces) },
_ => None
}

View file

@ -5,3 +5,10 @@
== first_child_pseudo_a.html first_child_pseudo_b.html
== last_child_pseudo_a.html last_child_pseudo_b.html
== only_child_pseudo_a.html only_child_pseudo_b.html
== nth_child_pseudo_a.html nth_child_pseudo_b.html
== nth_last_child_pseudo_a.html nth_last_child_pseudo_b.html
== nth_of_type_pseudo_a.html nth_of_type_pseudo_b.html
== nth_last_of_type_pseudo_a.html nth_last_of_type_pseudo_b.html
== first_of_type_pseudo_a.html first_of_type_pseudo_b.html
== last_of_type_pseudo_a.html last_of_type_pseudo_b.html
== only_of_type_pseudo_a.html only_of_type_pseudo_b.html

View file

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<title>:first-of-type test</title>
<style type="text/css">
/* should not match according to Selectors 3 because html has no parent element */
html:first-of-type { background: red; }
div > p,
div > div,
div > address {
float: left;
width: 20px;
height: 20px;
margin: 0px;
margin-right: 10px;
padding: 0px;
}
div > p {
background: white;
}
div > div,
div > address {
background: black;
}
body > div { clear: both; margin-bottom: 10px; }
#d1 > .ok { background: red; }
#d1 > *:first-of-type { background: green }
</style>
</head>
<body>
<div id="d1">
<p class="ok"> </p>
<div class="ok"> </div>
<div> </div>
<p> </p>
<address class="ok"> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<title>:first-of-type test</title>
<style type="text/css">
div > p,
div > div,
div > address {
float: left;
width: 20px;
height: 20px;
margin: 0px;
margin-right: 10px;
padding: 0px;
}
div > p {
background: white;
}
div > div,
div > address {
background: black;
}
body > div { clear: both; margin-bottom: 10px; }
#d1 > .ok { background: green; }
</style>
</head>
<body>
<div id="d1">
<p class="ok"> </p>
<div class="ok"> </div>
<div> </div>
<p> </p>
<address class="ok"> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<title>:last-of-type test</title>
<style type="text/css">
/* should not match according to Selectors 3 because html has no parent element */
html:last-of-type { background: red; }
div > p,
div > div,
div > address {
float: left;
width: 20px;
height: 20px;
margin: 0px;
margin-right: 10px;
padding: 0px;
}
div > p {
background: white;
}
div > div,
div > address {
background: black;
}
body > div { clear: both; margin-bottom: 10px; }
#d1 > .ok { background: red; }
#d1 > *:last-of-type { background: green }
</style>
</head>
<body>
<div id="d1">
<p> </p>
<div> </div>
<div> </div>
<p> </p>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
<address> </address>
<address class="ok"> </address>
<p> </p>
<div class="ok"> </div>
<p> </p>
<p class="ok"> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<title>:last-of-type test</title>
<style type="text/css">
div > p,
div > div,
div > address {
float: left;
width: 20px;
height: 20px;
margin: 0px;
margin-right: 10px;
padding: 0px;
}
div > p {
background: white;
}
div > div,
div > address {
background: black;
}
body > div { clear: both; margin-bottom: 10px; }
#d1 > .ok { background: green; }
</style>
</head>
<body>
<div id="d1">
<p> </p>
<div> </div>
<div> </div>
<p> </p>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
<address> </address>
<address class="ok"> </address>
<p> </p>
<div class="ok"> </div>
<p> </p>
<p class="ok"> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>
<head>
<title>:nth-child test</title>
<style type="text/css">
/* should not match according to Selectors 3 because html has no parent element */
html:nth-child(1) { background: red; }
div > p { float: left; width: 40px; height: 40px; margin-right: 10px; border: 1px solid black; }
div { clear: both; }
#odd > .odd { background: red; }
#odd > *:nth-child(odd) { background: green }
#even > .even { background: red; }
#even > *:nth-child(even) { background: green }
#nth > .nth { background: red; }
#nth > :nth-child(3n+5) { background: green; }
#nth2 > .nth2 { background: red; }
#nth2 > :nth-child(3n-5) { background: green; }
#negativen > .negativen { background: red; }
#negativen > :nth-child(-2n+5) { background: green; }
</style>
</head>
<body>
<div id="odd">
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
<p> </p>
</div>
<div id="even">
<p> </p>
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
</div>
<div id="nth">
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p class="nth"> </p>
<p> </p>
<p> </p>
<p class="nth"> </p>
<p> </p>
<p> </p>
<p class="nth"> </p>
</div>
<div id="nth2">
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
<p> </p>
</div>
<div id="negativen">
<p class="negativen"> </p>
<p> </p>
<p class="negativen"> </p>
<p> </p>
<p class="negativen"> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<title>:nth-child test</title>
<style type="text/css">
div > p { float: left; width: 40px; height: 40px; margin-right: 10px; border: 1px solid black; }
div { clear: both; }
.odd, .even, .nth, .nth2, .negativen { background: green; }
</style>
</head>
<body>
<div id="odd">
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
<p> </p>
</div>
<div id="even">
<p> </p>
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
</div>
<div id="nth">
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p class="nth"> </p>
<p> </p>
<p> </p>
<p class="nth"> </p>
<p> </p>
<p> </p>
<p class="nth"> </p>
</div>
<div id="nth2">
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
<p> </p>
</div>
<div id="negativen">
<p class="negativen"> </p>
<p> </p>
<p class="negativen"> </p>
<p> </p>
<p class="negativen"> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>
<head>
<title>:nth-last-child test</title>
<style type="text/css">
/* should not match according to Selectors 3 because html has no parent element */
html:nth-last-child(1) { background: red; }
div > p { float: left; width: 40px; height: 40px; margin-right: 10px; border: 1px solid black; }
div { clear: both; }
#odd > .odd { background: red; }
#odd > *:nth-last-child(odd) { background: green }
#even > .even { background: red; }
#even > *:nth-last-child(even) { background: green }
#nth > .nth { background: red; }
#nth > :nth-last-child(3n+5) { background: green; }
#nth2 > .nth2 { background: red; }
#nth2 > :nth-last-child(3n-5) { background: green; }
#negativen > .negativen { background: red; }
#negativen > :nth-last-child(-2n+5) { background: green; }
</style>
</head>
<body>
<div id="odd">
<p> </p>
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
</div>
<div id="even">
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
<p> </p>
</div>
<div id="nth">
<p class="nth"> </p>
<p> </p>
<p> </p>
<p class="nth"> </p>
<p> </p>
<p> </p>
<p class="nth"> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
</div>
<div id="nth2">
<p> </p>
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
</div>
<div id="negativen">
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p class="negativen"> </p>
<p> </p>
<p class="negativen"> </p>
<p> </p>
<p class="negativen"> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<title>:nth-last-child test</title>
<style type="text/css">
div > p { float: left; width: 40px; height: 40px; margin-right: 10px; border: 1px solid black; }
div { clear: both; }
.odd, .even, .nth, .nth2, .negativen { background: green; }
</style>
</head>
<body>
<div id="odd">
<p> </p>
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
<p> </p>
<p class="odd"> </p>
</div>
<div id="even">
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
<p> </p>
<p class="even"> </p>
<p> </p>
</div>
<div id="nth">
<p class="nth"> </p>
<p> </p>
<p> </p>
<p class="nth"> </p>
<p> </p>
<p> </p>
<p class="nth"> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
</div>
<div id="nth2">
<p> </p>
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
<p> </p>
<p> </p>
<p class="nth2"> </p>
</div>
<div id="negativen">
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p class="negativen"> </p>
<p> </p>
<p class="negativen"> </p>
<p> </p>
<p class="negativen"> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,131 @@
<!DOCTYPE html>
<html>
<head>
<title>:nth-last-of-type test</title>
<style type="text/css">
/* should not match according to Selectors 3 because html has no parent element */
html:nth-last-of-type(1) { background: red; }
div > p,
div > div,
div > address {
float: left;
width: 20px;
height: 20px;
margin: 0px;
margin-right: 10px;
padding: 0px;
}
div > p {
background: white;
}
div > div,
div > address {
background: black;
}
body > div { clear: both; margin-bottom: 10px; }
#odd > .odd { background: red; }
#odd > p:nth-last-of-type(odd) { background: green }
#even > .even { background: red; }
#even > p:nth-last-of-type(even) { background: green }
#nth > .nth { background: red; }
#nth > p:nth-last-of-type(3n+5) { background: green; }
#nth2 > .nth2 { background: red; }
#nth2 > p:nth-last-of-type(3n-5) { background: green; }
#negativen > .negativen { background: red; }
#negativen > p:nth-last-of-type(-2n+5) { background: green; }
</style>
</head>
<body>
<div id="odd">
<p> </p>
<div> </div>
<address> </address>
<div> </div>
<p class="odd"> </p>
<p> </p>
<div> </div>
<p class="odd"> </p>
<p> </p>
<address> </address>
<address> </address>
<p class="odd"> </p>
<div> </div>
<p> </p>
<p class="odd"> </p>
</div>
<div id="even">
<p class="even"> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p class="even"> </p>
<div> </div>
<p> </p>
<p class="even"> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p class="even"> </p>
<p> </p>
</div>
<div id="nth">
<p class="nth"> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p> </p>
<div> </div>
<p class="nth"> </p>
<p> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
</div>
<div id="nth2">
<p> </p>
<div> </div>
<address> </address>
<div> </div>
<p class="nth2"> </p>
<p> </p>
<div> </div>
<p> </p>
<p class="nth2"> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p class="nth2"> </p>
</div>
<div id="negativen">
<p> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p> </p>
<div> </div>
<p class="negativen"> </p>
<p> </p>
<address> </address>
<address> </address>
<p class="negativen"> </p>
<div> </div>
<p> </p>
<p class="negativen"> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html>
<head>
<title>:nth-last-of-type test</title>
<style type="text/css">
div > p,
div > div,
div > address {
float: left;
width: 20px;
height: 20px;
margin: 0px;
margin-right: 10px;
padding: 0px;
}
div > p {
background: white;
}
div > div,
div > address {
background: black;
}
body > div { clear: both; margin-bottom: 10px; }
.odd, .even, .nth, .nth2, .negativen { background: green; }
</style>
</head>
<body>
<div id="odd">
<p> </p>
<div> </div>
<address> </address>
<div> </div>
<p class="odd"> </p>
<p> </p>
<div> </div>
<p class="odd"> </p>
<p> </p>
<address> </address>
<address> </address>
<p class="odd"> </p>
<div> </div>
<p> </p>
<p class="odd"> </p>
</div>
<div id="even">
<p class="even"> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p class="even"> </p>
<div> </div>
<p> </p>
<p class="even"> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p class="even"> </p>
<p> </p>
</div>
<div id="nth">
<p class="nth"> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p> </p>
<div> </div>
<p class="nth"> </p>
<p> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
</div>
<div id="nth2">
<p> </p>
<div> </div>
<address> </address>
<div> </div>
<p class="nth2"> </p>
<p> </p>
<div> </div>
<p> </p>
<p class="nth2"> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p class="nth2"> </p>
</div>
<div id="negativen">
<p> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p> </p>
<div> </div>
<p class="negativen"> </p>
<p> </p>
<address> </address>
<address> </address>
<p class="negativen"> </p>
<div> </div>
<p> </p>
<p class="negativen"> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,131 @@
<!DOCTYPE html>
<html>
<head>
<title>:nth-of-type test</title>
<style type="text/css">
/* should not match according to Selectors 3 because html has no parent element */
html:nth-of-type(1) { background: red; }
div > p,
div > div,
div > address {
float: left;
width: 20px;
height: 20px;
margin: 0px;
margin-right: 10px;
padding: 0px;
}
div > p {
background: white;
}
div > div,
div > address {
background: black;
}
body > div { clear: both; margin-bottom: 10px; }
#odd > .odd { background: red; }
#odd > p:nth-of-type(odd) { background: green }
#even > .even { background: red; }
#even > p:nth-of-type(even) { background: green }
#nth > .nth { background: red; }
#nth > p:nth-of-type(3n+5) { background: green; }
#nth2 > .nth2 { background: red; }
#nth2 > p:nth-of-type(3n-5) { background: green; }
#negativen > .negativen { background: red; }
#negativen > p:nth-of-type(-2n+5) { background: green; }
</style>
</head>
<body>
<div id="odd">
<p class="odd"> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p class="odd"> </p>
<div> </div>
<p> </p>
<p class="odd"> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p class="odd"> </p>
<p> </p>
</div>
<div id="even">
<p> </p>
<div> </div>
<address> </address>
<div> </div>
<p class="even"> </p>
<p> </p>
<div> </div>
<p class="even"> </p>
<p> </p>
<address> </address>
<address> </address>
<p class="even"> </p>
<div> </div>
<p> </p>
<p class="even"> </p>
</div>
<div id="nth">
<p> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p> </p>
<div> </div>
<p> </p>
<p class="nth"> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p class="nth"> </p>
</div>
<div id="nth2">
<p class="nth2"> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p> </p>
<div> </div>
<p class="nth2"> </p>
<p> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p class="nth2"> </p>
<p> </p>
</div>
<div id="negativen">
<p class="negativen"> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p class="negativen"> </p>
<div> </div>
<p> </p>
<p class="negativen"> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,115 @@
<!DOCTYPE html>
<html>
<head>
<title>:nth-of-type test</title>
<style type="text/css">
div > p,
div > div,
div > address {
float: left;
width: 20px;
height: 20px;
margin: 0px;
margin-right: 10px;
padding: 0px;
}
div > p {
background: white;
}
div > div,
div > address {
background: black;
}
body > div { clear: both; margin-bottom: 10px; }
.odd, .even, .nth, .nth2, .negativen { background: green; }
</style>
</head>
<body>
<div id="odd">
<p class="odd"> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p class="odd"> </p>
<div> </div>
<p> </p>
<p class="odd"> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p class="odd"> </p>
<p> </p>
</div>
<div id="even">
<p> </p>
<div> </div>
<address> </address>
<div> </div>
<p class="even"> </p>
<p> </p>
<div> </div>
<p class="even"> </p>
<p> </p>
<address> </address>
<address> </address>
<p class="even"> </p>
<div> </div>
<p> </p>
<p class="even"> </p>
</div>
<div id="nth">
<p> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p> </p>
<div> </div>
<p> </p>
<p class="nth"> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p class="nth"> </p>
</div>
<div id="nth2">
<p class="nth2"> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p> </p>
<div> </div>
<p class="nth2"> </p>
<p> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p class="nth2"> </p>
<p> </p>
</div>
<div id="negativen">
<p class="negativen"> </p>
<div> </div>
<address> </address>
<div> </div>
<p> </p>
<p class="negativen"> </p>
<div> </div>
<p> </p>
<p class="negativen"> </p>
<address> </address>
<address> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>:only-of-type test</title>
<style type="text/css">
/* should not match according to Selectors 3 because html has no parent element */
html:only-of-type { background: red; }
div > p,
div > div,
div > address {
float: left;
width: 20px;
height: 20px;
margin: 0px;
margin-right: 10px;
padding: 0px;
}
div > div,
div > p {
background: black;
}
body > div { clear: both; margin-bottom: 10px; }
#d1 > .ok { background: red; }
#d1 > *:only-of-type { background: green }
</style>
</head>
<body>
<div id="d1">
<p> </p>
<div> </div>
<div> </div>
<p> </p>
<address class="ok"> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
</div>
</body>
</html>

View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title>:only-of-type test</title>
<style type="text/css">
div > p,
div > div,
div > address {
float: left;
width: 20px;
height: 20px;
margin: 0px;
margin-right: 10px;
padding: 0px;
}
div > div,
div > p {
background: black;
}
body > div { clear: both; margin-bottom: 10px; }
#d1 > .ok { background: green; }
</style>
</head>
<body>
<div id="d1">
<p> </p>
<div> </div>
<div> </div>
<p> </p>
<address class="ok"> </address>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
<p> </p>
<div> </div>
<p> </p>
<p> </p>
</div>
</body>
</html>