diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 78d2f1785a..5f6a29fdd6 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -495,4 +495,9 @@ const String& Document::compat_mode() const return css1_compat; } +bool Document::is_editable() const +{ + return m_editable; +} + } diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 6c8b08b47d..0ec5b8df3a 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,6 @@ #include #include #include -#include namespace Web::DOM { @@ -90,6 +90,11 @@ void Element::set_attribute(const FlyString& name, const String& value) parse_attribute(name, value); } +void Element::remove_attribute(const FlyString& name) +{ + m_attributes.remove_first_matching([&](auto& attribute) { return attribute.name() == name; }); +} + void Element::set_attributes(Vector&& attributes) { m_attributes = move(attributes); @@ -290,22 +295,62 @@ String Element::inner_html() const return builder.to_string(); } -bool Element::is_editable() const +Element::ContentEditableState Element::content_editable_state() const { auto contenteditable = attribute(HTML::AttributeNames::contenteditable); // "true" and the empty string map to the "true" state. if ((!contenteditable.is_null() && contenteditable.is_empty()) || contenteditable.equals_ignoring_case("true")) - return true; + return ContentEditableState::True; // "false" maps to the "false" state. if (contenteditable.equals_ignoring_case("false")) - return false; + return ContentEditableState::False; // "inherit", an invalid value, and a missing value all map to the "inherit" state. - return parent() && parent()->is_editable(); + return ContentEditableState::Inherit; } -bool Document::is_editable() const +bool Element::is_editable() const { - return m_editable; + switch (content_editable_state()) { + case ContentEditableState::True: + return true; + case ContentEditableState::False: + return false; + case ContentEditableState::Inherit: + return parent() && parent()->is_editable(); + default: + ASSERT_NOT_REACHED(); + } +} + +String Element::content_editable() const +{ + switch (content_editable_state()) { + case ContentEditableState::True: + return "true"; + case ContentEditableState::False: + return "false"; + case ContentEditableState::Inherit: + return "inherit"; + default: + ASSERT_NOT_REACHED(); + } +} + +void Element::set_content_editable(const String& content_editable) +{ + if (content_editable.equals_ignoring_case("inherit")) { + remove_attribute(HTML::AttributeNames::contenteditable); + return; + } + if (content_editable.equals_ignoring_case("true")) { + set_attribute(HTML::AttributeNames::contenteditable, "true"); + return; + } + if (content_editable.equals_ignoring_case("false")) { + set_attribute(HTML::AttributeNames::contenteditable, "false"); + return; + } + // FIXME: otherwise the attribute setter must throw a "SyntaxError" DOMException. } } diff --git a/Libraries/LibWeb/DOM/Element.h b/Libraries/LibWeb/DOM/Element.h index 937db4382b..c30eae1e9b 100644 --- a/Libraries/LibWeb/DOM/Element.h +++ b/Libraries/LibWeb/DOM/Element.h @@ -53,6 +53,7 @@ public: String attribute(const FlyString& name) const; String get_attribute(const FlyString& name) const { return attribute(name); } void set_attribute(const FlyString& name, const String& value); + void remove_attribute(const FlyString& name); void set_attributes(Vector&&); @@ -83,11 +84,20 @@ public: void set_inner_html(StringView); virtual bool is_editable() const final; + String content_editable() const; + void set_content_editable(const String&); protected: RefPtr create_layout_node(const CSS::StyleProperties* parent_style) override; private: + enum class ContentEditableState { + True, + False, + Inherit, + }; + ContentEditableState content_editable_state() const; + Attribute* find_attribute(const FlyString& name); const Attribute* find_attribute(const FlyString& name) const; diff --git a/Libraries/LibWeb/DOM/Element.idl b/Libraries/LibWeb/DOM/Element.idl index b9495a23c8..33f8fe6dca 100644 --- a/Libraries/LibWeb/DOM/Element.idl +++ b/Libraries/LibWeb/DOM/Element.idl @@ -9,5 +9,6 @@ interface Element : Node { [Reflect] attribute DOMString id; [Reflect=class] attribute DOMString className; + attribute DOMString contentEditable; }