From 4f19deb13be71182f1c7971b226a4dd2de07ee8d Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 16 Feb 2022 09:55:13 -0500 Subject: [PATCH] LibWeb: Implement reverse lookup to labels from their labelable nodes This enables, for example, clicking on the check box, dragging the mouse over to the label, releasing the mouse to act as a click on the check box. This was implemented for labels / labelable nodes with the "for" attribute already. This implements the same for labelable nodes that are inside the label. --- Base/res/html/misc/checkbox.html | 23 +++++++++++-- Userland/Libraries/LibWeb/Layout/Label.cpp | 39 +++++++++++++--------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/Base/res/html/misc/checkbox.html b/Base/res/html/misc/checkbox.html index 9264dcc4887..a4126f5742a 100644 --- a/Base/res/html/misc/checkbox.html +++ b/Base/res/html/misc/checkbox.html @@ -1,12 +1,29 @@ - -

+    
+    

+
+    
+    

+
     
 
diff --git a/Userland/Libraries/LibWeb/Layout/Label.cpp b/Userland/Libraries/LibWeb/Layout/Label.cpp
index 07e5578d14b..10d7a419730 100644
--- a/Userland/Libraries/LibWeb/Layout/Label.cpp
+++ b/Userland/Libraries/LibWeb/Layout/Label.cpp
@@ -89,28 +89,35 @@ bool Label::is_associated_label_hovered(LabelableNode& control)
     return false;
 }
 
+// https://html.spec.whatwg.org/multipage/forms.html#labeled-control
 Label* Label::label_for_control_node(LabelableNode& control)
 {
-    Label* label = nullptr;
-
     if (!control.document().layout_node())
-        return label;
+        return nullptr;
 
-    String id = control.dom_node().attribute(HTML::AttributeNames::id);
-    if (id.is_empty())
-        return label;
+    // 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 (auto id = control.dom_node().attribute(HTML::AttributeNames::id); !id.is_empty()) {
+        Label* label = nullptr;
 
-    control.document().layout_node()->for_each_in_inclusive_subtree_of_type