mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-23 04:55:15 +00:00
LibWeb: Implement popover's close watcher
Auto popovers now correctly establish a close watcher when shown. This means popovers now correctly close with an escape key press. Also correctly hide open popovers when removed from the document.
This commit is contained in:
parent
09a55e56ee
commit
0a02eb639d
Notes:
github-actions[bot]
2024-12-17 03:56:49 +00:00
Author: https://github.com/lukewarlow Commit: https://github.com/LadybirdBrowser/ladybird/commit/0a02eb639d6 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/344
2 changed files with 36 additions and 4 deletions
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibJS/Runtime/NativeFunction.h>
|
||||
#include <LibWeb/ARIA/Roles.h>
|
||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||
#include <LibWeb/Bindings/HTMLElementPrototype.h>
|
||||
|
@ -17,6 +18,7 @@
|
|||
#include <LibWeb/DOM/Position.h>
|
||||
#include <LibWeb/DOM/ShadowRoot.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/HTML/CloseWatcher.h>
|
||||
#include <LibWeb/HTML/CustomElements/CustomElementDefinition.h>
|
||||
#include <LibWeb/HTML/ElementInternals.h>
|
||||
#include <LibWeb/HTML/EventHandler.h>
|
||||
|
@ -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<void> 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<WebIDL::CallbackType>(*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<void> 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
|
||||
{
|
||||
|
|
|
@ -116,6 +116,8 @@ public:
|
|||
WebIDL::ExceptionOr<void> set_popover(Optional<String> value);
|
||||
Optional<String> 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<ToggleTaskTracker> m_popover_toggle_task_tracker;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/popover.html#popover-close-watcher
|
||||
GC::Ptr<CloseWatcher> m_popover_close_watcher;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue