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; }; }