LibWeb: Implement Element.toggleAttribute()

This commit is contained in:
Elisée Maurer 2022-03-30 16:50:44 +02:00 committed by Andreas Kling
parent 1ec3847acd
commit 34db0dab41
Notes: sideshowbarker 2024-07-17 16:29:01 +09:00
3 changed files with 50 additions and 0 deletions

View File

@ -172,6 +172,54 @@ bool Element::has_attribute(const FlyString& name) const
return m_attributes->get_attribute(name) != nullptr;
}
// https://dom.spec.whatwg.org/#dom-element-toggleattribute
DOM::ExceptionOr<bool> Element::toggle_attribute(FlyString const& name, Optional<bool> force)
{
// 1. If qualifiedName does not match the Name production in XML, then throw an "InvalidCharacterError" DOMException.
// FIXME: Proper name validation
if (name.is_empty())
return InvalidCharacterError::create("Attribute name must not be empty");
// 2. If this is in the HTML namespace and its node document is an HTML document, then set qualifiedName to qualifiedName in ASCII lowercase.
// FIXME: Handle the second condition, assume it is an HTML document for now.
bool insert_as_lowercase = namespace_uri() == Namespace::HTML;
// 3. Let attribute be the first attribute in thiss attribute list whose qualified name is qualifiedName, and null otherwise.
auto* attribute = m_attributes->get_attribute(name);
// 4. If attribute is null, then:
if (!attribute) {
// 1. If force is not given or is true, create an attribute whose local name is qualifiedName, value is the empty string, and node document is thiss node document, then append this attribute to this, and then return true.
if (!force.has_value() || force.value()) {
auto new_attribute = Attribute::create(document(), insert_as_lowercase ? name.to_lowercase() : name, "");
m_attributes->append_attribute(new_attribute);
parse_attribute(new_attribute->local_name(), "");
// FIXME: Invalidate less.
document().invalidate_style();
return true;
}
// 2. Return false.
return false;
}
// 5. Otherwise, if force is not given or is false, remove an attribute given qualifiedName and this, and then return false.
if (!force.has_value() || !force.value()) {
m_attributes->remove_attribute(name);
did_remove_attribute(name);
// FIXME: Invalidate less.
document().invalidate_style();
}
// 6. Return true.
return true;
}
// https://dom.spec.whatwg.org/#dom-element-getattributenames
Vector<String> Element::get_attribute_names() const
{

View File

@ -57,6 +57,7 @@ public:
ExceptionOr<void> set_attribute(const FlyString& name, const String& value);
ExceptionOr<void> set_attribute_ns(FlyString const& namespace_, FlyString const& qualified_name, String const& value);
void remove_attribute(const FlyString& name);
DOM::ExceptionOr<bool> toggle_attribute(FlyString const& name, Optional<bool> force);
size_t attribute_list_size() const { return m_attributes->length(); }
NonnullRefPtr<NamedNodeMap> const& attributes() const { return m_attributes; }
Vector<String> get_attribute_names() const;

View File

@ -16,6 +16,7 @@ interface Element : Node {
undefined setAttribute(DOMString qualifiedName, DOMString value);
[CEReactions] undefined setAttributeNS(DOMString? namespace , DOMString qualifiedName , DOMString value);
undefined removeAttribute(DOMString qualifiedName);
[CEReactions] boolean toggleAttribute(DOMString qualifiedName, optional boolean force);
boolean hasAttribute(DOMString qualifiedName);
boolean hasAttributes();
[SameObject] readonly attribute NamedNodeMap attributes;