Forráskód Böngészése

LibWeb: Implement the Element.contentEditable IDL attribute

Andreas Kling 5 éve
szülő
commit
7811cf3520

+ 5 - 0
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;
+}
+
 }

+ 52 - 7
Libraries/LibWeb/DOM/Element.cpp

@@ -33,6 +33,7 @@
 #include <LibWeb/DOM/Element.h>
 #include <LibWeb/DOM/Text.h>
 #include <LibWeb/Dump.h>
+#include <LibWeb/HTML/Parser/HTMLDocumentParser.h>
 #include <LibWeb/Layout/LayoutBlock.h>
 #include <LibWeb/Layout/LayoutInline.h>
 #include <LibWeb/Layout/LayoutListItem.h>
@@ -41,7 +42,6 @@
 #include <LibWeb/Layout/LayoutTableRow.h>
 #include <LibWeb/Layout/LayoutTableRowGroup.h>
 #include <LibWeb/Layout/LayoutTreeBuilder.h>
-#include <LibWeb/HTML/Parser/HTMLDocumentParser.h>
 
 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<Attribute>&& 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.
 }
 
 }

+ 10 - 0
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<Attribute>&&);
 
@@ -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<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;
 

+ 1 - 0
Libraries/LibWeb/DOM/Element.idl

@@ -9,5 +9,6 @@ interface Element : Node {
     [Reflect] attribute DOMString id;
     [Reflect=class] attribute DOMString className;
 
+    attribute DOMString contentEditable;
 }