mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 09:48:11 +00:00
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.
This commit is contained in:
parent
64ba289cfb
commit
bc15144972
7 changed files with 80 additions and 71 deletions
|
@ -295,62 +295,4 @@ String Element::inner_html() const
|
||||||
return builder.to_string();
|
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.
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,21 +83,10 @@ public:
|
||||||
String inner_html() const;
|
String inner_html() const;
|
||||||
void set_inner_html(StringView);
|
void set_inner_html(StringView);
|
||||||
|
|
||||||
virtual bool is_editable() const final;
|
|
||||||
String content_editable() const;
|
|
||||||
void set_content_editable(const String&);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RefPtr<LayoutNode> create_layout_node(const CSS::StyleProperties* parent_style) override;
|
RefPtr<LayoutNode> create_layout_node(const CSS::StyleProperties* parent_style) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class ContentEditableState {
|
|
||||||
True,
|
|
||||||
False,
|
|
||||||
Inherit,
|
|
||||||
};
|
|
||||||
ContentEditableState content_editable_state() const;
|
|
||||||
|
|
||||||
Attribute* find_attribute(const FlyString& name);
|
Attribute* find_attribute(const FlyString& name);
|
||||||
const Attribute* find_attribute(const FlyString& name) const;
|
const Attribute* find_attribute(const FlyString& name) const;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,5 @@ interface Element : Node {
|
||||||
attribute DOMString innerHTML;
|
attribute DOMString innerHTML;
|
||||||
[Reflect] attribute DOMString id;
|
[Reflect] attribute DOMString id;
|
||||||
[Reflect=class] attribute DOMString className;
|
[Reflect=class] attribute DOMString className;
|
||||||
|
|
||||||
attribute DOMString contentEditable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,19 @@ public:
|
||||||
|
|
||||||
String title() const { return attribute(HTML::AttributeNames::title); }
|
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:
|
private:
|
||||||
virtual bool is_html_element() const final { return true; }
|
virtual bool is_html_element() const final { return true; }
|
||||||
|
|
||||||
|
enum class ContentEditableState {
|
||||||
|
True,
|
||||||
|
False,
|
||||||
|
Inherit,
|
||||||
|
};
|
||||||
|
ContentEditableState content_editable_state() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,6 @@ interface HTMLElement : Element {
|
||||||
[Reflect] attribute DOMString title;
|
[Reflect] attribute DOMString title;
|
||||||
[Reflect] attribute DOMString lang;
|
[Reflect] attribute DOMString lang;
|
||||||
|
|
||||||
|
attribute DOMString contentEditable;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
9
Libraries/LibWeb/Tests/Elements/HTML/HTMLElement.js
Normal file
9
Libraries/LibWeb/Tests/Elements/HTML/HTMLElement.js
Normal file
|
@ -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");
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue