LibWeb: Implement document.designMode

Setting this attribute to "on" makes the entire document editable.
This commit is contained in:
Tim Ledbetter 2024-02-10 15:23:19 +00:00 committed by Andreas Kling
parent c9fb3e07d2
commit 774119bb57
Notes: sideshowbarker 2024-07-17 06:29:49 +09:00
5 changed files with 73 additions and 0 deletions

View File

@ -0,0 +1,6 @@
document.designMode initial value: off
document.designMode after setting to "invalid": off
document.designMode after setting to "on": on
document.designMode after setting to "off": off
document.designMode after setting to "ON": on
document.designMode after setting to "OFF": off

View File

@ -0,0 +1,17 @@
<script src="../include.js"></script>
<script>
function setDesignMode(value) {
document.designMode = value;
println(`document.designMode after setting to "${value}": ${document.designMode}`);
}
test(() => {
println(`document.designMode initial value: ${document.designMode}`);
setDesignMode("invalid");
setDesignMode("on");
setDesignMode("off");
setDesignMode("ON");
setDesignMode("OFF");
});
</script>

View File

@ -3735,6 +3735,47 @@ void Document::remove_form_associated_element_with_form_attribute(HTML::FormAsso
});
}
void Document::set_design_mode_enabled_state(bool design_mode_enabled)
{
m_design_mode_enabled = design_mode_enabled;
set_editable(design_mode_enabled);
}
// https://html.spec.whatwg.org/multipage/interaction.html#making-entire-documents-editable:-the-designmode-idl-attribute
String Document::design_mode() const
{
// The designMode getter steps are to return "on" if this's design mode enabled is true; otherwise "off".
return design_mode_enabled_state() ? "on"_string : "off"_string;
}
WebIDL::ExceptionOr<void> Document::set_design_mode(String const& design_mode)
{
// 1. Let value be the given value, converted to ASCII lowercase.
auto value = MUST(design_mode.to_lowercase());
// 2. If value is "on" and this's design mode enabled is false, then:
if (value == "on"sv && !m_design_mode_enabled) {
// 1. Set this's design mode enabled to true.
set_design_mode_enabled_state(true);
// 2. Reset this's active range's start and end boundary points to be at the start of this.
if (auto selection = get_selection(); selection) {
if (auto active_range = selection->range(); active_range) {
TRY(active_range->set_start(*this, 0));
TRY(active_range->set_end(*this, 0));
update_layout();
}
}
// 3. Run the focusing steps for this's document element, if non-null.
if (auto* document_element = this->document_element(); document_element)
HTML::run_focusing_steps(document_element);
}
// 3. If value is "off", then set this's design mode enabled to false.
else if (value == "off"sv) {
set_design_mode_enabled_state(false);
}
return {};
}
// https://drafts.csswg.org/cssom-view/#dom-document-elementfrompoint
Element const* Document::element_from_point(double x, double y)
{

View File

@ -561,6 +561,11 @@ public:
void add_form_associated_element_with_form_attribute(HTML::FormAssociatedElement&);
void remove_form_associated_element_with_form_attribute(HTML::FormAssociatedElement&);
bool design_mode_enabled_state() const { return m_design_mode_enabled; }
void set_design_mode_enabled_state(bool);
String design_mode() const;
WebIDL::ExceptionOr<void> set_design_mode(String const&);
Element const* element_from_point(double x, double y);
void set_needs_to_resolve_paint_only_properties() { m_needs_to_resolve_paint_only_properties = true; }
@ -789,6 +794,8 @@ private:
Vector<HTML::FormAssociatedElement*> m_form_associated_elements_with_form_attribute;
bool m_design_mode_enabled { false };
bool m_needs_to_resolve_paint_only_properties { true };
};

View File

@ -114,6 +114,8 @@ interface Document : Node {
Selection? getSelection();
[CEReactions] attribute DOMString designMode;
// https://www.w3.org/TR/web-animations-1/#extensions-to-the-document-interface
readonly attribute DocumentTimeline timeline;