Browse files

Implement :enabled/:disabled per the HTML5 spec. (Almost, see #6)

  • Loading branch information...
1 parent 3d8fd09 commit 1c12e2aa0b57984f8889fb8de617d5461eb88221 @SimonSapin SimonSapin committed Apr 20, 2012
Showing with 39 additions and 26 deletions.
  1. +18 −16 cssselect/tests.py
  2. +21 −10 cssselect/xpath.py
View
34 cssselect/tests.py
@@ -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']
@@ -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']
@@ -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)
@@ -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">
View
31 cssselect/xpath.py
@@ -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]
)
@@ -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.