Skip to content

Commit

Permalink
Merge pull request #301 from wojtekmach/wm-checked
Browse files Browse the repository at this point in the history
Support :checked pseudo-class
  • Loading branch information
philss authored Aug 26, 2020
2 parents 13412d4 + 205d7ca commit 4c0b898
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ Here you find all the [CSS selectors](https://www.w3.org/TR/selectors/#selectors
| E:nth-last-of-type(n) | an E element, the n-th child of its type among its siblings, counting from bottom to up |
| 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.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 @@ -187,6 +187,10 @@ defmodule Floki.Selector do
Enum.all?(pseudo_class.value, &(!Selector.match?(html_node, &1, tree)))
end

defp pseudo_class_match?(html_node, %{name: "checked"}, _tree) do
PseudoClass.match_checked?(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
18 changes: 18 additions & 0 deletions lib/floki/selector/pseudo_class.ex
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@ defmodule Floki.Selector.PseudoClass do
end
end

def match_checked?(%{type: "input"} = html_node) do
case List.keyfind(html_node.attributes, "checked", 0) do
{"checked", _} -> true
_ -> false
end
end

def match_checked?(%{type: "option"} = html_node) do
case List.keyfind(html_node.attributes, "selected", 0) do
{"selected", _} -> true
_ -> false
end
end

def match_checked?(_) 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
24 changes: 24 additions & 0 deletions test/floki_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,30 @@ defmodule FlokiTest do
assert Floki.find(html, ":fl-contains(' podcast')") == expected
end

test "checked pseudo-class" do
doc =
document!(
html_body(~s"""
<input type="checkbox" name="1" checked>
<input type="checkbox" name="2" checked="checked">
<input type="checkbox" name="3">
<input type="radio" name="4" checked>
<input type="radio" name="5">
<select>
<option selected>6</option>
<option>7</option>
</select>
""")
)

assert [
{"input", [{"type", "checkbox"}, {"name", "1"}, {"checked", _}], []},
{"input", [{"type", "checkbox"}, {"name", "2"}, {"checked", _}], []},
{"input", [{"type", "radio"}, {"name", "4"}, {"checked", _}], []},
{"option", [{"selected", _}], ["6"]}
] = Floki.find(doc, ":checked")
end

# Floki.find/2 - XML and invalid HTML

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

0 comments on commit 4c0b898

Please sign in to comment.