mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-25 14:05:15 +00:00
Before this change, we were going through the chain of base classes for each IDL interface object and having them set the prototype to their prototype. Instead of doing that, reorder things so that we set the right prototype immediately in Foo::initialize(), and then don't bother in all the base class overrides. This knocks off a ~1% profile item on Speedometer 3.
87 lines
3 KiB
C++
87 lines
3 KiB
C++
/*
|
|
* Copyright (c) 2020, the SerenityOS developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibWeb/Bindings/HTMLLabelElementPrototype.h>
|
|
#include <LibWeb/DOM/Document.h>
|
|
#include <LibWeb/HTML/FormAssociatedElement.h>
|
|
#include <LibWeb/HTML/HTMLLabelElement.h>
|
|
#include <LibWeb/Layout/Label.h>
|
|
|
|
namespace Web::HTML {
|
|
|
|
GC_DEFINE_ALLOCATOR(HTMLLabelElement);
|
|
|
|
HTMLLabelElement::HTMLLabelElement(DOM::Document& document, DOM::QualifiedName qualified_name)
|
|
: HTMLElement(document, move(qualified_name))
|
|
{
|
|
}
|
|
|
|
HTMLLabelElement::~HTMLLabelElement() = default;
|
|
|
|
void HTMLLabelElement::initialize(JS::Realm& realm)
|
|
{
|
|
WEB_SET_PROTOTYPE_FOR_INTERFACE(HTMLLabelElement);
|
|
Base::initialize(realm);
|
|
}
|
|
|
|
GC::Ptr<Layout::Node> HTMLLabelElement::create_layout_node(GC::Ref<CSS::ComputedProperties> style)
|
|
{
|
|
return heap().allocate<Layout::Label>(document(), this, move(style));
|
|
}
|
|
|
|
// https://html.spec.whatwg.org/multipage/forms.html#labeled-control
|
|
GC::Ptr<HTMLElement> HTMLLabelElement::control() const
|
|
{
|
|
GC::Ptr<HTMLElement> control;
|
|
|
|
// The for attribute may be specified to indicate a form control with which the caption is
|
|
// to be associated. If the attribute is specified, the attribute's value must be the ID of
|
|
// a labelable element in the same tree as the label element. If the attribute is specified
|
|
// and there is an element in the tree whose ID is equal to the value of the for attribute,
|
|
// and the first such element in tree order is a labelable element, then that element is the
|
|
// label element's labeled control.
|
|
if (for_().has_value()) {
|
|
root().for_each_in_inclusive_subtree_of_type<HTMLElement>([&](auto& element) {
|
|
if (element.id() == *for_() && element.is_labelable()) {
|
|
control = &const_cast<HTMLElement&>(element);
|
|
return TraversalDecision::Break;
|
|
}
|
|
return TraversalDecision::Continue;
|
|
});
|
|
return control;
|
|
}
|
|
|
|
// If the for attribute is not specified, but the label element has a labelable element descendant,
|
|
// then the first such descendant in tree order is the label element's labeled control.
|
|
for_each_in_subtree_of_type<HTMLElement>([&](auto& element) {
|
|
if (element.is_labelable()) {
|
|
control = &const_cast<HTMLElement&>(element);
|
|
return TraversalDecision::Break;
|
|
}
|
|
return TraversalDecision::Continue;
|
|
});
|
|
|
|
return control;
|
|
}
|
|
|
|
// https://html.spec.whatwg.org/multipage/forms.html#dom-label-form
|
|
GC::Ptr<HTMLFormElement> HTMLLabelElement::form() const
|
|
{
|
|
auto labeled_control = control();
|
|
|
|
// 1. If the label element has no labeled control, then return null.
|
|
if (!labeled_control)
|
|
return {};
|
|
|
|
// 2. If the label element's labeled control is not a form-associated element, then return null.
|
|
if (!is<FormAssociatedElement>(*labeled_control))
|
|
return {};
|
|
|
|
// 3. Return the label element's labeled control's form owner (which can still be null).
|
|
return dynamic_cast<FormAssociatedElement*>(labeled_control.ptr())->form();
|
|
}
|
|
|
|
}
|