SVGElement.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
  3. * Copyright (c) 2023, Preston Taylor <95388976+PrestonLTaylor@users.noreply.github.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <LibWeb/Bindings/ExceptionOrUtils.h>
  8. #include <LibWeb/Bindings/Intrinsics.h>
  9. #include <LibWeb/DOM/Document.h>
  10. #include <LibWeb/DOM/ShadowRoot.h>
  11. #include <LibWeb/HTML/DOMStringMap.h>
  12. #include <LibWeb/SVG/SVGElement.h>
  13. #include <LibWeb/SVG/SVGUseElement.h>
  14. namespace Web::SVG {
  15. SVGElement::SVGElement(DOM::Document& document, DOM::QualifiedName qualified_name)
  16. : Element(document, move(qualified_name))
  17. {
  18. }
  19. void SVGElement::initialize(JS::Realm& realm)
  20. {
  21. Base::initialize(realm);
  22. WEB_SET_PROTOTYPE_FOR_INTERFACE(SVGElement);
  23. m_dataset = HTML::DOMStringMap::create(*this);
  24. }
  25. void SVGElement::visit_edges(Cell::Visitor& visitor)
  26. {
  27. Base::visit_edges(visitor);
  28. visitor.visit(m_dataset);
  29. }
  30. void SVGElement::attribute_changed(FlyString const& name, Optional<String> const& value)
  31. {
  32. Base::attribute_changed(name, value);
  33. update_use_elements_that_reference_this();
  34. }
  35. void SVGElement::inserted()
  36. {
  37. Base::inserted();
  38. update_use_elements_that_reference_this();
  39. }
  40. void SVGElement::children_changed()
  41. {
  42. Base::children_changed();
  43. update_use_elements_that_reference_this();
  44. }
  45. void SVGElement::update_use_elements_that_reference_this()
  46. {
  47. if (is<SVGUseElement>(this)
  48. // If this element is in a shadow root, it already represents a clone and is not itself referenced.
  49. || is<DOM::ShadowRoot>(this->root())
  50. // If this does not have an id it cannot be referenced, no point in searching the entire DOM tree.
  51. || !id().has_value()
  52. // An unconnected node cannot have valid references.
  53. // This also prevents searches for elements that are in the process of being constructed - as clones.
  54. || !this->is_connected()
  55. // Each use element already listens for the completely_loaded event and then clones its referece,
  56. // we do not have to also clone it in the process of initial DOM building.
  57. || !document().is_completely_loaded()) {
  58. return;
  59. }
  60. document().for_each_in_subtree_of_type<SVGUseElement>([this](SVGUseElement& use_element) {
  61. use_element.svg_element_changed(*this);
  62. return IterationDecision::Continue;
  63. });
  64. }
  65. void SVGElement::removed_from(Node* parent)
  66. {
  67. Base::removed_from(parent);
  68. remove_from_use_element_that_reference_this();
  69. }
  70. void SVGElement::remove_from_use_element_that_reference_this()
  71. {
  72. if (is<SVGUseElement>(this) || !id().has_value()) {
  73. return;
  74. }
  75. document().for_each_in_subtree_of_type<SVGUseElement>([this](SVGUseElement& use_element) {
  76. use_element.svg_element_removed(*this);
  77. return IterationDecision::Continue;
  78. });
  79. }
  80. void SVGElement::focus()
  81. {
  82. dbgln("(STUBBED) SVGElement::focus()");
  83. }
  84. void SVGElement::blur()
  85. {
  86. dbgln("(STUBBED) SVGElement::blur()");
  87. }
  88. }