Skip to content

Commit

Permalink
Implement :enabled/:disabled per the HTML5 spec. (Almost, see #6)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonSapin committed Apr 20, 2012
1 parent 3d8fd09 commit 1c12e2a
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 26 deletions.
34 changes: 18 additions & 16 deletions cssselect/tests.py
Expand Up @@ -426,7 +426,6 @@ def pcss(main, *selectors, **kwargs):
return result

all_ids = pcss('*')
assert len(all_ids) == 32
assert all_ids[:6] == [
'html', 'nil', 'link-href', 'link-nohref', 'nil', 'outer-div']
assert all_ids[-1:] == ['foobar-span']
Expand Down Expand Up @@ -472,8 +471,7 @@ def pcss(main, *selectors, **kwargs):
assert pcss('ol:nth-last-of-type(1)') == ['first-ol']
assert pcss('span:only-child') == ['foobar-span']
assert pcss('li div:only-child') == ['li-div']
assert pcss('div *:only-child') == [
'li-div', 'checkbox-disabled', 'foobar-span']
assert pcss('div *:only-child') == ['li-div', 'foobar-span']
self.assertRaises(ExpressionError, pcss, 'p *:only-of-type')
self.assertRaises(ExpressionError, pcss, 'p:lang(fr)')
assert pcss('p:only-of-type') == ['paragraph']
Expand Down Expand Up @@ -504,25 +502,25 @@ def pcss(main, *selectors, **kwargs):
assert pcss('ol#first-ol *:last-child') == ['li-div', 'seventh-li']
assert pcss('#outer-div:first-child') == ['outer-div']
assert pcss('#outer-div :first-child') == [
'name-anchor', 'first-li', 'li-div', 'p-b', 'checkbox-disabled',
'area-href']
'name-anchor', 'first-li', 'li-div', 'p-b',
'checkbox-fieldset-disabled', 'area-href']
assert pcss('a[href]') == ['tag-anchor', 'nofollow-anchor']
assert pcss('a:not([href])') == ['name-anchor']
assert pcss('ol :Not(li[class])') == [
'first-li', 'second-li', 'li-div',
'fifth-li', 'sixth-li', 'seventh-li']


# HTML-specific
assert pcss(':link', html_only=True) == [
'link-href', 'tag-anchor', 'nofollow-anchor', 'area-href']
assert pcss(':visited', html_only=True) == []

assert pcss(':enabled', html_only=True) == [
'link-href', 'tag-anchor', 'nofollow-anchor',
'checkbox-unchecked', 'checkbox-checked', 'area-href']
assert pcss(':disabled', html_only=True) == [
'checkbox-disabled', 'fieldset', 'checkbox-fieldset-disabled']

assert pcss(':checked', html_only=True) == ['checkbox-checked']
assert pcss(':disabled', html_only=True) == [
'fieldset', 'checkbox-disabled']
assert pcss(':enabled', html_only=True) == [
'checkbox-unchecked', 'checkbox-checked']
assert pcss('a:not([href])') == ['name-anchor']
assert pcss('ol :Not(li[class])') == [
'first-li', 'second-li', 'li-div',
'fifth-li', 'sixth-li', 'seventh-li']

def test_select_shakespeare(self):
document = html.document_fromstring(HTML_SHAKESPEARE)
Expand Down Expand Up @@ -624,9 +622,13 @@ def count(selector):
<b id="p-b">hi</b> <em id="p-em">there</em>
<b id="p-b2">guy</b>
<input type="checkbox" id="checkbox-unchecked" />
<input type="checkbox" id="checkbox-disabled" disabled="disabled" />
<input type="hidden" />
<input type="hidden" disabled="disabled" />
<input type="checkbox" id="checkbox-checked" checked="checked" />
<fieldset id="fieldset" disabled="disabled">
<input type="checkbox" id="checkbox-disabled" />
<input type="checkbox" id="checkbox-fieldset-disabled" />
<input type="hidden" />
</fieldset>
</p>
<ol id="second-ol">
Expand Down
31 changes: 21 additions & 10 deletions cssselect/xpath.py
Expand Up @@ -529,23 +529,21 @@ def xpath_disabled_pseudo(self, xpath):
(
@disabled and
(
name(.) = 'input' or
(name(.) = 'input' and @type != 'hidden') or
name(.) = 'button' or
name(.) = 'select' or
name(.) = 'textarea' or
name(.) = 'keygen' or
name(.) = 'command' or
name(.) = 'fieldset' or
name(.) = 'optgroup' or
name(.) = 'option'
)
) or (
(
name(.) = 'input' or
(name(.) = 'input' and @type != 'hidden') or
name(.) = 'button' or
name(.) = 'select' or
name(.) = 'textarea' or
name(.) = 'keygen'
name(.) = 'textarea'
)
and ancestor::fieldset[@disabled]
)
Expand All @@ -557,23 +555,36 @@ def xpath_enabled_pseudo(self, xpath):
# http://www.w3.org/TR/html5/section-index.html#attributes-1
return xpath.add_condition('''
(
@href and (
name(.) = 'a' or
name(.) = 'link' or
name(.) = 'area'
)
) or (
(
name(.) = 'command' or
name(.) = 'fieldset' or
name(.) = 'optgroup' or
name(.) = 'option'
name(.) = 'optgroup'
)
and not(@disabled)
) or (
(
name(.) = 'input' or
(name(.) = 'input' and @type != 'hidden') or
name(.) = 'button' or
name(.) = 'select' or
name(.) = 'textarea' or
name(.) = 'keygen'
)
and not (@disabled or ancestor::fieldset[@disabled])
) or (
name(.) = 'option' and not(
@disabled or ancestor::optgroup[@disabled]
)
)
''')
# FIXME: in the second half, add "and is not a descendant of that
# fieldset element's first legend element child, if any."
# FIXME: ... or "li elements that are children of menu elements,
# and that have a child element that defines a command, if the first
# such element's Disabled State facet is false (not disabled)".
# FIXME: after ancestor::fieldset[@disabled], add "and is not a
# descendant of that fieldset element's first legend element child,
# if any."

0 comments on commit 1c12e2a

Please sign in to comment.