Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LibWeb/HTML: Extract dialog show_modal() into its own algorithm #3407

Merged
merged 1 commit into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 50 additions & 42 deletions Libraries/LibWeb/HTML/HTMLDialogElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,80 +150,88 @@ WebIDL::ExceptionOr<void> HTMLDialogElement::show()
// https://html.spec.whatwg.org/multipage/interactive-elements.html#dom-dialog-showmodal
WebIDL::ExceptionOr<void> HTMLDialogElement::show_modal()
{
// 1. If this has an open attribute and is modal of this is true, then return.
if (has_attribute(AttributeNames::open) && m_is_modal)
// The showModal() method steps are to show a modal dialog given this.
return show_a_modal_dialog(*this);
}

WebIDL::ExceptionOr<void> HTMLDialogElement::show_a_modal_dialog(HTMLDialogElement& subject)
{
// To show a modal dialog given a dialog element subject:
auto& realm = subject.realm();

// 1. If subject has an open attribute and is modal of subject is true, then return.
if (subject.has_attribute(AttributeNames::open) && subject.m_is_modal)
return {};

// 2. If this has an open attribute, then throw an "InvalidStateError" DOMException.
if (has_attribute(AttributeNames::open))
return WebIDL::InvalidStateError::create(realm(), "Dialog already open"_string);
// 2. If subject has an open attribute, then throw an "InvalidStateError" DOMException.
if (subject.has_attribute(AttributeNames::open))
return WebIDL::InvalidStateError::create(realm, "Dialog already open"_string);

// 3. If this's node document is not fully active, then throw an "InvalidStateError" DOMException.
if (!document().is_fully_active())
return WebIDL::InvalidStateError::create(realm(), "Document is not fully active"_string);
// 3. If subject's node document is not fully active, then throw an "InvalidStateError" DOMException.
if (!subject.document().is_fully_active())
return WebIDL::InvalidStateError::create(realm, "Document is not fully active"_string);

// 4. If this is not connected, then throw an "InvalidStateError" DOMException.
if (!is_connected())
return WebIDL::InvalidStateError::create(realm(), "Dialog not connected"_string);
// 4. If subject is not connected, then throw an "InvalidStateError" DOMException.
if (!subject.is_connected())
return WebIDL::InvalidStateError::create(realm, "Dialog not connected"_string);

// 5. If this is in the popover showing state, then throw an "InvalidStateError" DOMException.
if (popover_visibility_state() == PopoverVisibilityState::Showing)
return WebIDL::InvalidStateError::create(realm(), "Dialog already open as popover"_string);
// 5. If subject is in the popover showing state, then throw an "InvalidStateError" DOMException.
if (subject.popover_visibility_state() == PopoverVisibilityState::Showing)
return WebIDL::InvalidStateError::create(realm, "Dialog already open as popover"_string);

// 6. If the result of firing an event named beforetoggle, using ToggleEvent,
// with the cancelable attribute initialized to true, the oldState attribute initialized to "closed",
// and the newState attribute initialized to "open" at this is false, then return.
// and the newState attribute initialized to "open" at subject is false, then return.
ToggleEventInit event_init {};
event_init.cancelable = true;
event_init.old_state = "closed"_string;
event_init.new_state = "open"_string;

auto beforetoggle_result = dispatch_event(ToggleEvent::create(realm(), HTML::EventNames::beforetoggle, move(event_init)));
auto beforetoggle_result = subject.dispatch_event(ToggleEvent::create(realm, EventNames::beforetoggle, move(event_init)));
if (!beforetoggle_result)
return {};

// 7. If this has an open attribute, then return.
if (has_attribute(AttributeNames::open))
// 7. If subject has an open attribute, then return.
if (subject.has_attribute(AttributeNames::open))
return {};

// 8. If this is not connected, then return.
if (!is_connected())
// 8. If subject is not connected, then return.
if (!subject.is_connected())
return {};

// 9. If this is in the popover showing state, then return.
if (popover_visibility_state() == PopoverVisibilityState::Showing)
// 9. If subject is in the popover showing state, then return.
if (subject.popover_visibility_state() == PopoverVisibilityState::Showing)
return {};

// 10. Queue a dialog toggle event task given subject, "closed", and "open".
queue_a_dialog_toggle_event_task("closed"_string, "open"_string);
subject.queue_a_dialog_toggle_event_task("closed"_string, "open"_string);

// 11. Add an open attribute to this, whose value is the empty string.
TRY(set_attribute(AttributeNames::open, {}));
// 11. Add an open attribute to subject, whose value is the empty string.
TRY(subject.set_attribute(AttributeNames::open, {}));

// 12. Set is modal of this to true.
m_is_modal = true;
// 12. Set is modal of subject to true.
subject.m_is_modal = true;

// FIXME: 13. Assert: this's node document's open dialogs list does not contain this.
// FIXME: 14. Add this to this's node document's open dialogs list.
// FIXME: 15. Let this's node document be blocked by the modal dialog this.
// FIXME: 13. Assert: subject's node document's open dialogs list does not contain subject.
// FIXME: 14. Add subject to subject's node document's open dialogs list.
// FIXME: 15. Let subject's node document be blocked by the modal dialog subject.

// 16. If this's node document's top layer does not already contain this, then add an element to the top layer given this.
if (!document().top_layer_elements().contains(*this))
document().add_an_element_to_the_top_layer(*this);
// 16. If subject's node document's top layer does not already contain subject, then add an element to the top layer given subject.
if (!subject.document().top_layer_elements().contains(subject))
subject.document().add_an_element_to_the_top_layer(subject);

// 17. Set the dialog close watcher with this.
set_close_watcher();

// FIXME: 18. Set this's previously focused element to the focused element.
// 17. Set the dialog close watcher with subject.
subject.set_close_watcher();

// FIXME: 19. Let document be this's node document.
// FIXME: 20. Let hideUntil be the result of running topmost popover ancestor given this, document's showing hint popover list, null, and false.
// FIXME: 21. If hideUntil is null, then set hideUntil to the result of running topmost popover ancestor given this, document's showing auto popover list, null, and false.
// FIXME: 18. Set subject's previously focused element to the focused element.
// FIXME: 19. Let document be subject's node document.
// FIXME: 20. Let hideUntil be the result of running topmost popover ancestor given subject, document's showing hint popover list, null, and false.
// FIXME: 21. If hideUntil is null, then set hideUntil to the result of running topmost popover ancestor given subject, document's showing auto popover list, null, and false.
// FIXME: 22. If hideUntil is null, then set hideUntil to document.
// FIXME: 23. Run hide all popovers until given hideUntil, false, and true.

// 24. Run the dialog focusing steps given this.
run_dialog_focusing_steps();
// 24. Run the dialog focusing steps given subject.
subject.run_dialog_focusing_steps();

return {};
}
Expand Down
2 changes: 2 additions & 0 deletions Libraries/LibWeb/HTML/HTMLDialogElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class HTMLDialogElement final : public HTMLElement {
String return_value() const;
void set_return_value(String);

static WebIDL::ExceptionOr<void> show_a_modal_dialog(HTMLDialogElement&);

WebIDL::ExceptionOr<void> show();
WebIDL::ExceptionOr<void> show_modal();
void close(Optional<String> return_value);
Expand Down
Loading