Skip to content

Commit

Permalink
Merge pull request #309 from hashrocket/disable-pseudo-selector
Browse files Browse the repository at this point in the history
Add :disabled pseudo selector
  • Loading branch information
philss authored Oct 5, 2020
2 parents a5e9efb + 2f4d8ec commit 97eb44c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ Here you find all the [CSS selectors](https://www.w3.org/TR/selectors/#selectors
| E:first-of-type | an E element, first child of its type among its siblings |
| E:last-of-type | an E element, last child of its type among its siblings |
| E:checked | An E element (checkbox, radio, or option) that is checked |
| E:disabled | An E element (button, input, select, textarea, or option) that is disabled |
| E.warning | an E element whose class is "warning" |
| E#myid | an E element with ID equal to "myid" |
| E:not(s) | an E element that does not match simple selector s |
Expand Down
4 changes: 4 additions & 0 deletions lib/floki/selector.ex
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ defmodule Floki.Selector do
PseudoClass.match_checked?(html_node)
end

defp pseudo_class_match?(html_node, %{name: "disabled"}, _tree) do
PseudoClass.match_disabled?(html_node)
end

defp pseudo_class_match?(html_node, pseudo_class = %{name: "fl-contains"}, tree) do
PseudoClass.match_contains?(tree, html_node, pseudo_class)
end
Expand Down
13 changes: 13 additions & 0 deletions lib/floki/selector/pseudo_class.ex
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,19 @@ defmodule Floki.Selector.PseudoClass do
false
end

@disableable_html_nodes ~w[button input select option textarea]

def match_disabled?(%{type: type} = html_node) when type in @disableable_html_nodes do
case List.keyfind(html_node.attributes, "disabled", 0) do
{"disabled", _} -> true
_ -> false
end
end

def match_disabled?(_html_node) do
false
end

defp node_position(ids, %HTMLNode{node_id: node_id}) do
{_node_id, position} = Enum.find(ids, fn {id, _} -> id == node_id end)

Expand Down
42 changes: 42 additions & 0 deletions test/floki_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,48 @@ defmodule FlokiTest do
] = Floki.find(doc, ":checked")
end

test "disabled pseudo-class" do
doc =
document!(
html_body(~s"""
<button disabled="disabled">button 1</button>
<button disabled>button 2</button>
<button>button 3</button>
<input type="text" name="text 1" disabled="disabled">
<input type="text" name="text 2" disabled>
<input type="text" name="text 3">
<select name="select 1" disabled="disabled"><option value="option 1">Option 1</option></select>
<select name="select 2" disabled><option value="option 2">Option 2</option></select>
<select name="select 3"><option value="option 3">Option 3</option></select>
<select name="select 4"><option value="option 4" disabled="disabled">Option 4</option></select>
<select name="select 5"><option value="option 5" disabled>Option 5</option></select>
<select name="select 6"><option value="option 6">Option 6</option></select>
<textarea name="text area 1" disabled="disabled">Text Area 1</textarea>
<textarea name="text area 2" disabled>Text Area 2</textarea>
<textarea name="text area 3">Text Area 3</textarea>
""")
)

assert [
{"button", [{"disabled", _}], ["button 1"]},
{"button", [{"disabled", _}], ["button 2"]},
{"input", [{"type", "text"}, {"name", "text 1"}, {"disabled", _}], []},
{"input", [{"type", "text"}, {"name", "text 2"}, {"disabled", _}], []},
{"select", [{"name", "select 1"}, {"disabled", _}],
[{"option", [{"value", "option 1"}], ["Option 1"]}]},
{"select", [{"name", "select 2"}, {"disabled", _}],
[{"option", [{"value", "option 2"}], ["Option 2"]}]},
{"option", [{"value", "option 4"}, {"disabled", _}], ["Option 4"]},
{"option", [{"value", "option 5"}, {"disabled", _}], ["Option 5"]},
{"textarea", [{"name", "text area 1"}, {"disabled", _}], ["Text Area 1"]},
{"textarea", [{"name", "text area 2"}, {"disabled", _}], ["Text Area 2"]}
] = Floki.find(doc, ":disabled")
end

# Floki.find/2 - XML and invalid HTML

test "get elements inside a XML structure" do
Expand Down

0 comments on commit 97eb44c

Please sign in to comment.