diff options
author | Luke <luke.wilde@live.co.uk> | 2020-08-03 02:57:28 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-08-03 12:47:58 +0200 |
commit | bc151449722629cb64d495e3780852d9d0769ab7 (patch) | |
tree | a02b4595e68717c03ddfc8df78f3194c90b7e15e /Libraries/LibWeb | |
parent | 64ba289cfbdc5f205d5a54b8c9d28da7040ab054 (diff) | |
download | serenity-bc151449722629cb64d495e3780852d9d0769ab7.zip |
LibWeb: Move contentEditable from Element to HTMLElement
HTMLElement is the only interface that includes ElementContentEditable
in the HTML specification. This makes sense, as Element is also a base
class for elements in other specifications such as SVG,
which definitely shouldn't be editable.
Also adds a test for the attribute based on what Andreas did in the
video that added it.
Diffstat (limited to 'Libraries/LibWeb')
-rw-r--r-- | Libraries/LibWeb/DOM/Element.cpp | 58 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Element.h | 11 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Element.idl | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLElement.cpp | 58 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLElement.h | 11 | ||||
-rw-r--r-- | Libraries/LibWeb/HTML/HTMLElement.idl | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Tests/Elements/HTML/HTMLElement.js | 9 |
7 files changed, 80 insertions, 71 deletions
diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 0ec5b8df3a..0a7f4b473d 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -295,62 +295,4 @@ String Element::inner_html() const return builder.to_string(); } -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 ContentEditableState::True; - // "false" maps to the "false" state. - if (contenteditable.equals_ignoring_case("false")) - return ContentEditableState::False; - // "inherit", an invalid value, and a missing value all map to the "inherit" state. - return ContentEditableState::Inherit; -} - -bool Element::is_editable() const -{ - 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 c30eae1e9b..9b2b18adc4 100644 --- a/Libraries/LibWeb/DOM/Element.h +++ b/Libraries/LibWeb/DOM/Element.h @@ -83,21 +83,10 @@ public: String inner_html() const; void set_inner_html(StringView); - virtual bool is_editable() const final; - String content_editable() const; - void set_content_editable(const String&); - protected: RefPtr<LayoutNode> 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 33f8fe6dca..e698841c84 100644 --- a/Libraries/LibWeb/DOM/Element.idl +++ b/Libraries/LibWeb/DOM/Element.idl @@ -8,7 +8,5 @@ interface Element : Node { attribute DOMString innerHTML; [Reflect] attribute DOMString id; [Reflect=class] attribute DOMString className; - - attribute DOMString contentEditable; } diff --git a/Libraries/LibWeb/HTML/HTMLElement.cpp b/Libraries/LibWeb/HTML/HTMLElement.cpp index 757574eb90..ca7e0c7129 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -37,4 +37,62 @@ HTMLElement::~HTMLElement() { } +HTMLElement::ContentEditableState HTMLElement::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 ContentEditableState::True; + // "false" maps to the "false" state. + if (contenteditable.equals_ignoring_case("false")) + return ContentEditableState::False; + // "inherit", an invalid value, and a missing value all map to the "inherit" state. + return ContentEditableState::Inherit; +} + +bool HTMLElement::is_editable() const +{ + 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 HTMLElement::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 HTMLElement::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/HTML/HTMLElement.h b/Libraries/LibWeb/HTML/HTMLElement.h index b148fde16a..cd1da7bca3 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.h +++ b/Libraries/LibWeb/HTML/HTMLElement.h @@ -39,8 +39,19 @@ public: String title() const { return attribute(HTML::AttributeNames::title); } + virtual bool is_editable() const final; + String content_editable() const; + void set_content_editable(const String&); + private: virtual bool is_html_element() const final { return true; } + + enum class ContentEditableState { + True, + False, + Inherit, + }; + ContentEditableState content_editable_state() const; }; } diff --git a/Libraries/LibWeb/HTML/HTMLElement.idl b/Libraries/LibWeb/HTML/HTMLElement.idl index c47721cd8a..9991a76b78 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.idl +++ b/Libraries/LibWeb/HTML/HTMLElement.idl @@ -3,4 +3,6 @@ interface HTMLElement : Element { [Reflect] attribute DOMString title; [Reflect] attribute DOMString lang; + attribute DOMString contentEditable; + } diff --git a/Libraries/LibWeb/Tests/Elements/HTML/HTMLElement.js b/Libraries/LibWeb/Tests/Elements/HTML/HTMLElement.js new file mode 100644 index 0000000000..8e113e4865 --- /dev/null +++ b/Libraries/LibWeb/Tests/Elements/HTML/HTMLElement.js @@ -0,0 +1,9 @@ +loadPage("file:///res/html/misc/welcome.html") + +afterInitialPageLoad(() => { + test("contentEditable attribute", () => { + expect(document.body.contentEditable).toBe("inherit"); + expect(document.firstChild.nextSibling.nodeName).toBe("html"); + expect(document.firstChild.nextSibling.contentEditable).toBe("true"); + }); +}); |