Bug 38688 - Support control attribute of HTMLLabelElement
Summary: Support control attribute of HTMLLabelElement
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Forms (show other bugs)
Version: 528+ (Nightly build)
Hardware: PC OS X 10.5
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks: HTML5Forms 38713
  Show dependency treegraph
 
Reported: 2010-05-06 14:03 PDT by Yael
Modified: 2010-05-12 06:06 PDT (History)
5 users (show)

See Also:


Attachments
Patch adding support for the control attribute. (12.51 KB, patch)
2010-05-06 14:08 PDT, Yael
no flags Details | Formatted Diff | Diff
Attempt to fix Chromium build (14.41 KB, patch)
2010-05-06 16:26 PDT, Yael
no flags Details | Formatted Diff | Diff
Another try to fix the Chromium build (14.58 KB, patch)
2010-05-06 18:27 PDT, Yael
no flags Details | Formatted Diff | Diff
Another try to fix the Chromium build (14.80 KB, patch)
2010-05-07 04:36 PDT, Yael
no flags Details | Formatted Diff | Diff
Maybe this time it will compile? (14.60 KB, patch)
2010-05-07 05:51 PDT, Yael
darin: review-
Details | Formatted Diff | Diff
Patch for addressing review comments. (21.57 KB, patch)
2010-05-10 15:47 PDT, Yael
darin: review-
Details | Formatted Diff | Diff
Patch addressing comment #13. (24.55 KB, patch)
2010-05-10 20:00 PDT, Yael
darin: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Yael 2010-05-06 14:03:01 PDT
From http://dev.w3.org/html5/spec/Overview.html#the-label-element, the control attribute should return a reference to the control associated with the label, but only if it is a labelable control.
Comment 1 Yael 2010-05-06 14:08:00 PDT
Created attachment 55296 [details]
Patch adding support for the control attribute.
Comment 2 WebKit Review Bot 2010-05-06 15:37:11 PDT
Attachment 55296 [details] did not build on chromium:
Build output: http://webkit-commit-queue.appspot.com/results/2168027
Comment 3 Yael 2010-05-06 16:26:45 PDT
Created attachment 55316 [details]
Attempt to fix Chromium build
Comment 4 WebKit Review Bot 2010-05-06 17:45:45 PDT
Attachment 55316 [details] did not build on chromium:
Build output: http://webkit-commit-queue.appspot.com/results/2174030
Comment 5 Yael 2010-05-06 18:27:29 PDT
Created attachment 55332 [details]
Another try to fix the Chromium build
Comment 6 WebKit Review Bot 2010-05-06 20:05:32 PDT
Attachment 55332 [details] did not build on chromium:
Build output: http://webkit-commit-queue.appspot.com/results/2177026
Comment 7 Yael 2010-05-07 04:36:05 PDT
Created attachment 55360 [details]
Another try to fix the Chromium build
Comment 8 WebKit Review Bot 2010-05-07 05:01:40 PDT
Attachment 55360 [details] did not build on chromium:
Build output: http://webkit-commit-queue.appspot.com/results/2232047
Comment 9 Yael 2010-05-07 05:51:37 PDT
Created attachment 55369 [details]
Maybe this time it will compile?
Comment 10 Yael 2010-05-07 14:33:27 PDT
With this change, the following form controls cannot be associated with a label: fieldset, legend, optgroup and option.
Comment 11 Darin Adler 2010-05-09 19:44:06 PDT
Comment on attachment 55369 [details]
Maybe this time it will compile?

Looks good. But the multiple things you are doing need to be tested.

You changed the label element code so that it won't label other types of form control. So you need a test that shows that behavior change.

Your comment says that you "cleaned up" correspondingControl, but that's not what you did. You fixed a bug in it!

I'd also like to see the code refactored so the two branches of the function shared the code to check isFormControlElement rather than repeating the code twice. You could use the traverseElement code to make it even easier to share code.

> +bool HTMLFormControlElement::isControlLabelable() const

How about just "isLabelable" for this?
> +    // FIXME: Add meterTag and outputTag to the list once we support them.
> +    return hasTagName(buttonTag) || hasTagName(inputTag) || hasTagName(keygenTag)
> +#if ENABLE(PROGRESS_TAG)
> +    || hasTagName(progressTag)
> +#endif
> +    || hasTagName(selectTag) || hasTagName(textareaTag);

You should indent the continuation lines 4 spaces in.

> -HTMLElement* HTMLLabelElement::correspondingControl()
> +HTMLFormControlElement* HTMLLabelElement::correspondingControl() const

Does this really need to be a const member function? The need to const_cast in here is ugly.

> +        // the control must be "labelable form-associated element".

I see the "labelable" part here, but I don't see the "form-associated" part.

> +PassRefPtr<HTMLElement> HTMLLabelElement::control() const
> +{
> +    return correspondingControl();
> +}

There is no reason to return a PassRefPtr here. It should just be a raw pointer.

> -    HTMLElement* correspondingControl();
> +    HTMLFormControlElement* correspondingControl() const;

> +    PassRefPtr<HTMLElement> control() const;

I suggest renaming our correspondingControl function to control rather than adding a second function. And I see no reason to make this a const member function.

>      interface HTMLLabelElement : HTMLElement {
>          readonly attribute HTMLFormElement form;
> -        attribute [ConvertNullToNullString] DOMString accessKey;
> -        attribute [ConvertNullToNullString] DOMString htmlFor;
> +                 attribute [ConvertNullToNullString] DOMString accessKey;
> +                 attribute [ConvertNullToNullString] DOMString htmlFor;
> +        readonly attribute HTMLElement control;
>      };

I don't think we need to mimic the indenting of the HTML5 specification. I'd prefer to just have things indented one tab stop and not try to line things up.

Fix a few things and put it up for review again. Looks good.
Comment 12 Yael 2010-05-10 15:47:00 PDT
Created attachment 55614 [details]
Patch for addressing review comments.

This patch addresses the comments and adds more tests, including a manual test for testing that the label properly propagates focus, activation and hover to the correct form control element, while ignoring form control elements which are not labelable.
Comment 13 Darin Adler 2010-05-10 16:51:11 PDT
Comment on attachment 55614 [details]
Patch for addressing review comments.

> +static HTMLFormControlElement* nodeAsLabelableFormControl(Node* node)
> +{
> +    if (!node)
> +        return 0;
> +
> +    if (node->isHTMLElement() && static_cast<HTMLElement*>(node)->isFormControlElement()) {
> +        HTMLFormControlElement* formControlElement = static_cast<HTMLFormControlElement*>(node);
> +        if (formControlElement->isLabelable())
> +            return formControlElement;
> +    }
> +
> +    return 0;
> +}

I think this would read even better if it used early returns exclusively.

> +        // Search the children of the label element for a form element.

This searches the descendants of the label element, not just the children.

> +            if (HTMLFormControlElement* formControlElement = nodeAsLabelableFormControl(node))
> +                return formControlElement;

As I said before, I see how this checks for "labelable" elements, but not "form-associated". Maybe that's the same thing as checking isFormControlElement?

> +class HTMLFormControlElement;    
> +
>  class HTMLLabelElement : public HTMLElement {
>  public:
>      HTMLLabelElement(const QualifiedName&, Document*);
> @@ -46,7 +48,7 @@ public:
>      // Overridden to either click() or focus() the corresponding control.
>      virtual void defaultEventHandler(Event*);
>  
> -    HTMLElement* correspondingControl();
> +    HTMLElement* control();

Did you mean to change the type here to HTMLFormControlElement? If not, then why the forward declaration?

> +        readonly attribute HTMLElement control;

Was the type here supposed to be HTMLFormControlElement?

I don't entirely understand why the manual test you made is a manual test. Automated tests can both activate and focus, although perhaps for hover you need a manual test.

I'm going to say review- mainly because of the unused forward declaration in HTMLLabelElement.h that clearly seems to be in error.
Comment 14 Yael 2010-05-10 17:41:20 PDT
(In reply to comment #13)
> As I said before, I see how this checks for "labelable" elements, but not "form-associated". Maybe that's the same thing as checking isFormControlElement?
Sorry, I forgot to mention that form-associated elements are defined here http://dev.w3.org/html5/spec/Overview.html#form-associated-element, and are a super-set of labelable elements.
Comment 15 Yael 2010-05-10 20:00:33 PDT
Created attachment 55650 [details]
Patch addressing comment #13.
Comment 16 Darin Adler 2010-05-11 09:46:18 PDT
Comment on attachment 55650 [details]
Patch addressing comment #13.

> -HTMLElement* HTMLLabelElement::correspondingControl()
> +HTMLElement* HTMLLabelElement::control()

Why isn't the return type of this HTMLFormControlElement*? There are a lot of places in this patch that use HTMLElement* but instead should use HTMLFormControlElement.

> +        // Search the children and descendants of the label element for a form element.
> +        // per http://dev.w3.org/html5/spec/Overview.html#the-label-element
> +        // the form element must be "labelable form-associated element".

I think the comment should just leave out the link and say something more like this:

    // HTML5 says to search our descendants for the first labelable form-associated element
    // in document order.

OK as-is, though.
Comment 17 Yael 2010-05-11 10:18:56 PDT
(In reply to comment #16)
> (From update of attachment 55650 [details])
> > -HTMLElement* HTMLLabelElement::correspondingControl()
> > +HTMLElement* HTMLLabelElement::control()
> 
> Why isn't the return type of this HTMLFormControlElement*? There are a lot of places in this patch that use HTMLElement* but instead should use HTMLFormControlElement.
I was going to do that for correspondingControl(), but since control() is defined by the HTML5 spec to be of type HTMLElement, I thought that I cannot do that.
Comment 18 Darin Adler 2010-05-11 10:30:43 PDT
(In reply to comment #17)
> (In reply to comment #16)
> > (From update of attachment 55650 [details] [details])
> > > -HTMLElement* HTMLLabelElement::correspondingControl()
> > > +HTMLElement* HTMLLabelElement::control()
> > 
> > Why isn't the return type of this HTMLFormControlElement*? There are a lot of places in this patch that use HTMLElement* but instead should use HTMLFormControlElement.
> I was going to do that for correspondingControl(), but since control() is defined by the HTML5 spec to be of type HTMLElement, I thought that I cannot do that.

We can do it.

There are three angles on this:

    1) The DOM implementation itself can always use a more-specific return type. The binding mechanism supports that. And this gives us more type checking and in some cases can even lead to better code in the DOM implementation, so is probably worth doing.

    2) The JavaScript binding can't see the return type of a function, so it also doesn't matter exactly what object type is specified in the IDL file. So we probably could get away with using this type in the IDL file too.

    3) The reason HTML5 doesn't specify this is that HTMLFormControlElement is an implementation detail of WebKit and generally should not be exposed. It's an abstract base class. I do think, however, that it may be something you can see by looking at the prototype chains of form control elements. This has nothing to do with the return type of the function, though.
Comment 19 Yael 2010-05-12 06:06:31 PDT
Landed in r59228  <http://trac.webkit.org/changeset/59228>