ParentNode.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /*
  2. * Copyright (c) 2020, Luke Wilde <lukew@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibWeb/CSS/Parser/Parser.h>
  7. #include <LibWeb/CSS/SelectorEngine.h>
  8. #include <LibWeb/DOM/HTMLCollection.h>
  9. #include <LibWeb/DOM/ParentNode.h>
  10. #include <LibWeb/Dump.h>
  11. namespace Web::DOM {
  12. ExceptionOr<RefPtr<Element>> ParentNode::query_selector(StringView selector_text)
  13. {
  14. auto maybe_selectors = parse_selector(CSS::ParsingContext(*this), selector_text);
  15. if (!maybe_selectors.has_value())
  16. return DOM::SyntaxError::create("Failed to parse selector");
  17. auto selectors = maybe_selectors.value();
  18. RefPtr<Element> result;
  19. for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
  20. for (auto& selector : selectors) {
  21. if (SelectorEngine::matches(selector, element)) {
  22. result = element;
  23. return IterationDecision::Break;
  24. }
  25. }
  26. return IterationDecision::Continue;
  27. });
  28. return result;
  29. }
  30. ExceptionOr<NonnullRefPtrVector<Element>> ParentNode::query_selector_all(StringView selector_text)
  31. {
  32. auto maybe_selectors = parse_selector(CSS::ParsingContext(*this), selector_text);
  33. if (!maybe_selectors.has_value())
  34. return DOM::SyntaxError::create("Failed to parse selector");
  35. auto selectors = maybe_selectors.value();
  36. NonnullRefPtrVector<Element> elements;
  37. for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
  38. for (auto& selector : selectors) {
  39. if (SelectorEngine::matches(selector, element)) {
  40. elements.append(element);
  41. }
  42. }
  43. return IterationDecision::Continue;
  44. });
  45. return elements;
  46. }
  47. RefPtr<Element> ParentNode::first_element_child()
  48. {
  49. return first_child_of_type<Element>();
  50. }
  51. RefPtr<Element> ParentNode::last_element_child()
  52. {
  53. return last_child_of_type<Element>();
  54. }
  55. // https://dom.spec.whatwg.org/#dom-parentnode-childelementcount
  56. u32 ParentNode::child_element_count() const
  57. {
  58. u32 count = 0;
  59. for (auto* child = first_child(); child; child = child->next_sibling()) {
  60. if (is<Element>(child))
  61. ++count;
  62. }
  63. return count;
  64. }
  65. // https://dom.spec.whatwg.org/#dom-parentnode-children
  66. NonnullRefPtr<HTMLCollection> ParentNode::children()
  67. {
  68. // The children getter steps are to return an HTMLCollection collection rooted at this matching only element children.
  69. // FIXME: This should return the same HTMLCollection object every time,
  70. // but that would cause a reference cycle since HTMLCollection refs the root.
  71. return HTMLCollection::create(*this, [this](Element const& element) {
  72. return is_parent_of(element);
  73. });
  74. }
  75. }