/* * Copyright (c) 2023, Shannon Booth * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include namespace Web::DOM { JS_DEFINE_ALLOCATOR(HTMLFormControlsCollection); JS::NonnullGCPtr HTMLFormControlsCollection::create(ParentNode& root, Scope scope, Function filter) { return root.heap().allocate(root.realm(), root, scope, move(filter)); } HTMLFormControlsCollection::HTMLFormControlsCollection(ParentNode& root, Scope scope, Function filter) : HTMLCollection(root, scope, move(filter)) { } HTMLFormControlsCollection::~HTMLFormControlsCollection() = default; void HTMLFormControlsCollection::initialize(JS::Realm& realm) { Base::initialize(realm); set_prototype(&Bindings::ensure_web_prototype(realm, "HTMLFormControlsCollection"_fly_string)); } // https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-htmlformcontrolscollection-nameditem Variant> HTMLFormControlsCollection::named_item_or_radio_node_list(FlyString const& name) const { // 1. If name is the empty string, return null and stop the algorithm. if (name.is_empty()) return {}; auto const deprecated_name = name.to_deprecated_fly_string(); // 2. If, at the time the method is called, there is exactly one node in the collection that has either an id attribute or a name attribute equal to name, then return that node and stop the algorithm. // 3. Otherwise, if there are no nodes in the collection that have either an id attribute or a name attribute equal to name, then return null and stop the algorithm. Element* matching_element = nullptr; bool multiple_matching = false; auto collection = collect_matching_elements(); for (auto const& element : collection) { if (element->deprecated_attribute(HTML::AttributeNames::id) != deprecated_name && element->name() != deprecated_name) continue; if (matching_element) { multiple_matching = true; break; } matching_element = element; } if (!matching_element) return {}; if (!multiple_matching) return matching_element; // 4. Otherwise, create a new RadioNodeList object representing a live view of the HTMLFormControlsCollection object, further filtered so that the only nodes in the // RadioNodeList object are those that have either an id attribute or a name attribute equal to name. The nodes in the RadioNodeList object must be sorted in tree // order. Return that RadioNodeList object. return JS::make_handle(RadioNodeList::create(realm(), root(), LiveNodeList::Scope::Descendants, [deprecated_name](Node const& node) { if (!is(node)) return false; auto const& element = verify_cast(node); return element.deprecated_attribute(HTML::AttributeNames::id) == deprecated_name || element.name() == deprecated_name; })); } }