diff --git a/Libraries/LibWeb/HTML/HTMLElement.cpp b/Libraries/LibWeb/HTML/HTMLElement.cpp
index 35a412fdcb0..4189adf3015 100644
--- a/Libraries/LibWeb/HTML/HTMLElement.cpp
+++ b/Libraries/LibWeb/HTML/HTMLElement.cpp
@@ -5,6 +5,7 @@
*/
#include
+#include
#include
#include
#include
@@ -17,6 +18,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -65,6 +67,7 @@ void HTMLElement::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_labels);
visitor.visit(m_attached_internals);
visitor.visit(m_popover_invoker);
+ visitor.visit(m_popover_close_watcher);
}
// https://html.spec.whatwg.org/multipage/dom.html#dom-dir
@@ -1051,9 +1054,20 @@ WebIDL::ExceptionOr HTMLElement::show_popover(ThrowExceptions throw_except
// FIXME: 11.5. If originalType is not equal to the value of element's popover attribute, then throw a "InvalidStateError" DOMException.
// FIXME: 11.6. If the result of running check popover validity given element, false, throwExceptions, and document is false, then run cleanupShowingFlag and return.
// FIXME: 11.7. If the result of running topmost auto popover on document is null, then set shouldRestoreFocus to true.
- // FIXME: 11.8. Set element's popover close watcher to the result of establishing a close watcher given element's relevant global object, with:
+ // 11.8. Set element's popover close watcher to the result of establishing a close watcher given element's relevant global object, with:
+ m_popover_close_watcher = CloseWatcher::establish(*document.window());
// - cancelAction being to return true.
+ // We simply don't add an event listener for the cancel action.
// - closeAction being to hide a popover given element, true, true, and false.
+ auto close_callback_function = JS::NativeFunction::create(
+ realm(), [this](JS::VM&) {
+ MUST(hide_popover(FocusPreviousElement::Yes, FireEvents::Yes, ThrowExceptions::No));
+
+ return JS::js_undefined();
+ },
+ 0, "", &realm());
+ auto close_callback = realm().heap().allocate(*close_callback_function, realm());
+ m_popover_close_watcher->add_event_listener_without_options(HTML::EventNames::close, DOM::IDLEventListener::create(realm(), close_callback));
}
// FIXME: 12. Set element's previously focused element to null.
@@ -1116,9 +1130,13 @@ WebIDL::ExceptionOr HTMLElement::hide_popover(FocusPreviousElement, FireEv
// 6.1. If nestedHide is false, then set element's popover showing or hiding to false.
if (nested_hide)
m_popover_showing_or_hiding = false;
- // FIXME: 6.2. If element's popover close watcher is not null, then:
- // FIXME: 6.2.1. Destroy element's popover close watcher.
- // FIXME: 6.2.2. Set element's popover close watcher to null.
+ // 6.2. If element's popover close watcher is not null, then:
+ if (m_popover_close_watcher) {
+ // 6.2.1. Destroy element's popover close watcher.
+ m_popover_close_watcher->destroy();
+ // 6.2.2. Set element's popover close watcher to null.
+ m_popover_close_watcher = nullptr;
+ }
};
// 7. If element's popover attribute is in the auto state, then:
@@ -1275,6 +1293,15 @@ void HTMLElement::did_lose_focus()
document().editing_host_manager()->set_active_contenteditable_element(nullptr);
}
+void HTMLElement::removed_from(Node* old_parent)
+{
+ Element::removed_from(old_parent);
+
+ // If removedNode's popover attribute is not in the no popover state, then run the hide popover algorithm given removedNode, false, false, and false.
+ if (popover().has_value())
+ MUST(hide_popover(FocusPreviousElement::No, FireEvents::No, ThrowExceptions::No));
+}
+
// https://html.spec.whatwg.org/multipage/interaction.html#dom-accesskeylabel
String HTMLElement::access_key_label() const
{
diff --git a/Libraries/LibWeb/HTML/HTMLElement.h b/Libraries/LibWeb/HTML/HTMLElement.h
index c44bef4327e..bb85e985ff9 100644
--- a/Libraries/LibWeb/HTML/HTMLElement.h
+++ b/Libraries/LibWeb/HTML/HTMLElement.h
@@ -116,6 +116,8 @@ public:
WebIDL::ExceptionOr set_popover(Optional value);
Optional popover() const;
+ virtual void removed_from(Node*) override;
+
enum class PopoverVisibilityState {
Hidden,
Showing,
@@ -181,6 +183,9 @@ private:
// https://html.spec.whatwg.org/multipage/popover.html#the-popover-attribute:toggle-task-tracker
Optional m_popover_toggle_task_tracker;
+
+ // https://html.spec.whatwg.org/multipage/popover.html#popover-close-watcher
+ GC::Ptr m_popover_close_watcher;
};
}